diff options
Diffstat (limited to 'drivers')
629 files changed, 18398 insertions, 7926 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 88e42abf5d88..0df8fcb687d6 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
| @@ -61,6 +61,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file); | |||
| 61 | static int acpi_ac_add(struct acpi_device *device); | 61 | static int acpi_ac_add(struct acpi_device *device); |
| 62 | static int acpi_ac_remove(struct acpi_device *device, int type); | 62 | static int acpi_ac_remove(struct acpi_device *device, int type); |
| 63 | static int acpi_ac_resume(struct acpi_device *device); | 63 | static int acpi_ac_resume(struct acpi_device *device); |
| 64 | static void acpi_ac_notify(struct acpi_device *device, u32 event); | ||
| 64 | 65 | ||
| 65 | static const struct acpi_device_id ac_device_ids[] = { | 66 | static const struct acpi_device_id ac_device_ids[] = { |
| 66 | {"ACPI0003", 0}, | 67 | {"ACPI0003", 0}, |
| @@ -72,10 +73,12 @@ static struct acpi_driver acpi_ac_driver = { | |||
| 72 | .name = "ac", | 73 | .name = "ac", |
| 73 | .class = ACPI_AC_CLASS, | 74 | .class = ACPI_AC_CLASS, |
| 74 | .ids = ac_device_ids, | 75 | .ids = ac_device_ids, |
| 76 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 75 | .ops = { | 77 | .ops = { |
| 76 | .add = acpi_ac_add, | 78 | .add = acpi_ac_add, |
| 77 | .remove = acpi_ac_remove, | 79 | .remove = acpi_ac_remove, |
| 78 | .resume = acpi_ac_resume, | 80 | .resume = acpi_ac_resume, |
| 81 | .notify = acpi_ac_notify, | ||
| 79 | }, | 82 | }, |
| 80 | }; | 83 | }; |
| 81 | 84 | ||
| @@ -220,16 +223,14 @@ static int acpi_ac_remove_fs(struct acpi_device *device) | |||
| 220 | Driver Model | 223 | Driver Model |
| 221 | -------------------------------------------------------------------------- */ | 224 | -------------------------------------------------------------------------- */ |
| 222 | 225 | ||
| 223 | static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | 226 | static void acpi_ac_notify(struct acpi_device *device, u32 event) |
| 224 | { | 227 | { |
| 225 | struct acpi_ac *ac = data; | 228 | struct acpi_ac *ac = acpi_driver_data(device); |
| 226 | struct acpi_device *device = NULL; | ||
| 227 | 229 | ||
| 228 | 230 | ||
| 229 | if (!ac) | 231 | if (!ac) |
| 230 | return; | 232 | return; |
| 231 | 233 | ||
| 232 | device = ac->device; | ||
| 233 | switch (event) { | 234 | switch (event) { |
| 234 | default: | 235 | default: |
| 235 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 236 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -253,7 +254,6 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) | |||
| 253 | static int acpi_ac_add(struct acpi_device *device) | 254 | static int acpi_ac_add(struct acpi_device *device) |
| 254 | { | 255 | { |
| 255 | int result = 0; | 256 | int result = 0; |
| 256 | acpi_status status = AE_OK; | ||
| 257 | struct acpi_ac *ac = NULL; | 257 | struct acpi_ac *ac = NULL; |
| 258 | 258 | ||
| 259 | 259 | ||
| @@ -286,13 +286,6 @@ static int acpi_ac_add(struct acpi_device *device) | |||
| 286 | ac->charger.get_property = get_ac_property; | 286 | ac->charger.get_property = get_ac_property; |
| 287 | power_supply_register(&ac->device->dev, &ac->charger); | 287 | power_supply_register(&ac->device->dev, &ac->charger); |
| 288 | #endif | 288 | #endif |
| 289 | status = acpi_install_notify_handler(device->handle, | ||
| 290 | ACPI_ALL_NOTIFY, acpi_ac_notify, | ||
| 291 | ac); | ||
| 292 | if (ACPI_FAILURE(status)) { | ||
| 293 | result = -ENODEV; | ||
| 294 | goto end; | ||
| 295 | } | ||
| 296 | 289 | ||
| 297 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 290 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", |
| 298 | acpi_device_name(device), acpi_device_bid(device), | 291 | acpi_device_name(device), acpi_device_bid(device), |
| @@ -328,7 +321,6 @@ static int acpi_ac_resume(struct acpi_device *device) | |||
| 328 | 321 | ||
| 329 | static int acpi_ac_remove(struct acpi_device *device, int type) | 322 | static int acpi_ac_remove(struct acpi_device *device, int type) |
| 330 | { | 323 | { |
| 331 | acpi_status status = AE_OK; | ||
| 332 | struct acpi_ac *ac = NULL; | 324 | struct acpi_ac *ac = NULL; |
| 333 | 325 | ||
| 334 | 326 | ||
| @@ -337,8 +329,6 @@ static int acpi_ac_remove(struct acpi_device *device, int type) | |||
| 337 | 329 | ||
| 338 | ac = acpi_driver_data(device); | 330 | ac = acpi_driver_data(device); |
| 339 | 331 | ||
| 340 | status = acpi_remove_notify_handler(device->handle, | ||
| 341 | ACPI_ALL_NOTIFY, acpi_ac_notify); | ||
| 342 | #ifdef CONFIG_ACPI_SYSFS_POWER | 332 | #ifdef CONFIG_ACPI_SYSFS_POWER |
| 343 | if (ac->charger.dev) | 333 | if (ac->charger.dev) |
| 344 | power_supply_unregister(&ac->charger); | 334 | power_supply_unregister(&ac->charger); |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b0de6312919a..58b4517ce712 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -796,13 +796,12 @@ static void acpi_battery_remove_fs(struct acpi_device *device) | |||
| 796 | Driver Interface | 796 | Driver Interface |
| 797 | -------------------------------------------------------------------------- */ | 797 | -------------------------------------------------------------------------- */ |
| 798 | 798 | ||
| 799 | static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | 799 | static void acpi_battery_notify(struct acpi_device *device, u32 event) |
| 800 | { | 800 | { |
| 801 | struct acpi_battery *battery = data; | 801 | struct acpi_battery *battery = acpi_driver_data(device); |
| 802 | struct acpi_device *device; | 802 | |
| 803 | if (!battery) | 803 | if (!battery) |
| 804 | return; | 804 | return; |
| 805 | device = battery->device; | ||
| 806 | acpi_battery_update(battery); | 805 | acpi_battery_update(battery); |
| 807 | acpi_bus_generate_proc_event(device, event, | 806 | acpi_bus_generate_proc_event(device, event, |
| 808 | acpi_battery_present(battery)); | 807 | acpi_battery_present(battery)); |
| @@ -819,7 +818,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 819 | static int acpi_battery_add(struct acpi_device *device) | 818 | static int acpi_battery_add(struct acpi_device *device) |
| 820 | { | 819 | { |
| 821 | int result = 0; | 820 | int result = 0; |
| 822 | acpi_status status = 0; | ||
| 823 | struct acpi_battery *battery = NULL; | 821 | struct acpi_battery *battery = NULL; |
| 824 | if (!device) | 822 | if (!device) |
| 825 | return -EINVAL; | 823 | return -EINVAL; |
| @@ -834,22 +832,12 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 834 | acpi_battery_update(battery); | 832 | acpi_battery_update(battery); |
| 835 | #ifdef CONFIG_ACPI_PROCFS_POWER | 833 | #ifdef CONFIG_ACPI_PROCFS_POWER |
| 836 | result = acpi_battery_add_fs(device); | 834 | result = acpi_battery_add_fs(device); |
| 837 | if (result) | ||
| 838 | goto end; | ||
| 839 | #endif | 835 | #endif |
| 840 | status = acpi_install_notify_handler(device->handle, | 836 | if (!result) { |
| 841 | ACPI_ALL_NOTIFY, | 837 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", |
| 842 | acpi_battery_notify, battery); | 838 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), |
| 843 | if (ACPI_FAILURE(status)) { | 839 | device->status.battery_present ? "present" : "absent"); |
| 844 | ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); | 840 | } else { |
| 845 | result = -ENODEV; | ||
| 846 | goto end; | ||
| 847 | } | ||
| 848 | printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", | ||
| 849 | ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), | ||
| 850 | device->status.battery_present ? "present" : "absent"); | ||
| 851 | end: | ||
| 852 | if (result) { | ||
| 853 | #ifdef CONFIG_ACPI_PROCFS_POWER | 841 | #ifdef CONFIG_ACPI_PROCFS_POWER |
| 854 | acpi_battery_remove_fs(device); | 842 | acpi_battery_remove_fs(device); |
| 855 | #endif | 843 | #endif |
| @@ -860,15 +848,11 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 860 | 848 | ||
| 861 | static int acpi_battery_remove(struct acpi_device *device, int type) | 849 | static int acpi_battery_remove(struct acpi_device *device, int type) |
| 862 | { | 850 | { |
| 863 | acpi_status status = 0; | ||
| 864 | struct acpi_battery *battery = NULL; | 851 | struct acpi_battery *battery = NULL; |
| 865 | 852 | ||
| 866 | if (!device || !acpi_driver_data(device)) | 853 | if (!device || !acpi_driver_data(device)) |
| 867 | return -EINVAL; | 854 | return -EINVAL; |
| 868 | battery = acpi_driver_data(device); | 855 | battery = acpi_driver_data(device); |
| 869 | status = acpi_remove_notify_handler(device->handle, | ||
| 870 | ACPI_ALL_NOTIFY, | ||
| 871 | acpi_battery_notify); | ||
| 872 | #ifdef CONFIG_ACPI_PROCFS_POWER | 856 | #ifdef CONFIG_ACPI_PROCFS_POWER |
| 873 | acpi_battery_remove_fs(device); | 857 | acpi_battery_remove_fs(device); |
| 874 | #endif | 858 | #endif |
| @@ -896,10 +880,12 @@ static struct acpi_driver acpi_battery_driver = { | |||
| 896 | .name = "battery", | 880 | .name = "battery", |
| 897 | .class = ACPI_BATTERY_CLASS, | 881 | .class = ACPI_BATTERY_CLASS, |
| 898 | .ids = battery_device_ids, | 882 | .ids = battery_device_ids, |
| 883 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 899 | .ops = { | 884 | .ops = { |
| 900 | .add = acpi_battery_add, | 885 | .add = acpi_battery_add, |
| 901 | .resume = acpi_battery_resume, | 886 | .resume = acpi_battery_resume, |
| 902 | .remove = acpi_battery_remove, | 887 | .remove = acpi_battery_remove, |
| 888 | .notify = acpi_battery_notify, | ||
| 903 | }, | 889 | }, |
| 904 | }; | 890 | }; |
| 905 | 891 | ||
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 09c69806c1fc..f6baa77deefb 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
| @@ -192,6 +192,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { | |||
| 192 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), | 192 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), |
| 193 | }, | 193 | }, |
| 194 | }, | 194 | }, |
| 195 | { | ||
| 196 | .callback = dmi_disable_osi_vista, | ||
| 197 | .ident = "Sony VGN-NS10J_S", | ||
| 198 | .matches = { | ||
| 199 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 200 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), | ||
| 201 | }, | ||
| 202 | }, | ||
| 203 | { | ||
| 204 | .callback = dmi_disable_osi_vista, | ||
| 205 | .ident = "Sony VGN-SR290J", | ||
| 206 | .matches = { | ||
| 207 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 208 | DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), | ||
| 209 | }, | ||
| 210 | }, | ||
| 195 | 211 | ||
| 196 | /* | 212 | /* |
| 197 | * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. | 213 | * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ae862f1798dc..2876fc70c3a9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -450,18 +450,16 @@ int acpi_bus_receive_event(struct acpi_bus_event *event) | |||
| 450 | Notification Handling | 450 | Notification Handling |
| 451 | -------------------------------------------------------------------------- */ | 451 | -------------------------------------------------------------------------- */ |
| 452 | 452 | ||
| 453 | static int | 453 | static void acpi_bus_check_device(acpi_handle handle) |
| 454 | acpi_bus_check_device(struct acpi_device *device, int *status_changed) | ||
| 455 | { | 454 | { |
| 456 | acpi_status status = 0; | 455 | struct acpi_device *device; |
| 456 | acpi_status status; | ||
| 457 | struct acpi_device_status old_status; | 457 | struct acpi_device_status old_status; |
| 458 | 458 | ||
| 459 | 459 | if (acpi_bus_get_device(handle, &device)) | |
| 460 | return; | ||
| 460 | if (!device) | 461 | if (!device) |
| 461 | return -EINVAL; | 462 | return; |
| 462 | |||
| 463 | if (status_changed) | ||
| 464 | *status_changed = 0; | ||
| 465 | 463 | ||
| 466 | old_status = device->status; | 464 | old_status = device->status; |
| 467 | 465 | ||
| @@ -471,22 +469,15 @@ acpi_bus_check_device(struct acpi_device *device, int *status_changed) | |||
| 471 | */ | 469 | */ |
| 472 | if (device->parent && !device->parent->status.present) { | 470 | if (device->parent && !device->parent->status.present) { |
| 473 | device->status = device->parent->status; | 471 | device->status = device->parent->status; |
| 474 | if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { | 472 | return; |
| 475 | if (status_changed) | ||
| 476 | *status_changed = 1; | ||
| 477 | } | ||
| 478 | return 0; | ||
| 479 | } | 473 | } |
| 480 | 474 | ||
| 481 | status = acpi_bus_get_status(device); | 475 | status = acpi_bus_get_status(device); |
| 482 | if (ACPI_FAILURE(status)) | 476 | if (ACPI_FAILURE(status)) |
| 483 | return -ENODEV; | 477 | return; |
| 484 | 478 | ||
| 485 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) | 479 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) |
| 486 | return 0; | 480 | return; |
| 487 | |||
| 488 | if (status_changed) | ||
| 489 | *status_changed = 1; | ||
| 490 | 481 | ||
| 491 | /* | 482 | /* |
| 492 | * Device Insertion/Removal | 483 | * Device Insertion/Removal |
| @@ -498,33 +489,17 @@ acpi_bus_check_device(struct acpi_device *device, int *status_changed) | |||
| 498 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); | 489 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); |
| 499 | /* TBD: Handle device removal */ | 490 | /* TBD: Handle device removal */ |
| 500 | } | 491 | } |
| 501 | |||
| 502 | return 0; | ||
| 503 | } | 492 | } |
| 504 | 493 | ||
| 505 | static int acpi_bus_check_scope(struct acpi_device *device) | 494 | static void acpi_bus_check_scope(acpi_handle handle) |
| 506 | { | 495 | { |
| 507 | int result = 0; | ||
| 508 | int status_changed = 0; | ||
| 509 | |||
| 510 | |||
| 511 | if (!device) | ||
| 512 | return -EINVAL; | ||
| 513 | |||
| 514 | /* Status Change? */ | 496 | /* Status Change? */ |
| 515 | result = acpi_bus_check_device(device, &status_changed); | 497 | acpi_bus_check_device(handle); |
| 516 | if (result) | ||
| 517 | return result; | ||
| 518 | |||
| 519 | if (!status_changed) | ||
| 520 | return 0; | ||
| 521 | 498 | ||
| 522 | /* | 499 | /* |
| 523 | * TBD: Enumerate child devices within this device's scope and | 500 | * TBD: Enumerate child devices within this device's scope and |
| 524 | * run acpi_bus_check_device()'s on them. | 501 | * run acpi_bus_check_device()'s on them. |
| 525 | */ | 502 | */ |
| 526 | |||
| 527 | return 0; | ||
| 528 | } | 503 | } |
| 529 | 504 | ||
| 530 | static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); | 505 | static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); |
| @@ -547,22 +522,19 @@ EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); | |||
| 547 | */ | 522 | */ |
| 548 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | 523 | static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) |
| 549 | { | 524 | { |
| 550 | int result = 0; | ||
| 551 | struct acpi_device *device = NULL; | 525 | struct acpi_device *device = NULL; |
| 526 | struct acpi_driver *driver; | ||
| 527 | |||
| 528 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", | ||
| 529 | type, handle)); | ||
| 552 | 530 | ||
| 553 | blocking_notifier_call_chain(&acpi_bus_notify_list, | 531 | blocking_notifier_call_chain(&acpi_bus_notify_list, |
| 554 | type, (void *)handle); | 532 | type, (void *)handle); |
| 555 | 533 | ||
| 556 | if (acpi_bus_get_device(handle, &device)) | ||
| 557 | return; | ||
| 558 | |||
| 559 | switch (type) { | 534 | switch (type) { |
| 560 | 535 | ||
| 561 | case ACPI_NOTIFY_BUS_CHECK: | 536 | case ACPI_NOTIFY_BUS_CHECK: |
| 562 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 537 | acpi_bus_check_scope(handle); |
| 563 | "Received BUS CHECK notification for device [%s]\n", | ||
| 564 | device->pnp.bus_id)); | ||
| 565 | result = acpi_bus_check_scope(device); | ||
| 566 | /* | 538 | /* |
| 567 | * TBD: We'll need to outsource certain events to non-ACPI | 539 | * TBD: We'll need to outsource certain events to non-ACPI |
| 568 | * drivers via the device manager (device.c). | 540 | * drivers via the device manager (device.c). |
| @@ -570,10 +542,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
| 570 | break; | 542 | break; |
| 571 | 543 | ||
| 572 | case ACPI_NOTIFY_DEVICE_CHECK: | 544 | case ACPI_NOTIFY_DEVICE_CHECK: |
| 573 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 545 | acpi_bus_check_device(handle); |
| 574 | "Received DEVICE CHECK notification for device [%s]\n", | ||
| 575 | device->pnp.bus_id)); | ||
| 576 | result = acpi_bus_check_device(device, NULL); | ||
| 577 | /* | 546 | /* |
| 578 | * TBD: We'll need to outsource certain events to non-ACPI | 547 | * TBD: We'll need to outsource certain events to non-ACPI |
| 579 | * drivers via the device manager (device.c). | 548 | * drivers via the device manager (device.c). |
| @@ -581,44 +550,26 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
| 581 | break; | 550 | break; |
| 582 | 551 | ||
| 583 | case ACPI_NOTIFY_DEVICE_WAKE: | 552 | case ACPI_NOTIFY_DEVICE_WAKE: |
| 584 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 585 | "Received DEVICE WAKE notification for device [%s]\n", | ||
| 586 | device->pnp.bus_id)); | ||
| 587 | /* TBD */ | 553 | /* TBD */ |
| 588 | break; | 554 | break; |
| 589 | 555 | ||
| 590 | case ACPI_NOTIFY_EJECT_REQUEST: | 556 | case ACPI_NOTIFY_EJECT_REQUEST: |
| 591 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 592 | "Received EJECT REQUEST notification for device [%s]\n", | ||
| 593 | device->pnp.bus_id)); | ||
| 594 | /* TBD */ | 557 | /* TBD */ |
| 595 | break; | 558 | break; |
| 596 | 559 | ||
| 597 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | 560 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: |
| 598 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 599 | "Received DEVICE CHECK LIGHT notification for device [%s]\n", | ||
| 600 | device->pnp.bus_id)); | ||
| 601 | /* TBD: Exactly what does 'light' mean? */ | 561 | /* TBD: Exactly what does 'light' mean? */ |
| 602 | break; | 562 | break; |
| 603 | 563 | ||
| 604 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 564 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
| 605 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 606 | "Received FREQUENCY MISMATCH notification for device [%s]\n", | ||
| 607 | device->pnp.bus_id)); | ||
| 608 | /* TBD */ | 565 | /* TBD */ |
| 609 | break; | 566 | break; |
| 610 | 567 | ||
| 611 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 568 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
| 612 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 613 | "Received BUS MODE MISMATCH notification for device [%s]\n", | ||
| 614 | device->pnp.bus_id)); | ||
| 615 | /* TBD */ | 569 | /* TBD */ |
| 616 | break; | 570 | break; |
| 617 | 571 | ||
| 618 | case ACPI_NOTIFY_POWER_FAULT: | 572 | case ACPI_NOTIFY_POWER_FAULT: |
| 619 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 620 | "Received POWER FAULT notification for device [%s]\n", | ||
| 621 | device->pnp.bus_id)); | ||
| 622 | /* TBD */ | 573 | /* TBD */ |
| 623 | break; | 574 | break; |
| 624 | 575 | ||
| @@ -629,7 +580,13 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
| 629 | break; | 580 | break; |
| 630 | } | 581 | } |
| 631 | 582 | ||
| 632 | return; | 583 | acpi_bus_get_device(handle, &device); |
| 584 | if (device) { | ||
| 585 | driver = device->driver; | ||
| 586 | if (driver && driver->ops.notify && | ||
| 587 | (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS)) | ||
| 588 | driver->ops.notify(device, type); | ||
| 589 | } | ||
| 633 | } | 590 | } |
| 634 | 591 | ||
| 635 | /* -------------------------------------------------------------------------- | 592 | /* -------------------------------------------------------------------------- |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 8bd2c2a6884d..a8a5c29958c8 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -140,46 +140,6 @@ struct device *acpi_get_physical_device(acpi_handle handle) | |||
| 140 | 140 | ||
| 141 | EXPORT_SYMBOL(acpi_get_physical_device); | 141 | EXPORT_SYMBOL(acpi_get_physical_device); |
| 142 | 142 | ||
| 143 | /* ToDo: When a PCI bridge is found, return the PCI device behind the bridge | ||
| 144 | * This should work in general, but did not on a Lenovo T61 for the | ||
| 145 | * graphics card. But this must be fixed when the PCI device is | ||
| 146 | * bound and the kernel device struct is attached to the acpi device | ||
| 147 | * Note: A success call will increase reference count by one | ||
| 148 | * Do call put_device(dev) on the returned device then | ||
| 149 | */ | ||
| 150 | struct device *acpi_get_physical_pci_device(acpi_handle handle) | ||
| 151 | { | ||
| 152 | struct device *dev; | ||
| 153 | long long device_id; | ||
| 154 | acpi_status status; | ||
| 155 | |||
| 156 | status = | ||
| 157 | acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); | ||
| 158 | |||
| 159 | if (ACPI_FAILURE(status)) | ||
| 160 | return NULL; | ||
| 161 | |||
| 162 | /* We need to attempt to determine whether the _ADR refers to a | ||
| 163 | PCI device or not. There's no terribly good way to do this, | ||
| 164 | so the best we can hope for is to assume that there'll never | ||
| 165 | be a device in the host bridge */ | ||
| 166 | if (device_id >= 0x10000) { | ||
| 167 | /* It looks like a PCI device. Does it exist? */ | ||
| 168 | dev = acpi_get_physical_device(handle); | ||
| 169 | } else { | ||
| 170 | /* It doesn't look like a PCI device. Does its parent | ||
| 171 | exist? */ | ||
| 172 | acpi_handle phandle; | ||
| 173 | if (acpi_get_parent(handle, &phandle)) | ||
| 174 | return NULL; | ||
| 175 | dev = acpi_get_physical_device(phandle); | ||
| 176 | } | ||
| 177 | if (!dev) | ||
| 178 | return NULL; | ||
| 179 | return dev; | ||
| 180 | } | ||
| 181 | EXPORT_SYMBOL(acpi_get_physical_pci_device); | ||
| 182 | |||
| 183 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
| 184 | { | 144 | { |
| 185 | struct acpi_device *acpi_dev; | 145 | struct acpi_device *acpi_dev; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d916bea729f1..71670719d61a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -79,6 +79,7 @@ static acpi_osd_handler acpi_irq_handler; | |||
| 79 | static void *acpi_irq_context; | 79 | static void *acpi_irq_context; |
| 80 | static struct workqueue_struct *kacpid_wq; | 80 | static struct workqueue_struct *kacpid_wq; |
| 81 | static struct workqueue_struct *kacpi_notify_wq; | 81 | static struct workqueue_struct *kacpi_notify_wq; |
| 82 | static struct workqueue_struct *kacpi_hotplug_wq; | ||
| 82 | 83 | ||
| 83 | struct acpi_res_list { | 84 | struct acpi_res_list { |
| 84 | resource_size_t start; | 85 | resource_size_t start; |
| @@ -192,8 +193,10 @@ acpi_status acpi_os_initialize1(void) | |||
| 192 | { | 193 | { |
| 193 | kacpid_wq = create_singlethread_workqueue("kacpid"); | 194 | kacpid_wq = create_singlethread_workqueue("kacpid"); |
| 194 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); | 195 | kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); |
| 196 | kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); | ||
| 195 | BUG_ON(!kacpid_wq); | 197 | BUG_ON(!kacpid_wq); |
| 196 | BUG_ON(!kacpi_notify_wq); | 198 | BUG_ON(!kacpi_notify_wq); |
| 199 | BUG_ON(!kacpi_hotplug_wq); | ||
| 197 | return AE_OK; | 200 | return AE_OK; |
| 198 | } | 201 | } |
| 199 | 202 | ||
| @@ -206,6 +209,7 @@ acpi_status acpi_os_terminate(void) | |||
| 206 | 209 | ||
| 207 | destroy_workqueue(kacpid_wq); | 210 | destroy_workqueue(kacpid_wq); |
| 208 | destroy_workqueue(kacpi_notify_wq); | 211 | destroy_workqueue(kacpi_notify_wq); |
| 212 | destroy_workqueue(kacpi_hotplug_wq); | ||
| 209 | 213 | ||
| 210 | return AE_OK; | 214 | return AE_OK; |
| 211 | } | 215 | } |
| @@ -716,6 +720,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 716 | acpi_status status = AE_OK; | 720 | acpi_status status = AE_OK; |
| 717 | struct acpi_os_dpc *dpc; | 721 | struct acpi_os_dpc *dpc; |
| 718 | struct workqueue_struct *queue; | 722 | struct workqueue_struct *queue; |
| 723 | work_func_t func; | ||
| 719 | int ret; | 724 | int ret; |
| 720 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 725 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
| 721 | "Scheduling function [%p(%p)] for deferred execution.\n", | 726 | "Scheduling function [%p(%p)] for deferred execution.\n", |
| @@ -740,15 +745,17 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 740 | dpc->function = function; | 745 | dpc->function = function; |
| 741 | dpc->context = context; | 746 | dpc->context = context; |
| 742 | 747 | ||
| 743 | if (!hp) { | 748 | /* |
| 744 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); | 749 | * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq |
| 745 | queue = (type == OSL_NOTIFY_HANDLER) ? | 750 | * because the hotplug code may call driver .remove() functions, |
| 746 | kacpi_notify_wq : kacpid_wq; | 751 | * which invoke flush_scheduled_work/acpi_os_wait_events_complete |
| 747 | ret = queue_work(queue, &dpc->work); | 752 | * to flush these workqueues. |
| 748 | } else { | 753 | */ |
| 749 | INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred); | 754 | queue = hp ? kacpi_hotplug_wq : |
| 750 | ret = schedule_work(&dpc->work); | 755 | (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); |
| 751 | } | 756 | func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; |
| 757 | INIT_WORK(&dpc->work, func); | ||
| 758 | ret = queue_work(queue, &dpc->work); | ||
| 752 | 759 | ||
| 753 | if (!ret) { | 760 | if (!ret) { |
| 754 | printk(KERN_ERR PREFIX | 761 | printk(KERN_ERR PREFIX |
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index bc46de3d967f..a5a77b78a723 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
| @@ -24,12 +24,7 @@ | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/types.h> | 27 | #include <linux/types.h> |
| 30 | #include <linux/proc_fs.h> | ||
| 31 | #include <linux/spinlock.h> | ||
| 32 | #include <linux/pm.h> | ||
| 33 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
| 34 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
| 35 | #include <acpi/acpi_bus.h> | 30 | #include <acpi/acpi_bus.h> |
| @@ -38,310 +33,76 @@ | |||
| 38 | #define _COMPONENT ACPI_PCI_COMPONENT | 33 | #define _COMPONENT ACPI_PCI_COMPONENT |
| 39 | ACPI_MODULE_NAME("pci_bind"); | 34 | ACPI_MODULE_NAME("pci_bind"); |
| 40 | 35 | ||
| 41 | struct acpi_pci_data { | 36 | static int acpi_pci_unbind(struct acpi_device *device) |
| 42 | struct acpi_pci_id id; | ||
| 43 | struct pci_bus *bus; | ||
| 44 | struct pci_dev *dev; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static int acpi_pci_unbind(struct acpi_device *device); | ||
| 48 | |||
| 49 | static void acpi_pci_data_handler(acpi_handle handle, u32 function, | ||
| 50 | void *context) | ||
| 51 | { | ||
| 52 | |||
| 53 | /* TBD: Anything we need to do here? */ | ||
| 54 | |||
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 | /** | ||
| 59 | * acpi_get_pci_id | ||
| 60 | * ------------------ | ||
| 61 | * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem) | ||
| 62 | * to resolve PCI information for ACPI-PCI devices defined in the namespace. | ||
| 63 | * This typically occurs when resolving PCI operation region information. | ||
| 64 | */ | ||
| 65 | acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id) | ||
| 66 | { | 37 | { |
| 67 | int result = 0; | 38 | struct pci_dev *dev; |
| 68 | acpi_status status = AE_OK; | ||
| 69 | struct acpi_device *device = NULL; | ||
| 70 | struct acpi_pci_data *data = NULL; | ||
| 71 | |||
| 72 | |||
| 73 | if (!id) | ||
| 74 | return AE_BAD_PARAMETER; | ||
| 75 | |||
| 76 | result = acpi_bus_get_device(handle, &device); | ||
| 77 | if (result) { | ||
| 78 | printk(KERN_ERR PREFIX | ||
| 79 | "Invalid ACPI Bus context for device %s\n", | ||
| 80 | acpi_device_bid(device)); | ||
| 81 | return AE_NOT_EXIST; | ||
| 82 | } | ||
| 83 | |||
| 84 | status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data); | ||
| 85 | if (ACPI_FAILURE(status) || !data) { | ||
| 86 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 87 | "Invalid ACPI-PCI context for device %s", | ||
| 88 | acpi_device_bid(device))); | ||
| 89 | return status; | ||
| 90 | } | ||
| 91 | 39 | ||
| 92 | *id = data->id; | 40 | dev = acpi_get_pci_dev(device->handle); |
| 41 | if (!dev || !dev->subordinate) | ||
| 42 | goto out; | ||
| 93 | 43 | ||
| 94 | /* | 44 | acpi_pci_irq_del_prt(dev->subordinate); |
| 95 | id->segment = data->id.segment; | ||
| 96 | id->bus = data->id.bus; | ||
| 97 | id->device = data->id.device; | ||
| 98 | id->function = data->id.function; | ||
| 99 | */ | ||
| 100 | 45 | ||
| 101 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 46 | device->ops.bind = NULL; |
| 102 | "Device %s has PCI address %04x:%02x:%02x.%d\n", | 47 | device->ops.unbind = NULL; |
| 103 | acpi_device_bid(device), id->segment, id->bus, | ||
| 104 | id->device, id->function)); | ||
| 105 | 48 | ||
| 106 | return AE_OK; | 49 | out: |
| 50 | pci_dev_put(dev); | ||
| 51 | return 0; | ||
| 107 | } | 52 | } |
| 108 | 53 | ||
| 109 | EXPORT_SYMBOL(acpi_get_pci_id); | 54 | static int acpi_pci_bind(struct acpi_device *device) |
| 110 | |||
| 111 | int acpi_pci_bind(struct acpi_device *device) | ||
| 112 | { | 55 | { |
| 113 | int result = 0; | ||
| 114 | acpi_status status; | 56 | acpi_status status; |
| 115 | struct acpi_pci_data *data; | ||
| 116 | struct acpi_pci_data *pdata; | ||
| 117 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 118 | acpi_handle handle; | 57 | acpi_handle handle; |
| 58 | struct pci_bus *bus; | ||
| 59 | struct pci_dev *dev; | ||
| 119 | 60 | ||
| 120 | if (!device || !device->parent) | 61 | dev = acpi_get_pci_dev(device->handle); |
| 121 | return -EINVAL; | 62 | if (!dev) |
| 122 | 63 | return 0; | |
| 123 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); | ||
| 124 | if (!data) | ||
| 125 | return -ENOMEM; | ||
| 126 | |||
| 127 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | ||
| 128 | if (ACPI_FAILURE(status)) { | ||
| 129 | kfree(data); | ||
| 130 | return -ENODEV; | ||
| 131 | } | ||
| 132 | |||
| 133 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", | ||
| 134 | (char *)buffer.pointer)); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Segment & Bus | ||
| 138 | * ------------- | ||
| 139 | * These are obtained via the parent device's ACPI-PCI context. | ||
| 140 | */ | ||
| 141 | status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, | ||
| 142 | (void **)&pdata); | ||
| 143 | if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { | ||
| 144 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 145 | "Invalid ACPI-PCI context for parent device %s", | ||
| 146 | acpi_device_bid(device->parent))); | ||
| 147 | result = -ENODEV; | ||
| 148 | goto end; | ||
| 149 | } | ||
| 150 | data->id.segment = pdata->id.segment; | ||
| 151 | data->id.bus = pdata->bus->number; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Device & Function | ||
| 155 | * ----------------- | ||
| 156 | * These are simply obtained from the device's _ADR method. Note | ||
| 157 | * that a value of zero is valid. | ||
| 158 | */ | ||
| 159 | data->id.device = device->pnp.bus_address >> 16; | ||
| 160 | data->id.function = device->pnp.bus_address & 0xFFFF; | ||
| 161 | |||
| 162 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", | ||
| 163 | data->id.segment, data->id.bus, data->id.device, | ||
| 164 | data->id.function)); | ||
| 165 | |||
| 166 | /* | ||
| 167 | * TBD: Support slot devices (e.g. function=0xFFFF). | ||
| 168 | */ | ||
| 169 | |||
| 170 | /* | ||
| 171 | * Locate PCI Device | ||
| 172 | * ----------------- | ||
| 173 | * Locate matching device in PCI namespace. If it doesn't exist | ||
| 174 | * this typically means that the device isn't currently inserted | ||
| 175 | * (e.g. docking station, port replicator, etc.). | ||
| 176 | */ | ||
| 177 | data->dev = pci_get_slot(pdata->bus, | ||
| 178 | PCI_DEVFN(data->id.device, data->id.function)); | ||
| 179 | if (!data->dev) { | ||
| 180 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 181 | "Device %04x:%02x:%02x.%d not present in PCI namespace\n", | ||
| 182 | data->id.segment, data->id.bus, | ||
| 183 | data->id.device, data->id.function)); | ||
| 184 | result = -ENODEV; | ||
| 185 | goto end; | ||
| 186 | } | ||
| 187 | if (!data->dev->bus) { | ||
| 188 | printk(KERN_ERR PREFIX | ||
| 189 | "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", | ||
| 190 | data->id.segment, data->id.bus, | ||
| 191 | data->id.device, data->id.function); | ||
| 192 | result = -ENODEV; | ||
| 193 | goto end; | ||
| 194 | } | ||
| 195 | 64 | ||
| 196 | /* | 65 | /* |
| 197 | * PCI Bridge? | 66 | * Install the 'bind' function to facilitate callbacks for |
| 198 | * ----------- | 67 | * children of the P2P bridge. |
| 199 | * If so, set the 'bus' field and install the 'bind' function to | ||
| 200 | * facilitate callbacks for all of its children. | ||
| 201 | */ | 68 | */ |
| 202 | if (data->dev->subordinate) { | 69 | if (dev->subordinate) { |
| 203 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 70 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 204 | "Device %04x:%02x:%02x.%d is a PCI bridge\n", | 71 | "Device %04x:%02x:%02x.%d is a PCI bridge\n", |
| 205 | data->id.segment, data->id.bus, | 72 | pci_domain_nr(dev->bus), dev->bus->number, |
| 206 | data->id.device, data->id.function)); | 73 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); |
| 207 | data->bus = data->dev->subordinate; | ||
| 208 | device->ops.bind = acpi_pci_bind; | 74 | device->ops.bind = acpi_pci_bind; |
| 209 | device->ops.unbind = acpi_pci_unbind; | 75 | device->ops.unbind = acpi_pci_unbind; |
| 210 | } | 76 | } |
| 211 | 77 | ||
| 212 | /* | 78 | /* |
| 213 | * Attach ACPI-PCI Context | 79 | * Evaluate and parse _PRT, if exists. This code allows parsing of |
| 214 | * ----------------------- | 80 | * _PRT objects within the scope of non-bridge devices. Note that |
| 215 | * Thus binding the ACPI and PCI devices. | 81 | * _PRTs within the scope of a PCI bridge assume the bridge's |
| 216 | */ | 82 | * subordinate bus number. |
| 217 | status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); | ||
| 218 | if (ACPI_FAILURE(status)) { | ||
| 219 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 220 | "Unable to attach ACPI-PCI context to device %s", | ||
| 221 | acpi_device_bid(device))); | ||
| 222 | result = -ENODEV; | ||
| 223 | goto end; | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * PCI Routing Table | ||
| 228 | * ----------------- | ||
| 229 | * Evaluate and parse _PRT, if exists. This code is independent of | ||
| 230 | * PCI bridges (above) to allow parsing of _PRT objects within the | ||
| 231 | * scope of non-bridge devices. Note that _PRTs within the scope of | ||
| 232 | * a PCI bridge assume the bridge's subordinate bus number. | ||
| 233 | * | 83 | * |
| 234 | * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? | 84 | * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? |
| 235 | */ | 85 | */ |
| 236 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | 86 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); |
| 237 | if (ACPI_SUCCESS(status)) { | ||
| 238 | if (data->bus) /* PCI-PCI bridge */ | ||
| 239 | acpi_pci_irq_add_prt(device->handle, data->id.segment, | ||
| 240 | data->bus->number); | ||
| 241 | else /* non-bridge PCI device */ | ||
| 242 | acpi_pci_irq_add_prt(device->handle, data->id.segment, | ||
| 243 | data->id.bus); | ||
| 244 | } | ||
| 245 | |||
| 246 | end: | ||
| 247 | kfree(buffer.pointer); | ||
| 248 | if (result) { | ||
| 249 | pci_dev_put(data->dev); | ||
| 250 | kfree(data); | ||
| 251 | } | ||
| 252 | return result; | ||
| 253 | } | ||
| 254 | |||
| 255 | static int acpi_pci_unbind(struct acpi_device *device) | ||
| 256 | { | ||
| 257 | int result = 0; | ||
| 258 | acpi_status status; | ||
| 259 | struct acpi_pci_data *data; | ||
| 260 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 261 | |||
| 262 | |||
| 263 | if (!device || !device->parent) | ||
| 264 | return -EINVAL; | ||
| 265 | |||
| 266 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | ||
| 267 | if (ACPI_FAILURE(status)) | 87 | if (ACPI_FAILURE(status)) |
| 268 | return -ENODEV; | 88 | goto out; |
| 269 | 89 | ||
| 270 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", | 90 | if (dev->subordinate) |
| 271 | (char *) buffer.pointer)); | 91 | bus = dev->subordinate; |
| 272 | kfree(buffer.pointer); | 92 | else |
| 93 | bus = dev->bus; | ||
| 273 | 94 | ||
| 274 | status = | 95 | acpi_pci_irq_add_prt(device->handle, bus); |
| 275 | acpi_get_data(device->handle, acpi_pci_data_handler, | ||
| 276 | (void **)&data); | ||
| 277 | if (ACPI_FAILURE(status)) { | ||
| 278 | result = -ENODEV; | ||
| 279 | goto end; | ||
| 280 | } | ||
| 281 | 96 | ||
| 282 | status = acpi_detach_data(device->handle, acpi_pci_data_handler); | 97 | out: |
| 283 | if (ACPI_FAILURE(status)) { | 98 | pci_dev_put(dev); |
| 284 | ACPI_EXCEPTION((AE_INFO, status, | 99 | return 0; |
| 285 | "Unable to detach data from device %s", | ||
| 286 | acpi_device_bid(device))); | ||
| 287 | result = -ENODEV; | ||
| 288 | goto end; | ||
| 289 | } | ||
| 290 | if (data->dev->subordinate) { | ||
| 291 | acpi_pci_irq_del_prt(data->id.segment, data->bus->number); | ||
| 292 | } | ||
| 293 | pci_dev_put(data->dev); | ||
| 294 | kfree(data); | ||
| 295 | |||
| 296 | end: | ||
| 297 | return result; | ||
| 298 | } | 100 | } |
| 299 | 101 | ||
| 300 | int | 102 | int acpi_pci_bind_root(struct acpi_device *device) |
| 301 | acpi_pci_bind_root(struct acpi_device *device, | ||
| 302 | struct acpi_pci_id *id, struct pci_bus *bus) | ||
| 303 | { | 103 | { |
| 304 | int result = 0; | ||
| 305 | acpi_status status; | ||
| 306 | struct acpi_pci_data *data = NULL; | ||
| 307 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 308 | |||
| 309 | if (!device || !id || !bus) { | ||
| 310 | return -EINVAL; | ||
| 311 | } | ||
| 312 | |||
| 313 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); | ||
| 314 | if (!data) | ||
| 315 | return -ENOMEM; | ||
| 316 | |||
| 317 | data->id = *id; | ||
| 318 | data->bus = bus; | ||
| 319 | device->ops.bind = acpi_pci_bind; | 104 | device->ops.bind = acpi_pci_bind; |
| 320 | device->ops.unbind = acpi_pci_unbind; | 105 | device->ops.unbind = acpi_pci_unbind; |
| 321 | 106 | ||
| 322 | status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | 107 | return 0; |
| 323 | if (ACPI_FAILURE(status)) { | ||
| 324 | kfree (data); | ||
| 325 | return -ENODEV; | ||
| 326 | } | ||
| 327 | |||
| 328 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " | ||
| 329 | "%04x:%02x\n", (char *)buffer.pointer, | ||
| 330 | id->segment, id->bus)); | ||
| 331 | |||
| 332 | status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); | ||
| 333 | if (ACPI_FAILURE(status)) { | ||
| 334 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 335 | "Unable to attach ACPI-PCI context to device %s", | ||
| 336 | (char *)buffer.pointer)); | ||
| 337 | result = -ENODEV; | ||
| 338 | goto end; | ||
| 339 | } | ||
| 340 | |||
| 341 | end: | ||
| 342 | kfree(buffer.pointer); | ||
| 343 | if (result != 0) | ||
| 344 | kfree(data); | ||
| 345 | |||
| 346 | return result; | ||
| 347 | } | 108 | } |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2faa9e2ac893..b794eb88ab90 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -182,7 +182,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, | |||
| 182 | } | 182 | } |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | 185 | static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, |
| 186 | struct acpi_pci_routing_table *prt) | 186 | struct acpi_pci_routing_table *prt) |
| 187 | { | 187 | { |
| 188 | struct acpi_prt_entry *entry; | 188 | struct acpi_prt_entry *entry; |
| @@ -196,8 +196,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |||
| 196 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert | 196 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert |
| 197 | * it here. | 197 | * it here. |
| 198 | */ | 198 | */ |
| 199 | entry->id.segment = segment; | 199 | entry->id.segment = pci_domain_nr(bus); |
| 200 | entry->id.bus = bus; | 200 | entry->id.bus = bus->number; |
| 201 | entry->id.device = (prt->address >> 16) & 0xFFFF; | 201 | entry->id.device = (prt->address >> 16) & 0xFFFF; |
| 202 | entry->pin = prt->pin + 1; | 202 | entry->pin = prt->pin + 1; |
| 203 | 203 | ||
| @@ -242,7 +242,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |||
| 242 | return 0; | 242 | return 0; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | 245 | int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) |
| 246 | { | 246 | { |
| 247 | acpi_status status; | 247 | acpi_status status; |
| 248 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 248 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -271,7 +271,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | |||
| 271 | 271 | ||
| 272 | entry = buffer.pointer; | 272 | entry = buffer.pointer; |
| 273 | while (entry && (entry->length > 0)) { | 273 | while (entry && (entry->length > 0)) { |
| 274 | acpi_pci_irq_add_entry(handle, segment, bus, entry); | 274 | acpi_pci_irq_add_entry(handle, bus, entry); |
| 275 | entry = (struct acpi_pci_routing_table *) | 275 | entry = (struct acpi_pci_routing_table *) |
| 276 | ((unsigned long)entry + entry->length); | 276 | ((unsigned long)entry + entry->length); |
| 277 | } | 277 | } |
| @@ -280,16 +280,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | |||
| 280 | return 0; | 280 | return 0; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | void acpi_pci_irq_del_prt(int segment, int bus) | 283 | void acpi_pci_irq_del_prt(struct pci_bus *bus) |
| 284 | { | 284 | { |
| 285 | struct acpi_prt_entry *entry, *tmp; | 285 | struct acpi_prt_entry *entry, *tmp; |
| 286 | 286 | ||
| 287 | printk(KERN_DEBUG | 287 | printk(KERN_DEBUG |
| 288 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", | 288 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", |
| 289 | segment, bus); | 289 | pci_domain_nr(bus), bus->number); |
| 290 | spin_lock(&acpi_prt_lock); | 290 | spin_lock(&acpi_prt_lock); |
| 291 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { | 291 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { |
| 292 | if (segment == entry->id.segment && bus == entry->id.bus) { | 292 | if (pci_domain_nr(bus) == entry->id.segment |
| 293 | && bus->number == entry->id.bus) { | ||
| 293 | list_del(&entry->list); | 294 | list_del(&entry->list); |
| 294 | kfree(entry); | 295 | kfree(entry); |
| 295 | } | 296 | } |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 196f97d00956..55b5b90c2a44 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -63,9 +63,10 @@ static struct acpi_driver acpi_pci_root_driver = { | |||
| 63 | 63 | ||
| 64 | struct acpi_pci_root { | 64 | struct acpi_pci_root { |
| 65 | struct list_head node; | 65 | struct list_head node; |
| 66 | struct acpi_device * device; | 66 | struct acpi_device *device; |
| 67 | struct acpi_pci_id id; | ||
| 68 | struct pci_bus *bus; | 67 | struct pci_bus *bus; |
| 68 | u16 segment; | ||
| 69 | u8 bus_nr; | ||
| 69 | 70 | ||
| 70 | u32 osc_support_set; /* _OSC state of support bits */ | 71 | u32 osc_support_set; /* _OSC state of support bits */ |
| 71 | u32 osc_control_set; /* _OSC state of control bits */ | 72 | u32 osc_control_set; /* _OSC state of control bits */ |
| @@ -82,7 +83,7 @@ static DEFINE_MUTEX(osc_lock); | |||
| 82 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) | 83 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) |
| 83 | { | 84 | { |
| 84 | int n = 0; | 85 | int n = 0; |
| 85 | struct list_head *entry; | 86 | struct acpi_pci_root *root; |
| 86 | 87 | ||
| 87 | struct acpi_pci_driver **pptr = &sub_driver; | 88 | struct acpi_pci_driver **pptr = &sub_driver; |
| 88 | while (*pptr) | 89 | while (*pptr) |
| @@ -92,9 +93,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) | |||
| 92 | if (!driver->add) | 93 | if (!driver->add) |
| 93 | return 0; | 94 | return 0; |
| 94 | 95 | ||
| 95 | list_for_each(entry, &acpi_pci_roots) { | 96 | list_for_each_entry(root, &acpi_pci_roots, node) { |
| 96 | struct acpi_pci_root *root; | ||
| 97 | root = list_entry(entry, struct acpi_pci_root, node); | ||
| 98 | driver->add(root->device->handle); | 97 | driver->add(root->device->handle); |
| 99 | n++; | 98 | n++; |
| 100 | } | 99 | } |
| @@ -106,7 +105,7 @@ EXPORT_SYMBOL(acpi_pci_register_driver); | |||
| 106 | 105 | ||
| 107 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | 106 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) |
| 108 | { | 107 | { |
| 109 | struct list_head *entry; | 108 | struct acpi_pci_root *root; |
| 110 | 109 | ||
| 111 | struct acpi_pci_driver **pptr = &sub_driver; | 110 | struct acpi_pci_driver **pptr = &sub_driver; |
| 112 | while (*pptr) { | 111 | while (*pptr) { |
| @@ -120,28 +119,48 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
| 120 | if (!driver->remove) | 119 | if (!driver->remove) |
| 121 | return; | 120 | return; |
| 122 | 121 | ||
| 123 | list_for_each(entry, &acpi_pci_roots) { | 122 | list_for_each_entry(root, &acpi_pci_roots, node) |
| 124 | struct acpi_pci_root *root; | ||
| 125 | root = list_entry(entry, struct acpi_pci_root, node); | ||
| 126 | driver->remove(root->device->handle); | 123 | driver->remove(root->device->handle); |
| 127 | } | ||
| 128 | } | 124 | } |
| 129 | 125 | ||
| 130 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 126 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
| 131 | 127 | ||
| 132 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | 128 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) |
| 133 | { | 129 | { |
| 134 | struct acpi_pci_root *tmp; | 130 | struct acpi_pci_root *root; |
| 135 | 131 | ||
| 136 | list_for_each_entry(tmp, &acpi_pci_roots, node) { | 132 | list_for_each_entry(root, &acpi_pci_roots, node) |
| 137 | if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus)) | 133 | if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) |
| 138 | return tmp->device->handle; | 134 | return root->device->handle; |
| 139 | } | ||
| 140 | return NULL; | 135 | return NULL; |
| 141 | } | 136 | } |
| 142 | 137 | ||
| 143 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | 138 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); |
| 144 | 139 | ||
| 140 | /** | ||
| 141 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | ||
| 142 | * @handle - the ACPI CA node in question. | ||
| 143 | * | ||
| 144 | * Note: we could make this API take a struct acpi_device * instead, but | ||
| 145 | * for now, it's more convenient to operate on an acpi_handle. | ||
| 146 | */ | ||
| 147 | int acpi_is_root_bridge(acpi_handle handle) | ||
| 148 | { | ||
| 149 | int ret; | ||
| 150 | struct acpi_device *device; | ||
| 151 | |||
| 152 | ret = acpi_bus_get_device(handle, &device); | ||
| 153 | if (ret) | ||
| 154 | return 0; | ||
| 155 | |||
| 156 | ret = acpi_match_device_ids(device, root_device_ids); | ||
| 157 | if (ret) | ||
| 158 | return 0; | ||
| 159 | else | ||
| 160 | return 1; | ||
| 161 | } | ||
| 162 | EXPORT_SYMBOL_GPL(acpi_is_root_bridge); | ||
| 163 | |||
| 145 | static acpi_status | 164 | static acpi_status |
| 146 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | 165 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) |
| 147 | { | 166 | { |
| @@ -161,19 +180,22 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | |||
| 161 | return AE_OK; | 180 | return AE_OK; |
| 162 | } | 181 | } |
| 163 | 182 | ||
| 164 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) | 183 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
| 184 | unsigned long long *bus) | ||
| 165 | { | 185 | { |
| 166 | acpi_status status; | 186 | acpi_status status; |
| 187 | int busnum; | ||
| 167 | 188 | ||
| 168 | *busnum = -1; | 189 | busnum = -1; |
| 169 | status = | 190 | status = |
| 170 | acpi_walk_resources(handle, METHOD_NAME__CRS, | 191 | acpi_walk_resources(handle, METHOD_NAME__CRS, |
| 171 | get_root_bridge_busnr_callback, busnum); | 192 | get_root_bridge_busnr_callback, &busnum); |
| 172 | if (ACPI_FAILURE(status)) | 193 | if (ACPI_FAILURE(status)) |
| 173 | return status; | 194 | return status; |
| 174 | /* Check if we really get a bus number from _CRS */ | 195 | /* Check if we really get a bus number from _CRS */ |
| 175 | if (*busnum == -1) | 196 | if (busnum == -1) |
| 176 | return AE_ERROR; | 197 | return AE_ERROR; |
| 198 | *bus = busnum; | ||
| 177 | return AE_OK; | 199 | return AE_OK; |
| 178 | } | 200 | } |
| 179 | 201 | ||
| @@ -298,6 +320,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) | |||
| 298 | static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | 320 | static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) |
| 299 | { | 321 | { |
| 300 | struct acpi_pci_root *root; | 322 | struct acpi_pci_root *root; |
| 323 | |||
| 301 | list_for_each_entry(root, &acpi_pci_roots, node) { | 324 | list_for_each_entry(root, &acpi_pci_roots, node) { |
| 302 | if (root->device->handle == handle) | 325 | if (root->device->handle == handle) |
| 303 | return root; | 326 | return root; |
| @@ -305,6 +328,87 @@ static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | |||
| 305 | return NULL; | 328 | return NULL; |
| 306 | } | 329 | } |
| 307 | 330 | ||
| 331 | struct acpi_handle_node { | ||
| 332 | struct list_head node; | ||
| 333 | acpi_handle handle; | ||
| 334 | }; | ||
| 335 | |||
| 336 | /** | ||
| 337 | * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev | ||
| 338 | * @handle: the handle in question | ||
| 339 | * | ||
| 340 | * Given an ACPI CA handle, the desired PCI device is located in the | ||
| 341 | * list of PCI devices. | ||
| 342 | * | ||
| 343 | * If the device is found, its reference count is increased and this | ||
| 344 | * function returns a pointer to its data structure. The caller must | ||
| 345 | * decrement the reference count by calling pci_dev_put(). | ||
| 346 | * If no device is found, %NULL is returned. | ||
| 347 | */ | ||
| 348 | struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | ||
| 349 | { | ||
| 350 | int dev, fn; | ||
| 351 | unsigned long long adr; | ||
| 352 | acpi_status status; | ||
| 353 | acpi_handle phandle; | ||
| 354 | struct pci_bus *pbus; | ||
| 355 | struct pci_dev *pdev = NULL; | ||
| 356 | struct acpi_handle_node *node, *tmp; | ||
| 357 | struct acpi_pci_root *root; | ||
| 358 | LIST_HEAD(device_list); | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Walk up the ACPI CA namespace until we reach a PCI root bridge. | ||
| 362 | */ | ||
| 363 | phandle = handle; | ||
| 364 | while (!acpi_is_root_bridge(phandle)) { | ||
| 365 | node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); | ||
| 366 | if (!node) | ||
| 367 | goto out; | ||
| 368 | |||
| 369 | INIT_LIST_HEAD(&node->node); | ||
| 370 | node->handle = phandle; | ||
| 371 | list_add(&node->node, &device_list); | ||
| 372 | |||
| 373 | status = acpi_get_parent(phandle, &phandle); | ||
| 374 | if (ACPI_FAILURE(status)) | ||
| 375 | goto out; | ||
| 376 | } | ||
| 377 | |||
| 378 | root = acpi_pci_find_root(phandle); | ||
| 379 | if (!root) | ||
| 380 | goto out; | ||
| 381 | |||
| 382 | pbus = root->bus; | ||
| 383 | |||
| 384 | /* | ||
| 385 | * Now, walk back down the PCI device tree until we return to our | ||
| 386 | * original handle. Assumes that everything between the PCI root | ||
| 387 | * bridge and the device we're looking for must be a P2P bridge. | ||
| 388 | */ | ||
| 389 | list_for_each_entry(node, &device_list, node) { | ||
| 390 | acpi_handle hnd = node->handle; | ||
| 391 | status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); | ||
| 392 | if (ACPI_FAILURE(status)) | ||
| 393 | goto out; | ||
| 394 | dev = (adr >> 16) & 0xffff; | ||
| 395 | fn = adr & 0xffff; | ||
| 396 | |||
| 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); | ||
| 398 | if (!pdev || hnd == handle) | ||
| 399 | break; | ||
| 400 | |||
| 401 | pbus = pdev->subordinate; | ||
| 402 | pci_dev_put(pdev); | ||
| 403 | } | ||
| 404 | out: | ||
| 405 | list_for_each_entry_safe(node, tmp, &device_list, node) | ||
| 406 | kfree(node); | ||
| 407 | |||
| 408 | return pdev; | ||
| 409 | } | ||
| 410 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | ||
| 411 | |||
| 308 | /** | 412 | /** |
| 309 | * acpi_pci_osc_control_set - commit requested control to Firmware | 413 | * acpi_pci_osc_control_set - commit requested control to Firmware |
| 310 | * @handle: acpi_handle for the target ACPI object | 414 | * @handle: acpi_handle for the target ACPI object |
| @@ -363,31 +467,46 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); | |||
| 363 | 467 | ||
| 364 | static int __devinit acpi_pci_root_add(struct acpi_device *device) | 468 | static int __devinit acpi_pci_root_add(struct acpi_device *device) |
| 365 | { | 469 | { |
| 366 | int result = 0; | 470 | unsigned long long segment, bus; |
| 367 | struct acpi_pci_root *root = NULL; | 471 | acpi_status status; |
| 368 | struct acpi_pci_root *tmp; | 472 | int result; |
| 369 | acpi_status status = AE_OK; | 473 | struct acpi_pci_root *root; |
| 370 | unsigned long long value = 0; | 474 | acpi_handle handle; |
| 371 | acpi_handle handle = NULL; | ||
| 372 | struct acpi_device *child; | 475 | struct acpi_device *child; |
| 373 | u32 flags, base_flags; | 476 | u32 flags, base_flags; |
| 374 | 477 | ||
| 478 | segment = 0; | ||
| 479 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
| 480 | &segment); | ||
| 481 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
| 482 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); | ||
| 483 | return -ENODEV; | ||
| 484 | } | ||
| 375 | 485 | ||
| 376 | if (!device) | 486 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
| 377 | return -EINVAL; | 487 | bus = 0; |
| 488 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
| 489 | if (ACPI_FAILURE(status)) { | ||
| 490 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); | ||
| 491 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
| 492 | printk(KERN_ERR PREFIX | ||
| 493 | "no bus number in _CRS and can't evaluate _BBN\n"); | ||
| 494 | return -ENODEV; | ||
| 495 | } | ||
| 496 | } | ||
| 378 | 497 | ||
| 379 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | 498 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
| 380 | if (!root) | 499 | if (!root) |
| 381 | return -ENOMEM; | 500 | return -ENOMEM; |
| 382 | INIT_LIST_HEAD(&root->node); | ||
| 383 | 501 | ||
| 502 | INIT_LIST_HEAD(&root->node); | ||
| 384 | root->device = device; | 503 | root->device = device; |
| 504 | root->segment = segment & 0xFFFF; | ||
| 505 | root->bus_nr = bus & 0xFF; | ||
| 385 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 506 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
| 386 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 507 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
| 387 | device->driver_data = root; | 508 | device->driver_data = root; |
| 388 | 509 | ||
| 389 | device->ops.bind = acpi_pci_bind; | ||
| 390 | |||
| 391 | /* | 510 | /* |
| 392 | * All supported architectures that use ACPI have support for | 511 | * All supported architectures that use ACPI have support for |
| 393 | * PCI domains, so we indicate this in _OSC support capabilities. | 512 | * PCI domains, so we indicate this in _OSC support capabilities. |
| @@ -395,79 +514,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 395 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | 514 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
| 396 | acpi_pci_osc_support(root, flags); | 515 | acpi_pci_osc_support(root, flags); |
| 397 | 516 | ||
| 398 | /* | ||
| 399 | * Segment | ||
| 400 | * ------- | ||
| 401 | * Obtained via _SEG, if exists, otherwise assumed to be zero (0). | ||
| 402 | */ | ||
| 403 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
| 404 | &value); | ||
| 405 | switch (status) { | ||
| 406 | case AE_OK: | ||
| 407 | root->id.segment = (u16) value; | ||
| 408 | break; | ||
| 409 | case AE_NOT_FOUND: | ||
| 410 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 411 | "Assuming segment 0 (no _SEG)\n")); | ||
| 412 | root->id.segment = 0; | ||
| 413 | break; | ||
| 414 | default: | ||
| 415 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG")); | ||
| 416 | result = -ENODEV; | ||
| 417 | goto end; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* | ||
| 421 | * Bus | ||
| 422 | * --- | ||
| 423 | * Obtained via _BBN, if exists, otherwise assumed to be zero (0). | ||
| 424 | */ | ||
| 425 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, | ||
| 426 | &value); | ||
| 427 | switch (status) { | ||
| 428 | case AE_OK: | ||
| 429 | root->id.bus = (u16) value; | ||
| 430 | break; | ||
| 431 | case AE_NOT_FOUND: | ||
| 432 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n")); | ||
| 433 | root->id.bus = 0; | ||
| 434 | break; | ||
| 435 | default: | ||
| 436 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN")); | ||
| 437 | result = -ENODEV; | ||
| 438 | goto end; | ||
| 439 | } | ||
| 440 | |||
| 441 | /* Some systems have wrong _BBN */ | ||
| 442 | list_for_each_entry(tmp, &acpi_pci_roots, node) { | ||
| 443 | if ((tmp->id.segment == root->id.segment) | ||
| 444 | && (tmp->id.bus == root->id.bus)) { | ||
| 445 | int bus = 0; | ||
| 446 | acpi_status status; | ||
| 447 | |||
| 448 | printk(KERN_ERR PREFIX | ||
| 449 | "Wrong _BBN value, reboot" | ||
| 450 | " and use option 'pci=noacpi'\n"); | ||
| 451 | |||
| 452 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
| 453 | if (ACPI_FAILURE(status)) | ||
| 454 | break; | ||
| 455 | if (bus != root->id.bus) { | ||
| 456 | printk(KERN_INFO PREFIX | ||
| 457 | "PCI _CRS %d overrides _BBN 0\n", bus); | ||
| 458 | root->id.bus = bus; | ||
| 459 | } | ||
| 460 | break; | ||
| 461 | } | ||
| 462 | } | ||
| 463 | /* | ||
| 464 | * Device & Function | ||
| 465 | * ----------------- | ||
| 466 | * Obtained from _ADR (which has already been evaluated for us). | ||
| 467 | */ | ||
| 468 | root->id.device = device->pnp.bus_address >> 16; | ||
| 469 | root->id.function = device->pnp.bus_address & 0xFFFF; | ||
| 470 | |||
| 471 | /* | 517 | /* |
| 472 | * TBD: Need PCI interface for enumeration/configuration of roots. | 518 | * TBD: Need PCI interface for enumeration/configuration of roots. |
| 473 | */ | 519 | */ |
| @@ -477,7 +523,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 477 | 523 | ||
| 478 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", | 524 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", |
| 479 | acpi_device_name(device), acpi_device_bid(device), | 525 | acpi_device_name(device), acpi_device_bid(device), |
| 480 | root->id.segment, root->id.bus); | 526 | root->segment, root->bus_nr); |
| 481 | 527 | ||
| 482 | /* | 528 | /* |
| 483 | * Scan the Root Bridge | 529 | * Scan the Root Bridge |
| @@ -486,11 +532,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 486 | * PCI namespace does not get created until this call is made (and | 532 | * PCI namespace does not get created until this call is made (and |
| 487 | * thus the root bridge's pci_dev does not exist). | 533 | * thus the root bridge's pci_dev does not exist). |
| 488 | */ | 534 | */ |
| 489 | root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); | 535 | root->bus = pci_acpi_scan_root(device, segment, bus); |
| 490 | if (!root->bus) { | 536 | if (!root->bus) { |
| 491 | printk(KERN_ERR PREFIX | 537 | printk(KERN_ERR PREFIX |
| 492 | "Bus %04x:%02x not present in PCI namespace\n", | 538 | "Bus %04x:%02x not present in PCI namespace\n", |
| 493 | root->id.segment, root->id.bus); | 539 | root->segment, root->bus_nr); |
| 494 | result = -ENODEV; | 540 | result = -ENODEV; |
| 495 | goto end; | 541 | goto end; |
| 496 | } | 542 | } |
| @@ -500,7 +546,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 500 | * ----------------------- | 546 | * ----------------------- |
| 501 | * Thus binding the ACPI and PCI devices. | 547 | * Thus binding the ACPI and PCI devices. |
| 502 | */ | 548 | */ |
| 503 | result = acpi_pci_bind_root(device, &root->id, root->bus); | 549 | result = acpi_pci_bind_root(device); |
| 504 | if (result) | 550 | if (result) |
| 505 | goto end; | 551 | goto end; |
| 506 | 552 | ||
| @@ -511,8 +557,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 511 | */ | 557 | */ |
| 512 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | 558 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); |
| 513 | if (ACPI_SUCCESS(status)) | 559 | if (ACPI_SUCCESS(status)) |
| 514 | result = acpi_pci_irq_add_prt(device->handle, root->id.segment, | 560 | result = acpi_pci_irq_add_prt(device->handle, root->bus); |
| 515 | root->id.bus); | ||
| 516 | 561 | ||
| 517 | /* | 562 | /* |
| 518 | * Scan and bind all _ADR-Based Devices | 563 | * Scan and bind all _ADR-Based Devices |
| @@ -531,42 +576,28 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 531 | if (flags != base_flags) | 576 | if (flags != base_flags) |
| 532 | acpi_pci_osc_support(root, flags); | 577 | acpi_pci_osc_support(root, flags); |
| 533 | 578 | ||
| 534 | end: | 579 | return 0; |
| 535 | if (result) { | ||
| 536 | if (!list_empty(&root->node)) | ||
| 537 | list_del(&root->node); | ||
| 538 | kfree(root); | ||
| 539 | } | ||
| 540 | 580 | ||
| 581 | end: | ||
| 582 | if (!list_empty(&root->node)) | ||
| 583 | list_del(&root->node); | ||
| 584 | kfree(root); | ||
| 541 | return result; | 585 | return result; |
| 542 | } | 586 | } |
| 543 | 587 | ||
| 544 | static int acpi_pci_root_start(struct acpi_device *device) | 588 | static int acpi_pci_root_start(struct acpi_device *device) |
| 545 | { | 589 | { |
| 546 | struct acpi_pci_root *root; | 590 | struct acpi_pci_root *root = acpi_driver_data(device); |
| 547 | 591 | ||
| 548 | 592 | pci_bus_add_devices(root->bus); | |
| 549 | list_for_each_entry(root, &acpi_pci_roots, node) { | 593 | return 0; |
| 550 | if (root->device == device) { | ||
| 551 | pci_bus_add_devices(root->bus); | ||
| 552 | return 0; | ||
| 553 | } | ||
| 554 | } | ||
| 555 | return -ENODEV; | ||
| 556 | } | 594 | } |
| 557 | 595 | ||
| 558 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 596 | static int acpi_pci_root_remove(struct acpi_device *device, int type) |
| 559 | { | 597 | { |
| 560 | struct acpi_pci_root *root = NULL; | 598 | struct acpi_pci_root *root = acpi_driver_data(device); |
| 561 | |||
| 562 | |||
| 563 | if (!device || !acpi_driver_data(device)) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | root = acpi_driver_data(device); | ||
| 567 | 599 | ||
| 568 | kfree(root); | 600 | kfree(root); |
| 569 | |||
| 570 | return 0; | 601 | return 0; |
| 571 | } | 602 | } |
| 572 | 603 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 56665a63bf19..d74365d4a6e7 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -194,7 +194,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
| 194 | 194 | ||
| 195 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | 195 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) |
| 196 | { | 196 | { |
| 197 | int result = 0, state; | 197 | int result = 0; |
| 198 | int found = 0; | 198 | int found = 0; |
| 199 | acpi_status status = AE_OK; | 199 | acpi_status status = AE_OK; |
| 200 | struct acpi_power_resource *resource = NULL; | 200 | struct acpi_power_resource *resource = NULL; |
| @@ -236,18 +236,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
| 236 | if (ACPI_FAILURE(status)) | 236 | if (ACPI_FAILURE(status)) |
| 237 | return -ENODEV; | 237 | return -ENODEV; |
| 238 | 238 | ||
| 239 | if (!acpi_power_nocheck) { | ||
| 240 | /* | ||
| 241 | * If acpi_power_nocheck is set, it is unnecessary to check | ||
| 242 | * the power state after power transition. | ||
| 243 | */ | ||
| 244 | result = acpi_power_get_state(resource->device->handle, | ||
| 245 | &state); | ||
| 246 | if (result) | ||
| 247 | return result; | ||
| 248 | if (state != ACPI_POWER_RESOURCE_STATE_ON) | ||
| 249 | return -ENOEXEC; | ||
| 250 | } | ||
| 251 | /* Update the power resource's _device_ power state */ | 239 | /* Update the power resource's _device_ power state */ |
| 252 | resource->device->power.state = ACPI_STATE_D0; | 240 | resource->device->power.state = ACPI_STATE_D0; |
| 253 | 241 | ||
| @@ -258,7 +246,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
| 258 | 246 | ||
| 259 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | 247 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) |
| 260 | { | 248 | { |
| 261 | int result = 0, state; | 249 | int result = 0; |
| 262 | acpi_status status = AE_OK; | 250 | acpi_status status = AE_OK; |
| 263 | struct acpi_power_resource *resource = NULL; | 251 | struct acpi_power_resource *resource = NULL; |
| 264 | struct list_head *node, *next; | 252 | struct list_head *node, *next; |
| @@ -293,18 +281,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
| 293 | if (ACPI_FAILURE(status)) | 281 | if (ACPI_FAILURE(status)) |
| 294 | return -ENODEV; | 282 | return -ENODEV; |
| 295 | 283 | ||
| 296 | if (!acpi_power_nocheck) { | ||
| 297 | /* | ||
| 298 | * If acpi_power_nocheck is set, it is unnecessary to check | ||
| 299 | * the power state after power transition. | ||
| 300 | */ | ||
| 301 | result = acpi_power_get_state(handle, &state); | ||
| 302 | if (result) | ||
| 303 | return result; | ||
| 304 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) | ||
| 305 | return -ENOEXEC; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* Update the power resource's _device_ power state */ | 284 | /* Update the power resource's _device_ power state */ |
| 309 | resource->device->power.state = ACPI_STATE_D3; | 285 | resource->device->power.state = ACPI_STATE_D3; |
| 310 | 286 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 23f0fb84f1c1..84e0f3c07442 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -89,7 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); | |||
| 89 | 89 | ||
| 90 | static const struct acpi_device_id processor_device_ids[] = { | 90 | static const struct acpi_device_id processor_device_ids[] = { |
| 91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, | 91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, |
| 92 | {ACPI_PROCESSOR_HID, 0}, | 92 | {"ACPI0007", 0}, |
| 93 | {"", 0}, | 93 | {"", 0}, |
| 94 | }; | 94 | }; |
| 95 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); | 95 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); |
| @@ -596,7 +596,21 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
| 596 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 596 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 597 | "No bus mastering arbitration control\n")); | 597 | "No bus mastering arbitration control\n")); |
| 598 | 598 | ||
| 599 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { | 599 | if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { |
| 600 | /* Declared with "Processor" statement; match ProcessorID */ | ||
| 601 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | ||
| 602 | if (ACPI_FAILURE(status)) { | ||
| 603 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | ||
| 604 | return -ENODEV; | ||
| 605 | } | ||
| 606 | |||
| 607 | /* | ||
| 608 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | ||
| 609 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in | ||
| 610 | * arch/xxx/acpi.c | ||
| 611 | */ | ||
| 612 | pr->acpi_id = object.processor.proc_id; | ||
| 613 | } else { | ||
| 600 | /* | 614 | /* |
| 601 | * Declared with "Device" statement; match _UID. | 615 | * Declared with "Device" statement; match _UID. |
| 602 | * Note that we don't handle string _UIDs yet. | 616 | * Note that we don't handle string _UIDs yet. |
| @@ -611,20 +625,6 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
| 611 | } | 625 | } |
| 612 | device_declaration = 1; | 626 | device_declaration = 1; |
| 613 | pr->acpi_id = value; | 627 | pr->acpi_id = value; |
| 614 | } else { | ||
| 615 | /* Declared with "Processor" statement; match ProcessorID */ | ||
| 616 | status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); | ||
| 617 | if (ACPI_FAILURE(status)) { | ||
| 618 | printk(KERN_ERR PREFIX "Evaluating processor object\n"); | ||
| 619 | return -ENODEV; | ||
| 620 | } | ||
| 621 | |||
| 622 | /* | ||
| 623 | * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. | ||
| 624 | * >>> 'acpi_get_processor_id(acpi_id, &id)' in | ||
| 625 | * arch/xxx/acpi.c | ||
| 626 | */ | ||
| 627 | pr->acpi_id = object.processor.proc_id; | ||
| 628 | } | 628 | } |
| 629 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); | 629 | cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); |
| 630 | 630 | ||
| @@ -649,7 +649,16 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
| 649 | return -ENODEV; | 649 | return -ENODEV; |
| 650 | } | 650 | } |
| 651 | } | 651 | } |
| 652 | 652 | /* | |
| 653 | * On some boxes several processors use the same processor bus id. | ||
| 654 | * But they are located in different scope. For example: | ||
| 655 | * \_SB.SCK0.CPU0 | ||
| 656 | * \_SB.SCK1.CPU0 | ||
| 657 | * Rename the processor device bus id. And the new bus id will be | ||
| 658 | * generated as the following format: | ||
| 659 | * CPU+CPU ID. | ||
| 660 | */ | ||
| 661 | sprintf(acpi_device_bid(device), "CPU%X", pr->id); | ||
| 653 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, | 662 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, |
| 654 | pr->acpi_id)); | 663 | pr->acpi_id)); |
| 655 | 664 | ||
| @@ -731,6 +740,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
| 731 | /* _PDC call should be done before doing anything else (if reqd.). */ | 740 | /* _PDC call should be done before doing anything else (if reqd.). */ |
| 732 | arch_acpi_processor_init_pdc(pr); | 741 | arch_acpi_processor_init_pdc(pr); |
| 733 | acpi_processor_set_pdc(pr); | 742 | acpi_processor_set_pdc(pr); |
| 743 | arch_acpi_processor_cleanup_pdc(pr); | ||
| 744 | |||
| 734 | #ifdef CONFIG_CPU_FREQ | 745 | #ifdef CONFIG_CPU_FREQ |
| 735 | acpi_processor_ppc_has_changed(pr); | 746 | acpi_processor_ppc_has_changed(pr); |
| 736 | #endif | 747 | #endif |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 10a2d913635a..0efa59e7e3af 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -139,7 +139,7 @@ static void acpi_safe_halt(void) | |||
| 139 | * are affected too. We pick the most conservative approach: we assume | 139 | * are affected too. We pick the most conservative approach: we assume |
| 140 | * that the local APIC stops in both C2 and C3. | 140 | * that the local APIC stops in both C2 and C3. |
| 141 | */ | 141 | */ |
| 142 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | 142 | static void lapic_timer_check_state(int state, struct acpi_processor *pr, |
| 143 | struct acpi_processor_cx *cx) | 143 | struct acpi_processor_cx *cx) |
| 144 | { | 144 | { |
| 145 | struct acpi_processor_power *pwr = &pr->power; | 145 | struct acpi_processor_power *pwr = &pr->power; |
| @@ -162,7 +162,7 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | |||
| 162 | pr->power.timer_broadcast_on_state = state; | 162 | pr->power.timer_broadcast_on_state = state; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | 165 | static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) |
| 166 | { | 166 | { |
| 167 | unsigned long reason; | 167 | unsigned long reason; |
| 168 | 168 | ||
| @@ -173,7 +173,7 @@ static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | |||
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | /* Power(C) State timer broadcast control */ | 175 | /* Power(C) State timer broadcast control */ |
| 176 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | 176 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, |
| 177 | struct acpi_processor_cx *cx, | 177 | struct acpi_processor_cx *cx, |
| 178 | int broadcast) | 178 | int broadcast) |
| 179 | { | 179 | { |
| @@ -190,10 +190,10 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
| 190 | 190 | ||
| 191 | #else | 191 | #else |
| 192 | 192 | ||
| 193 | static void acpi_timer_check_state(int state, struct acpi_processor *pr, | 193 | static void lapic_timer_check_state(int state, struct acpi_processor *pr, |
| 194 | struct acpi_processor_cx *cstate) { } | 194 | struct acpi_processor_cx *cstate) { } |
| 195 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } | 195 | static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } |
| 196 | static void acpi_state_timer_broadcast(struct acpi_processor *pr, | 196 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, |
| 197 | struct acpi_processor_cx *cx, | 197 | struct acpi_processor_cx *cx, |
| 198 | int broadcast) | 198 | int broadcast) |
| 199 | { | 199 | { |
| @@ -515,7 +515,8 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | |||
| 515 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 515 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, |
| 516 | struct acpi_processor_cx *cx) | 516 | struct acpi_processor_cx *cx) |
| 517 | { | 517 | { |
| 518 | static int bm_check_flag; | 518 | static int bm_check_flag = -1; |
| 519 | static int bm_control_flag = -1; | ||
| 519 | 520 | ||
| 520 | 521 | ||
| 521 | if (!cx->address) | 522 | if (!cx->address) |
| @@ -545,12 +546,14 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
| 545 | } | 546 | } |
| 546 | 547 | ||
| 547 | /* All the logic here assumes flags.bm_check is same across all CPUs */ | 548 | /* All the logic here assumes flags.bm_check is same across all CPUs */ |
| 548 | if (!bm_check_flag) { | 549 | if (bm_check_flag == -1) { |
| 549 | /* Determine whether bm_check is needed based on CPU */ | 550 | /* Determine whether bm_check is needed based on CPU */ |
| 550 | acpi_processor_power_init_bm_check(&(pr->flags), pr->id); | 551 | acpi_processor_power_init_bm_check(&(pr->flags), pr->id); |
| 551 | bm_check_flag = pr->flags.bm_check; | 552 | bm_check_flag = pr->flags.bm_check; |
| 553 | bm_control_flag = pr->flags.bm_control; | ||
| 552 | } else { | 554 | } else { |
| 553 | pr->flags.bm_check = bm_check_flag; | 555 | pr->flags.bm_check = bm_check_flag; |
| 556 | pr->flags.bm_control = bm_control_flag; | ||
| 554 | } | 557 | } |
| 555 | 558 | ||
| 556 | if (pr->flags.bm_check) { | 559 | if (pr->flags.bm_check) { |
| @@ -614,29 +617,25 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 614 | switch (cx->type) { | 617 | switch (cx->type) { |
| 615 | case ACPI_STATE_C1: | 618 | case ACPI_STATE_C1: |
| 616 | cx->valid = 1; | 619 | cx->valid = 1; |
| 617 | acpi_timer_check_state(i, pr, cx); | ||
| 618 | break; | 620 | break; |
| 619 | 621 | ||
| 620 | case ACPI_STATE_C2: | 622 | case ACPI_STATE_C2: |
| 621 | acpi_processor_power_verify_c2(cx); | 623 | acpi_processor_power_verify_c2(cx); |
| 622 | if (cx->valid) | ||
| 623 | acpi_timer_check_state(i, pr, cx); | ||
| 624 | break; | 624 | break; |
| 625 | 625 | ||
| 626 | case ACPI_STATE_C3: | 626 | case ACPI_STATE_C3: |
| 627 | acpi_processor_power_verify_c3(pr, cx); | 627 | acpi_processor_power_verify_c3(pr, cx); |
| 628 | if (cx->valid) | ||
| 629 | acpi_timer_check_state(i, pr, cx); | ||
| 630 | break; | 628 | break; |
| 631 | } | 629 | } |
| 632 | if (cx->valid) | 630 | if (!cx->valid) |
| 633 | tsc_check_state(cx->type); | 631 | continue; |
| 634 | 632 | ||
| 635 | if (cx->valid) | 633 | lapic_timer_check_state(i, pr, cx); |
| 636 | working++; | 634 | tsc_check_state(cx->type); |
| 635 | working++; | ||
| 637 | } | 636 | } |
| 638 | 637 | ||
| 639 | acpi_propagate_timer_broadcast(pr); | 638 | lapic_timer_propagate_broadcast(pr); |
| 640 | 639 | ||
| 641 | return (working); | 640 | return (working); |
| 642 | } | 641 | } |
| @@ -839,7 +838,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 839 | return 0; | 838 | return 0; |
| 840 | } | 839 | } |
| 841 | 840 | ||
| 842 | acpi_state_timer_broadcast(pr, cx, 1); | 841 | lapic_timer_state_broadcast(pr, cx, 1); |
| 843 | kt1 = ktime_get_real(); | 842 | kt1 = ktime_get_real(); |
| 844 | acpi_idle_do_entry(cx); | 843 | acpi_idle_do_entry(cx); |
| 845 | kt2 = ktime_get_real(); | 844 | kt2 = ktime_get_real(); |
| @@ -847,7 +846,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 847 | 846 | ||
| 848 | local_irq_enable(); | 847 | local_irq_enable(); |
| 849 | cx->usage++; | 848 | cx->usage++; |
| 850 | acpi_state_timer_broadcast(pr, cx, 0); | 849 | lapic_timer_state_broadcast(pr, cx, 0); |
| 851 | 850 | ||
| 852 | return idle_time; | 851 | return idle_time; |
| 853 | } | 852 | } |
| @@ -892,7 +891,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
| 892 | * Must be done before busmaster disable as we might need to | 891 | * Must be done before busmaster disable as we might need to |
| 893 | * access HPET ! | 892 | * access HPET ! |
| 894 | */ | 893 | */ |
| 895 | acpi_state_timer_broadcast(pr, cx, 1); | 894 | lapic_timer_state_broadcast(pr, cx, 1); |
| 896 | 895 | ||
| 897 | if (cx->type == ACPI_STATE_C3) | 896 | if (cx->type == ACPI_STATE_C3) |
| 898 | ACPI_FLUSH_CPU_CACHE(); | 897 | ACPI_FLUSH_CPU_CACHE(); |
| @@ -914,7 +913,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
| 914 | 913 | ||
| 915 | cx->usage++; | 914 | cx->usage++; |
| 916 | 915 | ||
| 917 | acpi_state_timer_broadcast(pr, cx, 0); | 916 | lapic_timer_state_broadcast(pr, cx, 0); |
| 918 | cx->time += sleep_ticks; | 917 | cx->time += sleep_ticks; |
| 919 | return idle_time; | 918 | return idle_time; |
| 920 | } | 919 | } |
| @@ -981,7 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
| 981 | * Must be done before busmaster disable as we might need to | 980 | * Must be done before busmaster disable as we might need to |
| 982 | * access HPET ! | 981 | * access HPET ! |
| 983 | */ | 982 | */ |
| 984 | acpi_state_timer_broadcast(pr, cx, 1); | 983 | lapic_timer_state_broadcast(pr, cx, 1); |
| 985 | 984 | ||
| 986 | kt1 = ktime_get_real(); | 985 | kt1 = ktime_get_real(); |
| 987 | /* | 986 | /* |
| @@ -1026,7 +1025,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
| 1026 | 1025 | ||
| 1027 | cx->usage++; | 1026 | cx->usage++; |
| 1028 | 1027 | ||
| 1029 | acpi_state_timer_broadcast(pr, cx, 0); | 1028 | lapic_timer_state_broadcast(pr, cx, 0); |
| 1030 | cx->time += sleep_ticks; | 1029 | cx->time += sleep_ticks; |
| 1031 | return idle_time; | 1030 | return idle_time; |
| 1032 | } | 1031 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8ff510b91d88..781435d7e369 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -95,7 +95,7 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
| 95 | } | 95 | } |
| 96 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 96 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
| 97 | 97 | ||
| 98 | static int acpi_bus_hot_remove_device(void *context) | 98 | static void acpi_bus_hot_remove_device(void *context) |
| 99 | { | 99 | { |
| 100 | struct acpi_device *device; | 100 | struct acpi_device *device; |
| 101 | acpi_handle handle = context; | 101 | acpi_handle handle = context; |
| @@ -104,10 +104,10 @@ static int acpi_bus_hot_remove_device(void *context) | |||
| 104 | acpi_status status = AE_OK; | 104 | acpi_status status = AE_OK; |
| 105 | 105 | ||
| 106 | if (acpi_bus_get_device(handle, &device)) | 106 | if (acpi_bus_get_device(handle, &device)) |
| 107 | return 0; | 107 | return; |
| 108 | 108 | ||
| 109 | if (!device) | 109 | if (!device) |
| 110 | return 0; | 110 | return; |
| 111 | 111 | ||
| 112 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 112 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 113 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 113 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
| @@ -115,7 +115,7 @@ static int acpi_bus_hot_remove_device(void *context) | |||
| 115 | if (acpi_bus_trim(device, 1)) { | 115 | if (acpi_bus_trim(device, 1)) { |
| 116 | printk(KERN_ERR PREFIX | 116 | printk(KERN_ERR PREFIX |
| 117 | "Removing device failed\n"); | 117 | "Removing device failed\n"); |
| 118 | return -1; | 118 | return; |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | /* power off device */ | 121 | /* power off device */ |
| @@ -142,9 +142,10 @@ static int acpi_bus_hot_remove_device(void *context) | |||
| 142 | */ | 142 | */ |
| 143 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); | 143 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); |
| 144 | if (ACPI_FAILURE(status)) | 144 | if (ACPI_FAILURE(status)) |
| 145 | return -ENODEV; | 145 | printk(KERN_WARNING PREFIX |
| 146 | "Eject device failed\n"); | ||
| 146 | 147 | ||
| 147 | return 0; | 148 | return; |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | static ssize_t | 151 | static ssize_t |
| @@ -155,7 +156,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
| 155 | acpi_status status; | 156 | acpi_status status; |
| 156 | acpi_object_type type = 0; | 157 | acpi_object_type type = 0; |
| 157 | struct acpi_device *acpi_device = to_acpi_device(d); | 158 | struct acpi_device *acpi_device = to_acpi_device(d); |
| 158 | struct task_struct *task; | ||
| 159 | 159 | ||
| 160 | if ((!count) || (buf[0] != '1')) { | 160 | if ((!count) || (buf[0] != '1')) { |
| 161 | return -EINVAL; | 161 | return -EINVAL; |
| @@ -172,11 +172,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
| 172 | goto err; | 172 | goto err; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | /* remove the device in another thread to fix the deadlock issue */ | 175 | acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle); |
| 176 | task = kthread_run(acpi_bus_hot_remove_device, | ||
| 177 | acpi_device->handle, "acpi_hot_remove_device"); | ||
| 178 | if (IS_ERR(task)) | ||
| 179 | ret = PTR_ERR(task); | ||
| 180 | err: | 176 | err: |
| 181 | return ret; | 177 | return ret; |
| 182 | } | 178 | } |
| @@ -198,12 +194,12 @@ acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *b | |||
| 198 | int result; | 194 | int result; |
| 199 | 195 | ||
| 200 | result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); | 196 | result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); |
| 201 | if(result) | 197 | if (result) |
| 202 | goto end; | 198 | goto end; |
| 203 | 199 | ||
| 204 | result = sprintf(buf, "%s\n", (char*)path.pointer); | 200 | result = sprintf(buf, "%s\n", (char*)path.pointer); |
| 205 | kfree(path.pointer); | 201 | kfree(path.pointer); |
| 206 | end: | 202 | end: |
| 207 | return result; | 203 | return result; |
| 208 | } | 204 | } |
| 209 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); | 205 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); |
| @@ -217,21 +213,21 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
| 217 | /* | 213 | /* |
| 218 | * Devices gotten from FADT don't have a "path" attribute | 214 | * Devices gotten from FADT don't have a "path" attribute |
| 219 | */ | 215 | */ |
| 220 | if(dev->handle) { | 216 | if (dev->handle) { |
| 221 | result = device_create_file(&dev->dev, &dev_attr_path); | 217 | result = device_create_file(&dev->dev, &dev_attr_path); |
| 222 | if(result) | 218 | if (result) |
| 223 | goto end; | 219 | goto end; |
| 224 | } | 220 | } |
| 225 | 221 | ||
| 226 | if(dev->flags.hardware_id) { | 222 | if (dev->flags.hardware_id) { |
| 227 | result = device_create_file(&dev->dev, &dev_attr_hid); | 223 | result = device_create_file(&dev->dev, &dev_attr_hid); |
| 228 | if(result) | 224 | if (result) |
| 229 | goto end; | 225 | goto end; |
| 230 | } | 226 | } |
| 231 | 227 | ||
| 232 | if (dev->flags.hardware_id || dev->flags.compatible_ids){ | 228 | if (dev->flags.hardware_id || dev->flags.compatible_ids) { |
| 233 | result = device_create_file(&dev->dev, &dev_attr_modalias); | 229 | result = device_create_file(&dev->dev, &dev_attr_modalias); |
| 234 | if(result) | 230 | if (result) |
| 235 | goto end; | 231 | goto end; |
| 236 | } | 232 | } |
| 237 | 233 | ||
| @@ -242,7 +238,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
| 242 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); | 238 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); |
| 243 | if (ACPI_SUCCESS(status)) | 239 | if (ACPI_SUCCESS(status)) |
| 244 | result = device_create_file(&dev->dev, &dev_attr_eject); | 240 | result = device_create_file(&dev->dev, &dev_attr_eject); |
| 245 | end: | 241 | end: |
| 246 | return result; | 242 | return result; |
| 247 | } | 243 | } |
| 248 | 244 | ||
| @@ -262,9 +258,9 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
| 262 | if (dev->flags.hardware_id || dev->flags.compatible_ids) | 258 | if (dev->flags.hardware_id || dev->flags.compatible_ids) |
| 263 | device_remove_file(&dev->dev, &dev_attr_modalias); | 259 | device_remove_file(&dev->dev, &dev_attr_modalias); |
| 264 | 260 | ||
| 265 | if(dev->flags.hardware_id) | 261 | if (dev->flags.hardware_id) |
| 266 | device_remove_file(&dev->dev, &dev_attr_hid); | 262 | device_remove_file(&dev->dev, &dev_attr_hid); |
| 267 | if(dev->handle) | 263 | if (dev->handle) |
| 268 | device_remove_file(&dev->dev, &dev_attr_path); | 264 | device_remove_file(&dev->dev, &dev_attr_path); |
| 269 | } | 265 | } |
| 270 | /* -------------------------------------------------------------------------- | 266 | /* -------------------------------------------------------------------------- |
| @@ -512,7 +508,7 @@ static int acpi_device_register(struct acpi_device *device, | |||
| 512 | break; | 508 | break; |
| 513 | } | 509 | } |
| 514 | } | 510 | } |
| 515 | if(!found) { | 511 | if (!found) { |
| 516 | acpi_device_bus_id = new_bus_id; | 512 | acpi_device_bus_id = new_bus_id; |
| 517 | strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); | 513 | strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); |
| 518 | acpi_device_bus_id->instance_no = 0; | 514 | acpi_device_bus_id->instance_no = 0; |
| @@ -530,22 +526,21 @@ static int acpi_device_register(struct acpi_device *device, | |||
| 530 | if (device->parent) | 526 | if (device->parent) |
| 531 | device->dev.parent = &parent->dev; | 527 | device->dev.parent = &parent->dev; |
| 532 | device->dev.bus = &acpi_bus_type; | 528 | device->dev.bus = &acpi_bus_type; |
| 533 | device_initialize(&device->dev); | ||
| 534 | device->dev.release = &acpi_device_release; | 529 | device->dev.release = &acpi_device_release; |
| 535 | result = device_add(&device->dev); | 530 | result = device_register(&device->dev); |
| 536 | if(result) { | 531 | if (result) { |
| 537 | dev_err(&device->dev, "Error adding device\n"); | 532 | dev_err(&device->dev, "Error registering device\n"); |
| 538 | goto end; | 533 | goto end; |
| 539 | } | 534 | } |
| 540 | 535 | ||
| 541 | result = acpi_device_setup_files(device); | 536 | result = acpi_device_setup_files(device); |
| 542 | if(result) | 537 | if (result) |
| 543 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", | 538 | printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", |
| 544 | dev_name(&device->dev)); | 539 | dev_name(&device->dev)); |
| 545 | 540 | ||
| 546 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; | 541 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
| 547 | return 0; | 542 | return 0; |
| 548 | end: | 543 | end: |
| 549 | mutex_lock(&acpi_device_lock); | 544 | mutex_lock(&acpi_device_lock); |
| 550 | if (device->parent) | 545 | if (device->parent) |
| 551 | list_del(&device->node); | 546 | list_del(&device->node); |
| @@ -577,7 +572,7 @@ static void acpi_device_unregister(struct acpi_device *device, int type) | |||
| 577 | * @device: the device to add and initialize | 572 | * @device: the device to add and initialize |
| 578 | * @driver: driver for the device | 573 | * @driver: driver for the device |
| 579 | * | 574 | * |
| 580 | * Used to initialize a device via its device driver. Called whenever a | 575 | * Used to initialize a device via its device driver. Called whenever a |
| 581 | * driver is bound to a device. Invokes the driver's add() ops. | 576 | * driver is bound to a device. Invokes the driver's add() ops. |
| 582 | */ | 577 | */ |
| 583 | static int | 578 | static int |
| @@ -585,7 +580,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) | |||
| 585 | { | 580 | { |
| 586 | int result = 0; | 581 | int result = 0; |
| 587 | 582 | ||
| 588 | |||
| 589 | if (!device || !driver) | 583 | if (!device || !driver) |
| 590 | return -EINVAL; | 584 | return -EINVAL; |
| 591 | 585 | ||
| @@ -802,7 +796,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 802 | if (!acpi_match_device_ids(device, button_device_ids)) | 796 | if (!acpi_match_device_ids(device, button_device_ids)) |
| 803 | device->wakeup.flags.run_wake = 1; | 797 | device->wakeup.flags.run_wake = 1; |
| 804 | 798 | ||
| 805 | end: | 799 | end: |
| 806 | if (ACPI_FAILURE(status)) | 800 | if (ACPI_FAILURE(status)) |
| 807 | device->flags.wake_capable = 0; | 801 | device->flags.wake_capable = 0; |
| 808 | return 0; | 802 | return 0; |
| @@ -1070,7 +1064,7 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
| 1070 | break; | 1064 | break; |
| 1071 | } | 1065 | } |
| 1072 | 1066 | ||
| 1073 | /* | 1067 | /* |
| 1074 | * \_SB | 1068 | * \_SB |
| 1075 | * ---- | 1069 | * ---- |
| 1076 | * Fix for the system root bus device -- the only root-level device. | 1070 | * Fix for the system root bus device -- the only root-level device. |
| @@ -1320,7 +1314,7 @@ acpi_add_single_object(struct acpi_device **child, | |||
| 1320 | device->parent->ops.bind(device); | 1314 | device->parent->ops.bind(device); |
| 1321 | } | 1315 | } |
| 1322 | 1316 | ||
| 1323 | end: | 1317 | end: |
| 1324 | if (!result) | 1318 | if (!result) |
| 1325 | *child = device; | 1319 | *child = device; |
| 1326 | else { | 1320 | else { |
| @@ -1464,7 +1458,6 @@ acpi_bus_add(struct acpi_device **child, | |||
| 1464 | 1458 | ||
| 1465 | return result; | 1459 | return result; |
| 1466 | } | 1460 | } |
| 1467 | |||
| 1468 | EXPORT_SYMBOL(acpi_bus_add); | 1461 | EXPORT_SYMBOL(acpi_bus_add); |
| 1469 | 1462 | ||
| 1470 | int acpi_bus_start(struct acpi_device *device) | 1463 | int acpi_bus_start(struct acpi_device *device) |
| @@ -1484,7 +1477,6 @@ int acpi_bus_start(struct acpi_device *device) | |||
| 1484 | } | 1477 | } |
| 1485 | return result; | 1478 | return result; |
| 1486 | } | 1479 | } |
| 1487 | |||
| 1488 | EXPORT_SYMBOL(acpi_bus_start); | 1480 | EXPORT_SYMBOL(acpi_bus_start); |
| 1489 | 1481 | ||
| 1490 | int acpi_bus_trim(struct acpi_device *start, int rmdevice) | 1482 | int acpi_bus_trim(struct acpi_device *start, int rmdevice) |
| @@ -1542,7 +1534,6 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice) | |||
| 1542 | } | 1534 | } |
| 1543 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1535 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
| 1544 | 1536 | ||
| 1545 | |||
| 1546 | static int acpi_bus_scan_fixed(struct acpi_device *root) | 1537 | static int acpi_bus_scan_fixed(struct acpi_device *root) |
| 1547 | { | 1538 | { |
| 1548 | int result = 0; | 1539 | int result = 0; |
| @@ -1610,6 +1601,6 @@ int __init acpi_scan_init(void) | |||
| 1610 | if (result) | 1601 | if (result) |
| 1611 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); | 1602 | acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); |
| 1612 | 1603 | ||
| 1613 | Done: | 1604 | Done: |
| 1614 | return result; | 1605 | return result; |
| 1615 | } | 1606 | } |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1bdfb37377e3..8851315ce858 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -76,6 +76,7 @@ MODULE_LICENSE("GPL"); | |||
| 76 | static int brightness_switch_enabled = 1; | 76 | static int brightness_switch_enabled = 1; |
| 77 | module_param(brightness_switch_enabled, bool, 0644); | 77 | module_param(brightness_switch_enabled, bool, 0644); |
| 78 | 78 | ||
| 79 | static int register_count = 0; | ||
| 79 | static int acpi_video_bus_add(struct acpi_device *device); | 80 | static int acpi_video_bus_add(struct acpi_device *device); |
| 80 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 81 | static int acpi_video_bus_remove(struct acpi_device *device, int type); |
| 81 | static int acpi_video_resume(struct acpi_device *device); | 82 | static int acpi_video_resume(struct acpi_device *device); |
| @@ -586,6 +587,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 586 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), | 587 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), |
| 587 | }, | 588 | }, |
| 588 | }, | 589 | }, |
| 590 | { | ||
| 591 | .callback = video_set_bqc_offset, | ||
| 592 | .ident = "Acer Aspire 7720", | ||
| 593 | .matches = { | ||
| 594 | DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), | ||
| 595 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), | ||
| 596 | }, | ||
| 597 | }, | ||
| 589 | {} | 598 | {} |
| 590 | }; | 599 | }; |
| 591 | 600 | ||
| @@ -976,6 +985,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 976 | device->backlight->props.max_brightness = device->brightness->count-3; | 985 | device->backlight->props.max_brightness = device->brightness->count-3; |
| 977 | kfree(name); | 986 | kfree(name); |
| 978 | 987 | ||
| 988 | result = sysfs_create_link(&device->backlight->dev.kobj, | ||
| 989 | &device->dev->dev.kobj, "device"); | ||
| 990 | if (result) | ||
| 991 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 992 | |||
| 979 | device->cdev = thermal_cooling_device_register("LCD", | 993 | device->cdev = thermal_cooling_device_register("LCD", |
| 980 | device->dev, &video_cooling_ops); | 994 | device->dev, &video_cooling_ops); |
| 981 | if (IS_ERR(device->cdev)) | 995 | if (IS_ERR(device->cdev)) |
| @@ -1054,15 +1068,15 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
| 1054 | static int acpi_video_bus_check(struct acpi_video_bus *video) | 1068 | static int acpi_video_bus_check(struct acpi_video_bus *video) |
| 1055 | { | 1069 | { |
| 1056 | acpi_status status = -ENOENT; | 1070 | acpi_status status = -ENOENT; |
| 1057 | struct device *dev; | 1071 | struct pci_dev *dev; |
| 1058 | 1072 | ||
| 1059 | if (!video) | 1073 | if (!video) |
| 1060 | return -EINVAL; | 1074 | return -EINVAL; |
| 1061 | 1075 | ||
| 1062 | dev = acpi_get_physical_pci_device(video->device->handle); | 1076 | dev = acpi_get_pci_dev(video->device->handle); |
| 1063 | if (!dev) | 1077 | if (!dev) |
| 1064 | return -ENODEV; | 1078 | return -ENODEV; |
| 1065 | put_device(dev); | 1079 | pci_dev_put(dev); |
| 1066 | 1080 | ||
| 1067 | /* Since there is no HID, CID and so on for VGA driver, we have | 1081 | /* Since there is no HID, CID and so on for VGA driver, we have |
| 1068 | * to check well known required nodes. | 1082 | * to check well known required nodes. |
| @@ -1990,6 +2004,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 1990 | status = acpi_remove_notify_handler(device->dev->handle, | 2004 | status = acpi_remove_notify_handler(device->dev->handle, |
| 1991 | ACPI_DEVICE_NOTIFY, | 2005 | ACPI_DEVICE_NOTIFY, |
| 1992 | acpi_video_device_notify); | 2006 | acpi_video_device_notify); |
| 2007 | sysfs_remove_link(&device->backlight->dev.kobj, "device"); | ||
| 1993 | backlight_device_unregister(device->backlight); | 2008 | backlight_device_unregister(device->backlight); |
| 1994 | if (device->cdev) { | 2009 | if (device->cdev) { |
| 1995 | sysfs_remove_link(&device->dev->dev.kobj, | 2010 | sysfs_remove_link(&device->dev->dev.kobj, |
| @@ -2318,6 +2333,13 @@ static int __init intel_opregion_present(void) | |||
| 2318 | int acpi_video_register(void) | 2333 | int acpi_video_register(void) |
| 2319 | { | 2334 | { |
| 2320 | int result = 0; | 2335 | int result = 0; |
| 2336 | if (register_count) { | ||
| 2337 | /* | ||
| 2338 | * if the function of acpi_video_register is already called, | ||
| 2339 | * don't register the acpi_vide_bus again and return no error. | ||
| 2340 | */ | ||
| 2341 | return 0; | ||
| 2342 | } | ||
| 2321 | 2343 | ||
| 2322 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2344 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
| 2323 | if (!acpi_video_dir) | 2345 | if (!acpi_video_dir) |
| @@ -2329,10 +2351,35 @@ int acpi_video_register(void) | |||
| 2329 | return -ENODEV; | 2351 | return -ENODEV; |
| 2330 | } | 2352 | } |
| 2331 | 2353 | ||
| 2354 | /* | ||
| 2355 | * When the acpi_video_bus is loaded successfully, increase | ||
| 2356 | * the counter reference. | ||
| 2357 | */ | ||
| 2358 | register_count = 1; | ||
| 2359 | |||
| 2332 | return 0; | 2360 | return 0; |
| 2333 | } | 2361 | } |
| 2334 | EXPORT_SYMBOL(acpi_video_register); | 2362 | EXPORT_SYMBOL(acpi_video_register); |
| 2335 | 2363 | ||
| 2364 | void acpi_video_unregister(void) | ||
| 2365 | { | ||
| 2366 | if (!register_count) { | ||
| 2367 | /* | ||
| 2368 | * If the acpi video bus is already unloaded, don't | ||
| 2369 | * unload it again and return directly. | ||
| 2370 | */ | ||
| 2371 | return; | ||
| 2372 | } | ||
| 2373 | acpi_bus_unregister_driver(&acpi_video_bus); | ||
| 2374 | |||
| 2375 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
| 2376 | |||
| 2377 | register_count = 0; | ||
| 2378 | |||
| 2379 | return; | ||
| 2380 | } | ||
| 2381 | EXPORT_SYMBOL(acpi_video_unregister); | ||
| 2382 | |||
| 2336 | /* | 2383 | /* |
| 2337 | * This is kind of nasty. Hardware using Intel chipsets may require | 2384 | * This is kind of nasty. Hardware using Intel chipsets may require |
| 2338 | * the video opregion code to be run first in order to initialise | 2385 | * the video opregion code to be run first in order to initialise |
| @@ -2350,16 +2397,12 @@ static int __init acpi_video_init(void) | |||
| 2350 | return acpi_video_register(); | 2397 | return acpi_video_register(); |
| 2351 | } | 2398 | } |
| 2352 | 2399 | ||
| 2353 | void acpi_video_exit(void) | 2400 | static void __exit acpi_video_exit(void) |
| 2354 | { | 2401 | { |
| 2355 | 2402 | acpi_video_unregister(); | |
| 2356 | acpi_bus_unregister_driver(&acpi_video_bus); | ||
| 2357 | |||
| 2358 | remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); | ||
| 2359 | 2403 | ||
| 2360 | return; | 2404 | return; |
| 2361 | } | 2405 | } |
| 2362 | EXPORT_SYMBOL(acpi_video_exit); | ||
| 2363 | 2406 | ||
| 2364 | module_init(acpi_video_init); | 2407 | module_init(acpi_video_init); |
| 2365 | module_exit(acpi_video_exit); | 2408 | module_exit(acpi_video_exit); |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 09737275e25f..7cd2b63435ea 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | * assinged | 10 | * assinged |
| 11 | * | 11 | * |
| 12 | * After PCI devices are glued with ACPI devices | 12 | * After PCI devices are glued with ACPI devices |
| 13 | * acpi_get_physical_pci_device() can be called to identify ACPI graphics | 13 | * acpi_get_pci_dev() can be called to identify ACPI graphics |
| 14 | * devices for which a real graphics card is plugged in | 14 | * devices for which a real graphics card is plugged in |
| 15 | * | 15 | * |
| 16 | * Now acpi_video_get_capabilities() can be called to check which | 16 | * Now acpi_video_get_capabilities() can be called to check which |
| @@ -36,6 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | #include <linux/acpi.h> | 37 | #include <linux/acpi.h> |
| 38 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
| 39 | #include <linux/pci.h> | ||
| 39 | 40 | ||
| 40 | ACPI_MODULE_NAME("video"); | 41 | ACPI_MODULE_NAME("video"); |
| 41 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 42 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
| @@ -109,7 +110,7 @@ static acpi_status | |||
| 109 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | 110 | find_video(acpi_handle handle, u32 lvl, void *context, void **rv) |
| 110 | { | 111 | { |
| 111 | long *cap = context; | 112 | long *cap = context; |
| 112 | struct device *dev; | 113 | struct pci_dev *dev; |
| 113 | struct acpi_device *acpi_dev; | 114 | struct acpi_device *acpi_dev; |
| 114 | 115 | ||
| 115 | const struct acpi_device_id video_ids[] = { | 116 | const struct acpi_device_id video_ids[] = { |
| @@ -120,10 +121,10 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 120 | return AE_OK; | 121 | return AE_OK; |
| 121 | 122 | ||
| 122 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { | 123 | if (!acpi_match_device_ids(acpi_dev, video_ids)) { |
| 123 | dev = acpi_get_physical_pci_device(handle); | 124 | dev = acpi_get_pci_dev(handle); |
| 124 | if (!dev) | 125 | if (!dev) |
| 125 | return AE_OK; | 126 | return AE_OK; |
| 126 | put_device(dev); | 127 | pci_dev_put(dev); |
| 127 | *cap |= acpi_is_video_device(acpi_dev); | 128 | *cap |= acpi_is_video_device(acpi_dev); |
| 128 | } | 129 | } |
| 129 | return AE_OK; | 130 | return AE_OK; |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 3d763fdf99b7..246650673010 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
| @@ -207,6 +207,16 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) | |||
| 207 | void __iomem *tmp; | 207 | void __iomem *tmp; |
| 208 | int i, ret; | 208 | int i, ret; |
| 209 | 209 | ||
| 210 | device_initialize(&dev->dev); | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Copy from device_add | ||
| 214 | */ | ||
| 215 | if (dev->dev.init_name) { | ||
| 216 | dev_set_name(&dev->dev, "%s", dev->dev.init_name); | ||
| 217 | dev->dev.init_name = NULL; | ||
| 218 | } | ||
| 219 | |||
| 210 | dev->dev.release = amba_device_release; | 220 | dev->dev.release = amba_device_release; |
| 211 | dev->dev.bus = &amba_bustype; | 221 | dev->dev.bus = &amba_bustype; |
| 212 | dev->dev.dma_mask = &dev->dma_mask; | 222 | dev->dev.dma_mask = &dev->dma_mask; |
| @@ -240,7 +250,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) | |||
| 240 | goto err_release; | 250 | goto err_release; |
| 241 | } | 251 | } |
| 242 | 252 | ||
| 243 | ret = device_register(&dev->dev); | 253 | ret = device_add(&dev->dev); |
| 244 | if (ret) | 254 | if (ret) |
| 245 | goto err_release; | 255 | goto err_release; |
| 246 | 256 | ||
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 15a23031833f..336eb1ed73cc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -513,6 +513,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
| 513 | { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ | 513 | { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ |
| 514 | { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ | 514 | { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ |
| 515 | { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ | 515 | { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ |
| 516 | { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ | ||
| 516 | { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ | 517 | { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ |
| 517 | { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ | 518 | { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ |
| 518 | { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ | 519 | { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 045a486a09ea..2c6aedaef718 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -3392,17 +3392,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) | |||
| 3392 | 3392 | ||
| 3393 | static int ata_dev_set_mode(struct ata_device *dev) | 3393 | static int ata_dev_set_mode(struct ata_device *dev) |
| 3394 | { | 3394 | { |
| 3395 | struct ata_port *ap = dev->link->ap; | ||
| 3395 | struct ata_eh_context *ehc = &dev->link->eh_context; | 3396 | struct ata_eh_context *ehc = &dev->link->eh_context; |
| 3397 | const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER; | ||
| 3396 | const char *dev_err_whine = ""; | 3398 | const char *dev_err_whine = ""; |
| 3397 | int ign_dev_err = 0; | 3399 | int ign_dev_err = 0; |
| 3398 | unsigned int err_mask; | 3400 | unsigned int err_mask = 0; |
| 3399 | int rc; | 3401 | int rc; |
| 3400 | 3402 | ||
| 3401 | dev->flags &= ~ATA_DFLAG_PIO; | 3403 | dev->flags &= ~ATA_DFLAG_PIO; |
| 3402 | if (dev->xfer_shift == ATA_SHIFT_PIO) | 3404 | if (dev->xfer_shift == ATA_SHIFT_PIO) |
| 3403 | dev->flags |= ATA_DFLAG_PIO; | 3405 | dev->flags |= ATA_DFLAG_PIO; |
| 3404 | 3406 | ||
| 3405 | err_mask = ata_dev_set_xfermode(dev); | 3407 | if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id)) |
| 3408 | dev_err_whine = " (SET_XFERMODE skipped)"; | ||
| 3409 | else { | ||
| 3410 | if (nosetxfer) | ||
| 3411 | ata_dev_printk(dev, KERN_WARNING, | ||
| 3412 | "NOSETXFER but PATA detected - can't " | ||
| 3413 | "skip SETXFER, might malfunction\n"); | ||
| 3414 | err_mask = ata_dev_set_xfermode(dev); | ||
| 3415 | } | ||
| 3406 | 3416 | ||
| 3407 | if (err_mask & ~AC_ERR_DEV) | 3417 | if (err_mask & ~AC_ERR_DEV) |
| 3408 | goto fail; | 3418 | goto fail; |
| @@ -4297,6 +4307,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 4297 | /* Devices which aren't very happy with higher link speeds */ | 4307 | /* Devices which aren't very happy with higher link speeds */ |
| 4298 | { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, | 4308 | { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, |
| 4299 | 4309 | ||
| 4310 | /* | ||
| 4311 | * Devices which choke on SETXFER. Applies only if both the | ||
| 4312 | * device and controller are SATA. | ||
| 4313 | */ | ||
| 4314 | { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, | ||
| 4315 | |||
| 4300 | /* End Marker */ | 4316 | /* End Marker */ |
| 4301 | { } | 4317 | { } |
| 4302 | }; | 4318 | }; |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index fa22f94ca415..1a07c061f644 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
| @@ -2517,6 +2517,10 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2517 | 2517 | ||
| 2518 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | 2518 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); |
| 2519 | rc = ata_do_reset(link, reset, classes, deadline, true); | 2519 | rc = ata_do_reset(link, reset, classes, deadline, true); |
| 2520 | if (rc) { | ||
| 2521 | failed_link = link; | ||
| 2522 | goto fail; | ||
| 2523 | } | ||
| 2520 | } | 2524 | } |
| 2521 | } else { | 2525 | } else { |
| 2522 | if (verbose) | 2526 | if (verbose) |
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 4b27617be26d..8561a9f195c1 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c | |||
| @@ -312,11 +312,12 @@ err_ide_ioremap: | |||
| 312 | static int __devexit pata_at91_remove(struct platform_device *pdev) | 312 | static int __devexit pata_at91_remove(struct platform_device *pdev) |
| 313 | { | 313 | { |
| 314 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 314 | struct ata_host *host = dev_get_drvdata(&pdev->dev); |
| 315 | struct at91_ide_info *info = host->private_data; | 315 | struct at91_ide_info *info; |
| 316 | struct device *dev = &pdev->dev; | 316 | struct device *dev = &pdev->dev; |
| 317 | 317 | ||
| 318 | if (!host) | 318 | if (!host) |
| 319 | return 0; | 319 | return 0; |
| 320 | info = host->private_data; | ||
| 320 | 321 | ||
| 321 | ata_host_detach(host); | 322 | ata_host_detach(host); |
| 322 | 323 | ||
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index e8beb8e5b626..05dd307e8f02 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c | |||
| @@ -428,6 +428,9 @@ int devres_release_all(struct device *dev) | |||
| 428 | { | 428 | { |
| 429 | unsigned long flags; | 429 | unsigned long flags; |
| 430 | 430 | ||
| 431 | /* Looks like an uninitialized device structure */ | ||
| 432 | if (WARN_ON(dev->devres_head.next == NULL)) | ||
| 433 | return -ENODEV; | ||
| 431 | spin_lock_irqsave(&dev->devres_lock, flags); | 434 | spin_lock_irqsave(&dev->devres_lock, flags); |
| 432 | return release_nodes(dev, dev->devres_head.next, &dev->devres_head, | 435 | return release_nodes(dev, dev->devres_head.next, &dev->devres_head, |
| 433 | flags); | 436 | flags); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ddeb819c8f87..f285f441fab9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -217,8 +217,10 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 217 | ret_count = -ENODEV; | 217 | ret_count = -ENODEV; |
| 218 | goto out; | 218 | goto out; |
| 219 | } | 219 | } |
| 220 | if (offset > fw->size) | 220 | if (offset > fw->size) { |
| 221 | return 0; | 221 | ret_count = 0; |
| 222 | goto out; | ||
| 223 | } | ||
| 222 | if (count > fw->size - offset) | 224 | if (count > fw->size - offset) |
| 223 | count = fw->size - offset; | 225 | count = fw->size - offset; |
| 224 | 226 | ||
| @@ -357,7 +359,7 @@ static void fw_dev_release(struct device *dev) | |||
| 357 | kfree(fw_priv->pages); | 359 | kfree(fw_priv->pages); |
| 358 | kfree(fw_priv->fw_id); | 360 | kfree(fw_priv->fw_id); |
| 359 | kfree(fw_priv); | 361 | kfree(fw_priv); |
| 360 | put_device(dev); | 362 | kfree(dev); |
| 361 | 363 | ||
| 362 | module_put(THIS_MODULE); | 364 | module_put(THIS_MODULE); |
| 363 | } | 365 | } |
| @@ -408,13 +410,11 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, | |||
| 408 | if (retval) { | 410 | if (retval) { |
| 409 | dev_err(device, "%s: device_register failed\n", __func__); | 411 | dev_err(device, "%s: device_register failed\n", __func__); |
| 410 | put_device(f_dev); | 412 | put_device(f_dev); |
| 411 | goto error_kfree_fw_id; | 413 | return retval; |
| 412 | } | 414 | } |
| 413 | *dev_p = f_dev; | 415 | *dev_p = f_dev; |
| 414 | return 0; | 416 | return 0; |
| 415 | 417 | ||
| 416 | error_kfree_fw_id: | ||
| 417 | kfree(fw_priv->fw_id); | ||
| 418 | error_kfree: | 418 | error_kfree: |
| 419 | kfree(f_dev); | 419 | kfree(f_dev); |
| 420 | kfree(fw_priv); | 420 | kfree(fw_priv); |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index fae725458981..58a3e572f2c9 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -762,6 +762,7 @@ static int dpm_prepare(pm_message_t state) | |||
| 762 | dev->power.status = DPM_ON; | 762 | dev->power.status = DPM_ON; |
| 763 | if (error == -EAGAIN) { | 763 | if (error == -EAGAIN) { |
| 764 | put_device(dev); | 764 | put_device(dev); |
| 765 | error = 0; | ||
| 765 | continue; | 766 | continue; |
| 766 | } | 767 | } |
| 767 | printk(KERN_ERR "PM: Failed to prepare device %s " | 768 | printk(KERN_ERR "PM: Failed to prepare device %s " |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 668dc234b8e2..1e6b7c14f697 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
| 37 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/smp_lock.h> | ||
| 39 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
| 40 | #include <linux/reboot.h> | 41 | #include <linux/reboot.h> |
| 41 | #include <linux/spinlock.h> | 42 | #include <linux/spinlock.h> |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index bb72ada9f074..1d886e079c58 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -298,6 +298,22 @@ config BLK_DEV_NBD | |||
| 298 | 298 | ||
| 299 | If unsure, say N. | 299 | If unsure, say N. |
| 300 | 300 | ||
| 301 | config BLK_DEV_OSD | ||
| 302 | tristate "OSD object-as-blkdev support" | ||
| 303 | depends on SCSI_OSD_ULD | ||
| 304 | ---help--- | ||
| 305 | Saying Y or M here will allow the exporting of a single SCSI | ||
| 306 | OSD (object-based storage) object as a Linux block device. | ||
| 307 | |||
| 308 | For example, if you create a 2G object on an OSD device, | ||
| 309 | you can then use this module to present that 2G object as | ||
| 310 | a Linux block device. | ||
| 311 | |||
| 312 | To compile this driver as a module, choose M here: the | ||
| 313 | module will be called osdblk. | ||
| 314 | |||
| 315 | If unsure, say N. | ||
| 316 | |||
| 301 | config BLK_DEV_SX8 | 317 | config BLK_DEV_SX8 |
| 302 | tristate "Promise SATA SX8 support" | 318 | tristate "Promise SATA SX8 support" |
| 303 | depends on PCI | 319 | depends on PCI |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 7755a5e2a85e..cdaa3f8fddf0 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o | |||
| 23 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o | 23 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o |
| 24 | obj-$(CONFIG_MG_DISK) += mg_disk.o | 24 | obj-$(CONFIG_MG_DISK) += mg_disk.o |
| 25 | obj-$(CONFIG_SUNVDC) += sunvdc.o | 25 | obj-$(CONFIG_SUNVDC) += sunvdc.o |
| 26 | obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o | ||
| 26 | 27 | ||
| 27 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o | 28 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o |
| 28 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o | 29 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 9c6e5b0fe894..2f07b7c99a95 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
| @@ -1645,7 +1645,7 @@ static int __init fd_probe_drives(void) | |||
| 1645 | { | 1645 | { |
| 1646 | int drive,drives,nomem; | 1646 | int drive,drives,nomem; |
| 1647 | 1647 | ||
| 1648 | printk(KERN_INFO "FD: probing units\n" KERN_INFO "found "); | 1648 | printk(KERN_INFO "FD: probing units\nfound "); |
| 1649 | drives=0; | 1649 | drives=0; |
| 1650 | nomem=0; | 1650 | nomem=0; |
| 1651 | for(drive=0;drive<FD_MAX_UNITS;drive++) { | 1651 | for(drive=0;drive<FD_MAX_UNITS;drive++) { |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c7a527c08a09..a52cc7fe45ea 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 30 | #include <linux/major.h> | 31 | #include <linux/major.h> |
| 31 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
| @@ -226,8 +227,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c) | |||
| 226 | 227 | ||
| 227 | static inline void removeQ(CommandList_struct *c) | 228 | static inline void removeQ(CommandList_struct *c) |
| 228 | { | 229 | { |
| 229 | if (WARN_ON(hlist_unhashed(&c->list))) | 230 | /* |
| 231 | * After kexec/dump some commands might still | ||
| 232 | * be in flight, which the firmware will try | ||
| 233 | * to complete. Resetting the firmware doesn't work | ||
| 234 | * with old fw revisions, so we have to mark | ||
| 235 | * them off as 'stale' to prevent the driver from | ||
| 236 | * falling over. | ||
| 237 | */ | ||
| 238 | if (WARN_ON(hlist_unhashed(&c->list))) { | ||
| 239 | c->cmd_type = CMD_MSG_STALE; | ||
| 230 | return; | 240 | return; |
| 241 | } | ||
| 231 | 242 | ||
| 232 | hlist_del_init(&c->list); | 243 | hlist_del_init(&c->list); |
| 233 | } | 244 | } |
| @@ -4246,7 +4257,8 @@ static void fail_all_cmds(unsigned long ctlr) | |||
| 4246 | while (!hlist_empty(&h->cmpQ)) { | 4257 | while (!hlist_empty(&h->cmpQ)) { |
| 4247 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); | 4258 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); |
| 4248 | removeQ(c); | 4259 | removeQ(c); |
| 4249 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | 4260 | if (c->cmd_type != CMD_MSG_STALE) |
| 4261 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
| 4250 | if (c->cmd_type == CMD_RWREQ) { | 4262 | if (c->cmd_type == CMD_RWREQ) { |
| 4251 | complete_command(h, c, 0); | 4263 | complete_command(h, c, 0); |
| 4252 | } else if (c->cmd_type == CMD_IOCTL_PEND) | 4264 | } else if (c->cmd_type == CMD_IOCTL_PEND) |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd665b00c7c5..dbaed1ea0da3 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
| @@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct { | |||
| 274 | #define CMD_SCSI 0x03 | 274 | #define CMD_SCSI 0x03 |
| 275 | #define CMD_MSG_DONE 0x04 | 275 | #define CMD_MSG_DONE 0x04 |
| 276 | #define CMD_MSG_TIMEOUT 0x05 | 276 | #define CMD_MSG_TIMEOUT 0x05 |
| 277 | #define CMD_MSG_STALE 0xff | ||
| 277 | 278 | ||
| 278 | /* This structure needs to be divisible by 8 for new | 279 | /* This structure needs to be divisible by 8 for new |
| 279 | * indexing method. | 280 | * indexing method. |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 862b40c90181..91b753013780 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -3327,7 +3327,10 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
| 3327 | if (!capable(CAP_SYS_ADMIN)) | 3327 | if (!capable(CAP_SYS_ADMIN)) |
| 3328 | return -EPERM; | 3328 | return -EPERM; |
| 3329 | mutex_lock(&open_lock); | 3329 | mutex_lock(&open_lock); |
| 3330 | LOCK_FDC(drive, 1); | 3330 | if (lock_fdc(drive, 1)) { |
| 3331 | mutex_unlock(&open_lock); | ||
| 3332 | return -EINTR; | ||
| 3333 | } | ||
| 3331 | floppy_type[type] = *g; | 3334 | floppy_type[type] = *g; |
| 3332 | floppy_type[type].name = "user format"; | 3335 | floppy_type[type].name = "user format"; |
| 3333 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) | 3336 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 801f4ab83302..5757188cd1fb 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -61,7 +61,6 @@ | |||
| 61 | #include <linux/blkdev.h> | 61 | #include <linux/blkdev.h> |
| 62 | #include <linux/blkpg.h> | 62 | #include <linux/blkpg.h> |
| 63 | #include <linux/init.h> | 63 | #include <linux/init.h> |
| 64 | #include <linux/smp_lock.h> | ||
| 65 | #include <linux/swap.h> | 64 | #include <linux/swap.h> |
| 66 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
| 67 | #include <linux/loop.h> | 66 | #include <linux/loop.h> |
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c new file mode 100644 index 000000000000..13c1aee6aa3f --- /dev/null +++ b/drivers/block/osdblk.c | |||
| @@ -0,0 +1,701 @@ | |||
| 1 | |||
| 2 | /* | ||
| 3 | osdblk.c -- Export a single SCSI OSD object as a Linux block device | ||
| 4 | |||
| 5 | |||
| 6 | Copyright 2009 Red Hat, Inc. | ||
| 7 | |||
| 8 | This program is free software; you can redistribute it and/or modify | ||
| 9 | it under the terms of the GNU General Public License as published by | ||
| 10 | the Free Software Foundation. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | |||
| 22 | Instructions for use | ||
| 23 | -------------------- | ||
| 24 | |||
| 25 | 1) Map a Linux block device to an existing OSD object. | ||
| 26 | |||
| 27 | In this example, we will use partition id 1234, object id 5678, | ||
| 28 | OSD device /dev/osd1. | ||
| 29 | |||
| 30 | $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add | ||
| 31 | |||
| 32 | |||
| 33 | 2) List all active blkdev<->object mappings. | ||
| 34 | |||
| 35 | In this example, we have performed step #1 twice, creating two blkdevs, | ||
| 36 | mapped to two separate OSD objects. | ||
| 37 | |||
| 38 | $ cat /sys/class/osdblk/list | ||
| 39 | 0 174 1234 5678 /dev/osd1 | ||
| 40 | 1 179 1994 897123 /dev/osd0 | ||
| 41 | |||
| 42 | The columns, in order, are: | ||
| 43 | - blkdev unique id | ||
| 44 | - blkdev assigned major | ||
| 45 | - OSD object partition id | ||
| 46 | - OSD object id | ||
| 47 | - OSD device | ||
| 48 | |||
| 49 | |||
| 50 | 3) Remove an active blkdev<->object mapping. | ||
| 51 | |||
| 52 | In this example, we remove the mapping with blkdev unique id 1. | ||
| 53 | |||
| 54 | $ echo 1 > /sys/class/osdblk/remove | ||
| 55 | |||
| 56 | |||
| 57 | NOTE: The actual creation and deletion of OSD objects is outside the scope | ||
| 58 | of this driver. | ||
| 59 | |||
| 60 | */ | ||
| 61 | |||
| 62 | #include <linux/kernel.h> | ||
| 63 | #include <linux/device.h> | ||
| 64 | #include <linux/module.h> | ||
| 65 | #include <linux/fs.h> | ||
| 66 | #include <scsi/osd_initiator.h> | ||
| 67 | #include <scsi/osd_attributes.h> | ||
| 68 | #include <scsi/osd_sec.h> | ||
| 69 | #include <scsi/scsi_device.h> | ||
| 70 | |||
| 71 | #define DRV_NAME "osdblk" | ||
| 72 | #define PFX DRV_NAME ": " | ||
| 73 | |||
| 74 | /* #define _OSDBLK_DEBUG */ | ||
| 75 | #ifdef _OSDBLK_DEBUG | ||
| 76 | #define OSDBLK_DEBUG(fmt, a...) \ | ||
| 77 | printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a) | ||
| 78 | #else | ||
| 79 | #define OSDBLK_DEBUG(fmt, a...) \ | ||
| 80 | do { if (0) printk(fmt, ##a); } while (0) | ||
| 81 | #endif | ||
| 82 | |||
| 83 | MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>"); | ||
| 84 | MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko"); | ||
| 85 | MODULE_LICENSE("GPL"); | ||
| 86 | |||
| 87 | struct osdblk_device; | ||
| 88 | |||
| 89 | enum { | ||
| 90 | OSDBLK_MINORS_PER_MAJOR = 256, /* max minors per blkdev */ | ||
| 91 | OSDBLK_MAX_REQ = 32, /* max parallel requests */ | ||
| 92 | OSDBLK_OP_TIMEOUT = 4 * 60, /* sync OSD req timeout */ | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct osdblk_request { | ||
| 96 | struct request *rq; /* blk layer request */ | ||
| 97 | struct bio *bio; /* cloned bio */ | ||
| 98 | struct osdblk_device *osdev; /* associated blkdev */ | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct osdblk_device { | ||
| 102 | int id; /* blkdev unique id */ | ||
| 103 | |||
| 104 | int major; /* blkdev assigned major */ | ||
| 105 | struct gendisk *disk; /* blkdev's gendisk and rq */ | ||
| 106 | struct request_queue *q; | ||
| 107 | |||
| 108 | struct osd_dev *osd; /* associated OSD */ | ||
| 109 | |||
| 110 | char name[32]; /* blkdev name, e.g. osdblk34 */ | ||
| 111 | |||
| 112 | spinlock_t lock; /* queue lock */ | ||
| 113 | |||
| 114 | struct osd_obj_id obj; /* OSD partition, obj id */ | ||
| 115 | uint8_t obj_cred[OSD_CAP_LEN]; /* OSD cred */ | ||
| 116 | |||
| 117 | struct osdblk_request req[OSDBLK_MAX_REQ]; /* request table */ | ||
| 118 | |||
| 119 | struct list_head node; | ||
| 120 | |||
| 121 | char osd_path[0]; /* OSD device path */ | ||
| 122 | }; | ||
| 123 | |||
| 124 | static struct class *class_osdblk; /* /sys/class/osdblk */ | ||
| 125 | static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ | ||
| 126 | static LIST_HEAD(osdblkdev_list); | ||
| 127 | |||
| 128 | static struct block_device_operations osdblk_bd_ops = { | ||
| 129 | .owner = THIS_MODULE, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static const struct osd_attr g_attr_logical_length = ATTR_DEF( | ||
| 133 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | ||
| 134 | |||
| 135 | static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN], | ||
| 136 | const struct osd_obj_id *obj) | ||
| 137 | { | ||
| 138 | osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); | ||
| 139 | } | ||
| 140 | |||
| 141 | /* copied from exofs; move to libosd? */ | ||
| 142 | /* | ||
| 143 | * Perform a synchronous OSD operation. copied from exofs; move to libosd? | ||
| 144 | */ | ||
| 145 | static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential) | ||
| 146 | { | ||
| 147 | int ret; | ||
| 148 | |||
| 149 | or->timeout = timeout; | ||
| 150 | ret = osd_finalize_request(or, 0, credential, NULL); | ||
| 151 | if (ret) | ||
| 152 | return ret; | ||
| 153 | |||
| 154 | ret = osd_execute_request(or); | ||
| 155 | |||
| 156 | /* osd_req_decode_sense(or, ret); */ | ||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Perform an asynchronous OSD operation. copied from exofs; move to libosd? | ||
| 162 | */ | ||
| 163 | static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done, | ||
| 164 | void *caller_context, u8 *cred) | ||
| 165 | { | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | ret = osd_finalize_request(or, 0, cred, NULL); | ||
| 169 | if (ret) | ||
| 170 | return ret; | ||
| 171 | |||
| 172 | ret = osd_execute_request_async(or, async_done, caller_context); | ||
| 173 | |||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* copied from exofs; move to libosd? */ | ||
| 178 | static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) | ||
| 179 | { | ||
| 180 | struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ | ||
| 181 | void *iter = NULL; | ||
| 182 | int nelem; | ||
| 183 | |||
| 184 | do { | ||
| 185 | nelem = 1; | ||
| 186 | osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); | ||
| 187 | if ((cur_attr.attr_page == attr->attr_page) && | ||
| 188 | (cur_attr.attr_id == attr->attr_id)) { | ||
| 189 | attr->len = cur_attr.len; | ||
| 190 | attr->val_ptr = cur_attr.val_ptr; | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | } while (iter); | ||
| 194 | |||
| 195 | return -EIO; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out) | ||
| 199 | { | ||
| 200 | struct osd_request *or; | ||
| 201 | struct osd_attr attr; | ||
| 202 | int ret; | ||
| 203 | |||
| 204 | /* start request */ | ||
| 205 | or = osd_start_request(osdev->osd, GFP_KERNEL); | ||
| 206 | if (!or) | ||
| 207 | return -ENOMEM; | ||
| 208 | |||
| 209 | /* create a get-attributes(length) request */ | ||
| 210 | osd_req_get_attributes(or, &osdev->obj); | ||
| 211 | |||
| 212 | osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); | ||
| 213 | |||
| 214 | /* execute op synchronously */ | ||
| 215 | ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred); | ||
| 216 | if (ret) | ||
| 217 | goto out; | ||
| 218 | |||
| 219 | /* extract length from returned attribute info */ | ||
| 220 | attr = g_attr_logical_length; | ||
| 221 | ret = extract_attr_from_req(or, &attr); | ||
| 222 | if (ret) | ||
| 223 | goto out; | ||
| 224 | |||
| 225 | *size_out = get_unaligned_be64(attr.val_ptr); | ||
| 226 | |||
| 227 | out: | ||
| 228 | osd_end_request(or); | ||
| 229 | return ret; | ||
| 230 | |||
| 231 | } | ||
| 232 | |||
| 233 | static void osdblk_osd_complete(struct osd_request *or, void *private) | ||
| 234 | { | ||
| 235 | struct osdblk_request *orq = private; | ||
| 236 | struct osd_sense_info osi; | ||
| 237 | int ret = osd_req_decode_sense(or, &osi); | ||
| 238 | |||
| 239 | if (ret) { | ||
| 240 | ret = -EIO; | ||
| 241 | OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret); | ||
| 242 | } | ||
| 243 | |||
| 244 | /* complete OSD request */ | ||
| 245 | osd_end_request(or); | ||
| 246 | |||
| 247 | /* complete request passed to osdblk by block layer */ | ||
| 248 | __blk_end_request_all(orq->rq, ret); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void bio_chain_put(struct bio *chain) | ||
| 252 | { | ||
| 253 | struct bio *tmp; | ||
| 254 | |||
| 255 | while (chain) { | ||
| 256 | tmp = chain; | ||
| 257 | chain = chain->bi_next; | ||
| 258 | |||
| 259 | bio_put(tmp); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask) | ||
| 264 | { | ||
| 265 | struct bio *tmp, *new_chain = NULL, *tail = NULL; | ||
| 266 | |||
| 267 | while (old_chain) { | ||
| 268 | tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); | ||
| 269 | if (!tmp) | ||
| 270 | goto err_out; | ||
| 271 | |||
| 272 | __bio_clone(tmp, old_chain); | ||
| 273 | tmp->bi_bdev = NULL; | ||
| 274 | gfpmask &= ~__GFP_WAIT; | ||
| 275 | tmp->bi_next = NULL; | ||
| 276 | |||
| 277 | if (!new_chain) | ||
| 278 | new_chain = tail = tmp; | ||
| 279 | else { | ||
| 280 | tail->bi_next = tmp; | ||
| 281 | tail = tmp; | ||
| 282 | } | ||
| 283 | |||
| 284 | old_chain = old_chain->bi_next; | ||
| 285 | } | ||
| 286 | |||
| 287 | return new_chain; | ||
| 288 | |||
| 289 | err_out: | ||
| 290 | OSDBLK_DEBUG("bio_chain_clone with err\n"); | ||
| 291 | bio_chain_put(new_chain); | ||
| 292 | return NULL; | ||
| 293 | } | ||
| 294 | |||
| 295 | static void osdblk_rq_fn(struct request_queue *q) | ||
| 296 | { | ||
| 297 | struct osdblk_device *osdev = q->queuedata; | ||
| 298 | |||
| 299 | while (1) { | ||
| 300 | struct request *rq; | ||
| 301 | struct osdblk_request *orq; | ||
| 302 | struct osd_request *or; | ||
| 303 | struct bio *bio; | ||
| 304 | bool do_write, do_flush; | ||
| 305 | |||
| 306 | /* peek at request from block layer */ | ||
| 307 | rq = blk_fetch_request(q); | ||
| 308 | if (!rq) | ||
| 309 | break; | ||
| 310 | |||
| 311 | /* filter out block requests we don't understand */ | ||
| 312 | if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { | ||
| 313 | blk_end_request_all(rq, 0); | ||
| 314 | continue; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* deduce our operation (read, write, flush) */ | ||
| 318 | /* I wish the block layer simplified cmd_type/cmd_flags/cmd[] | ||
| 319 | * into a clearly defined set of RPC commands: | ||
| 320 | * read, write, flush, scsi command, power mgmt req, | ||
| 321 | * driver-specific, etc. | ||
| 322 | */ | ||
| 323 | |||
| 324 | do_flush = (rq->special == (void *) 0xdeadbeefUL); | ||
| 325 | do_write = (rq_data_dir(rq) == WRITE); | ||
| 326 | |||
| 327 | if (!do_flush) { /* osd_flush does not use a bio */ | ||
| 328 | /* a bio clone to be passed down to OSD request */ | ||
| 329 | bio = bio_chain_clone(rq->bio, GFP_ATOMIC); | ||
| 330 | if (!bio) | ||
| 331 | break; | ||
| 332 | } else | ||
| 333 | bio = NULL; | ||
| 334 | |||
| 335 | /* alloc internal OSD request, for OSD command execution */ | ||
| 336 | or = osd_start_request(osdev->osd, GFP_ATOMIC); | ||
| 337 | if (!or) { | ||
| 338 | bio_chain_put(bio); | ||
| 339 | OSDBLK_DEBUG("osd_start_request with err\n"); | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | |||
| 343 | orq = &osdev->req[rq->tag]; | ||
| 344 | orq->rq = rq; | ||
| 345 | orq->bio = bio; | ||
| 346 | orq->osdev = osdev; | ||
| 347 | |||
| 348 | /* init OSD command: flush, write or read */ | ||
| 349 | if (do_flush) | ||
| 350 | osd_req_flush_object(or, &osdev->obj, | ||
| 351 | OSD_CDB_FLUSH_ALL, 0, 0); | ||
| 352 | else if (do_write) | ||
| 353 | osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||
| 354 | bio, blk_rq_bytes(rq)); | ||
| 355 | else | ||
| 356 | osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||
| 357 | bio, blk_rq_bytes(rq)); | ||
| 358 | |||
| 359 | OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n", | ||
| 360 | do_flush ? "flush" : do_write ? | ||
| 361 | "write" : "read", blk_rq_bytes(rq), | ||
| 362 | blk_rq_pos(rq) * 512ULL); | ||
| 363 | |||
| 364 | /* begin OSD command execution */ | ||
| 365 | if (osd_async_op(or, osdblk_osd_complete, orq, | ||
| 366 | osdev->obj_cred)) { | ||
| 367 | osd_end_request(or); | ||
| 368 | blk_requeue_request(q, rq); | ||
| 369 | bio_chain_put(bio); | ||
| 370 | OSDBLK_DEBUG("osd_execute_request_async with err\n"); | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* remove the special 'flush' marker, now that the command | ||
| 375 | * is executing | ||
| 376 | */ | ||
| 377 | rq->special = NULL; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | static void osdblk_prepare_flush(struct request_queue *q, struct request *rq) | ||
| 382 | { | ||
| 383 | /* add driver-specific marker, to indicate that this request | ||
| 384 | * is a flush command | ||
| 385 | */ | ||
| 386 | rq->special = (void *) 0xdeadbeefUL; | ||
| 387 | } | ||
| 388 | |||
| 389 | static void osdblk_free_disk(struct osdblk_device *osdev) | ||
| 390 | { | ||
| 391 | struct gendisk *disk = osdev->disk; | ||
| 392 | |||
| 393 | if (!disk) | ||
| 394 | return; | ||
| 395 | |||
| 396 | if (disk->flags & GENHD_FL_UP) | ||
| 397 | del_gendisk(disk); | ||
| 398 | if (disk->queue) | ||
| 399 | blk_cleanup_queue(disk->queue); | ||
| 400 | put_disk(disk); | ||
| 401 | } | ||
| 402 | |||
| 403 | static int osdblk_init_disk(struct osdblk_device *osdev) | ||
| 404 | { | ||
| 405 | struct gendisk *disk; | ||
| 406 | struct request_queue *q; | ||
| 407 | int rc; | ||
| 408 | u64 obj_size = 0; | ||
| 409 | |||
| 410 | /* contact OSD, request size info about the object being mapped */ | ||
| 411 | rc = osdblk_get_obj_size(osdev, &obj_size); | ||
| 412 | if (rc) | ||
| 413 | return rc; | ||
| 414 | |||
| 415 | /* create gendisk info */ | ||
| 416 | disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR); | ||
| 417 | if (!disk) | ||
| 418 | return -ENOMEM; | ||
| 419 | |||
| 420 | sprintf(disk->disk_name, DRV_NAME "%d", osdev->id); | ||
| 421 | disk->major = osdev->major; | ||
| 422 | disk->first_minor = 0; | ||
| 423 | disk->fops = &osdblk_bd_ops; | ||
| 424 | disk->private_data = osdev; | ||
| 425 | |||
| 426 | /* init rq */ | ||
| 427 | q = blk_init_queue(osdblk_rq_fn, &osdev->lock); | ||
| 428 | if (!q) { | ||
| 429 | put_disk(disk); | ||
| 430 | return -ENOMEM; | ||
| 431 | } | ||
| 432 | |||
| 433 | /* switch queue to TCQ mode; allocate tag map */ | ||
| 434 | rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL); | ||
| 435 | if (rc) { | ||
| 436 | blk_cleanup_queue(q); | ||
| 437 | put_disk(disk); | ||
| 438 | return rc; | ||
| 439 | } | ||
| 440 | |||
| 441 | /* Set our limits to the lower device limits, because osdblk cannot | ||
| 442 | * sleep when allocating a lower-request and therefore cannot be | ||
| 443 | * bouncing. | ||
| 444 | */ | ||
| 445 | blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); | ||
| 446 | |||
| 447 | blk_queue_prep_rq(q, blk_queue_start_tag); | ||
| 448 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); | ||
| 449 | |||
| 450 | disk->queue = q; | ||
| 451 | |||
| 452 | q->queuedata = osdev; | ||
| 453 | |||
| 454 | osdev->disk = disk; | ||
| 455 | osdev->q = q; | ||
| 456 | |||
| 457 | /* finally, announce the disk to the world */ | ||
| 458 | set_capacity(disk, obj_size / 512ULL); | ||
| 459 | add_disk(disk); | ||
| 460 | |||
| 461 | printk(KERN_INFO "%s: Added of size 0x%llx\n", | ||
| 462 | disk->disk_name, (unsigned long long)obj_size); | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | /******************************************************************** | ||
| 468 | * /sys/class/osdblk/ | ||
| 469 | * add map OSD object to blkdev | ||
| 470 | * remove unmap OSD object | ||
| 471 | * list show mappings | ||
| 472 | *******************************************************************/ | ||
| 473 | |||
| 474 | static void class_osdblk_release(struct class *cls) | ||
| 475 | { | ||
| 476 | kfree(cls); | ||
| 477 | } | ||
| 478 | |||
| 479 | static ssize_t class_osdblk_list(struct class *c, char *data) | ||
| 480 | { | ||
| 481 | int n = 0; | ||
| 482 | struct list_head *tmp; | ||
| 483 | |||
| 484 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
| 485 | |||
| 486 | list_for_each(tmp, &osdblkdev_list) { | ||
| 487 | struct osdblk_device *osdev; | ||
| 488 | |||
| 489 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
| 490 | |||
| 491 | n += sprintf(data+n, "%d %d %llu %llu %s\n", | ||
| 492 | osdev->id, | ||
| 493 | osdev->major, | ||
| 494 | osdev->obj.partition, | ||
| 495 | osdev->obj.id, | ||
| 496 | osdev->osd_path); | ||
| 497 | } | ||
| 498 | |||
| 499 | mutex_unlock(&ctl_mutex); | ||
| 500 | return n; | ||
| 501 | } | ||
| 502 | |||
| 503 | static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) | ||
| 504 | { | ||
| 505 | struct osdblk_device *osdev; | ||
| 506 | ssize_t rc; | ||
| 507 | int irc, new_id = 0; | ||
| 508 | struct list_head *tmp; | ||
| 509 | |||
| 510 | if (!try_module_get(THIS_MODULE)) | ||
| 511 | return -ENODEV; | ||
| 512 | |||
| 513 | /* new osdblk_device object */ | ||
| 514 | osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL); | ||
| 515 | if (!osdev) { | ||
| 516 | rc = -ENOMEM; | ||
| 517 | goto err_out_mod; | ||
| 518 | } | ||
| 519 | |||
| 520 | /* static osdblk_device initialization */ | ||
| 521 | spin_lock_init(&osdev->lock); | ||
| 522 | INIT_LIST_HEAD(&osdev->node); | ||
| 523 | |||
| 524 | /* generate unique id: find highest unique id, add one */ | ||
| 525 | |||
| 526 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
| 527 | |||
| 528 | list_for_each(tmp, &osdblkdev_list) { | ||
| 529 | struct osdblk_device *osdev; | ||
| 530 | |||
| 531 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
| 532 | if (osdev->id > new_id) | ||
| 533 | new_id = osdev->id + 1; | ||
| 534 | } | ||
| 535 | |||
| 536 | osdev->id = new_id; | ||
| 537 | |||
| 538 | /* add to global list */ | ||
| 539 | list_add_tail(&osdev->node, &osdblkdev_list); | ||
| 540 | |||
| 541 | mutex_unlock(&ctl_mutex); | ||
| 542 | |||
| 543 | /* parse add command */ | ||
| 544 | if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id, | ||
| 545 | osdev->osd_path) != 3) { | ||
| 546 | rc = -EINVAL; | ||
| 547 | goto err_out_slot; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* initialize rest of new object */ | ||
| 551 | sprintf(osdev->name, DRV_NAME "%d", osdev->id); | ||
| 552 | |||
| 553 | /* contact requested OSD */ | ||
| 554 | osdev->osd = osduld_path_lookup(osdev->osd_path); | ||
| 555 | if (IS_ERR(osdev->osd)) { | ||
| 556 | rc = PTR_ERR(osdev->osd); | ||
| 557 | goto err_out_slot; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* build OSD credential */ | ||
| 561 | osdblk_make_credential(osdev->obj_cred, &osdev->obj); | ||
| 562 | |||
| 563 | /* register our block device */ | ||
| 564 | irc = register_blkdev(0, osdev->name); | ||
| 565 | if (irc < 0) { | ||
| 566 | rc = irc; | ||
| 567 | goto err_out_osd; | ||
| 568 | } | ||
| 569 | |||
| 570 | osdev->major = irc; | ||
| 571 | |||
| 572 | /* set up and announce blkdev mapping */ | ||
| 573 | rc = osdblk_init_disk(osdev); | ||
| 574 | if (rc) | ||
| 575 | goto err_out_blkdev; | ||
| 576 | |||
| 577 | return count; | ||
| 578 | |||
| 579 | err_out_blkdev: | ||
| 580 | unregister_blkdev(osdev->major, osdev->name); | ||
| 581 | err_out_osd: | ||
| 582 | osduld_put_device(osdev->osd); | ||
| 583 | err_out_slot: | ||
| 584 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
| 585 | list_del_init(&osdev->node); | ||
| 586 | mutex_unlock(&ctl_mutex); | ||
| 587 | |||
| 588 | kfree(osdev); | ||
| 589 | err_out_mod: | ||
| 590 | OSDBLK_DEBUG("Error adding device %s\n", buf); | ||
| 591 | module_put(THIS_MODULE); | ||
| 592 | return rc; | ||
| 593 | } | ||
| 594 | |||
| 595 | static ssize_t class_osdblk_remove(struct class *c, const char *buf, | ||
| 596 | size_t count) | ||
| 597 | { | ||
| 598 | struct osdblk_device *osdev = NULL; | ||
| 599 | int target_id, rc; | ||
| 600 | unsigned long ul; | ||
| 601 | struct list_head *tmp; | ||
| 602 | |||
| 603 | rc = strict_strtoul(buf, 10, &ul); | ||
| 604 | if (rc) | ||
| 605 | return rc; | ||
| 606 | |||
| 607 | /* convert to int; abort if we lost anything in the conversion */ | ||
| 608 | target_id = (int) ul; | ||
| 609 | if (target_id != ul) | ||
| 610 | return -EINVAL; | ||
| 611 | |||
| 612 | /* remove object from list immediately */ | ||
| 613 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
| 614 | |||
| 615 | list_for_each(tmp, &osdblkdev_list) { | ||
| 616 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
| 617 | if (osdev->id == target_id) { | ||
| 618 | list_del_init(&osdev->node); | ||
| 619 | break; | ||
| 620 | } | ||
| 621 | osdev = NULL; | ||
| 622 | } | ||
| 623 | |||
| 624 | mutex_unlock(&ctl_mutex); | ||
| 625 | |||
| 626 | if (!osdev) | ||
| 627 | return -ENOENT; | ||
| 628 | |||
| 629 | /* clean up and free blkdev and associated OSD connection */ | ||
| 630 | osdblk_free_disk(osdev); | ||
| 631 | unregister_blkdev(osdev->major, osdev->name); | ||
| 632 | osduld_put_device(osdev->osd); | ||
| 633 | kfree(osdev); | ||
| 634 | |||
| 635 | /* release module ref */ | ||
| 636 | module_put(THIS_MODULE); | ||
| 637 | |||
| 638 | return count; | ||
| 639 | } | ||
| 640 | |||
| 641 | static struct class_attribute class_osdblk_attrs[] = { | ||
| 642 | __ATTR(add, 0200, NULL, class_osdblk_add), | ||
| 643 | __ATTR(remove, 0200, NULL, class_osdblk_remove), | ||
| 644 | __ATTR(list, 0444, class_osdblk_list, NULL), | ||
| 645 | __ATTR_NULL | ||
| 646 | }; | ||
| 647 | |||
| 648 | static int osdblk_sysfs_init(void) | ||
| 649 | { | ||
| 650 | int ret = 0; | ||
| 651 | |||
| 652 | /* | ||
| 653 | * create control files in sysfs | ||
| 654 | * /sys/class/osdblk/... | ||
| 655 | */ | ||
| 656 | class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL); | ||
| 657 | if (!class_osdblk) | ||
| 658 | return -ENOMEM; | ||
| 659 | |||
| 660 | class_osdblk->name = DRV_NAME; | ||
| 661 | class_osdblk->owner = THIS_MODULE; | ||
| 662 | class_osdblk->class_release = class_osdblk_release; | ||
| 663 | class_osdblk->class_attrs = class_osdblk_attrs; | ||
| 664 | |||
| 665 | ret = class_register(class_osdblk); | ||
| 666 | if (ret) { | ||
| 667 | kfree(class_osdblk); | ||
| 668 | class_osdblk = NULL; | ||
| 669 | printk(PFX "failed to create class osdblk\n"); | ||
| 670 | return ret; | ||
| 671 | } | ||
| 672 | |||
| 673 | return 0; | ||
| 674 | } | ||
| 675 | |||
| 676 | static void osdblk_sysfs_cleanup(void) | ||
| 677 | { | ||
| 678 | if (class_osdblk) | ||
| 679 | class_destroy(class_osdblk); | ||
| 680 | class_osdblk = NULL; | ||
| 681 | } | ||
| 682 | |||
| 683 | static int __init osdblk_init(void) | ||
| 684 | { | ||
| 685 | int rc; | ||
| 686 | |||
| 687 | rc = osdblk_sysfs_init(); | ||
| 688 | if (rc) | ||
| 689 | return rc; | ||
| 690 | |||
| 691 | return 0; | ||
| 692 | } | ||
| 693 | |||
| 694 | static void __exit osdblk_exit(void) | ||
| 695 | { | ||
| 696 | osdblk_sysfs_cleanup(); | ||
| 697 | } | ||
| 698 | |||
| 699 | module_init(osdblk_init); | ||
| 700 | module_exit(osdblk_exit); | ||
| 701 | |||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 83650e00632d..99a506f619b7 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -1372,8 +1372,10 @@ try_next_bio: | |||
| 1372 | wakeup = (pd->write_congestion_on > 0 | 1372 | wakeup = (pd->write_congestion_on > 0 |
| 1373 | && pd->bio_queue_size <= pd->write_congestion_off); | 1373 | && pd->bio_queue_size <= pd->write_congestion_off); |
| 1374 | spin_unlock(&pd->lock); | 1374 | spin_unlock(&pd->lock); |
| 1375 | if (wakeup) | 1375 | if (wakeup) { |
| 1376 | clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE); | 1376 | clear_bdi_congested(&pd->disk->queue->backing_dev_info, |
| 1377 | BLK_RW_ASYNC); | ||
| 1378 | } | ||
| 1377 | 1379 | ||
| 1378 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); | 1380 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); |
| 1379 | pkt_set_state(pkt, PACKET_WAITING_STATE); | 1381 | pkt_set_state(pkt, PACKET_WAITING_STATE); |
| @@ -2592,10 +2594,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) | |||
| 2592 | spin_lock(&pd->lock); | 2594 | spin_lock(&pd->lock); |
| 2593 | if (pd->write_congestion_on > 0 | 2595 | if (pd->write_congestion_on > 0 |
| 2594 | && pd->bio_queue_size >= pd->write_congestion_on) { | 2596 | && pd->bio_queue_size >= pd->write_congestion_on) { |
| 2595 | set_bdi_congested(&q->backing_dev_info, WRITE); | 2597 | set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC); |
| 2596 | do { | 2598 | do { |
| 2597 | spin_unlock(&pd->lock); | 2599 | spin_unlock(&pd->lock); |
| 2598 | congestion_wait(WRITE, HZ); | 2600 | congestion_wait(BLK_RW_ASYNC, HZ); |
| 2599 | spin_lock(&pd->lock); | 2601 | spin_lock(&pd->lock); |
| 2600 | } while(pd->bio_queue_size > pd->write_congestion_off); | 2602 | } while(pd->bio_queue_size > pd->write_congestion_off); |
| 2601 | } | 2603 | } |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 43db3ea15b54..fbeefb68a31f 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -213,7 +213,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
| 213 | * Only allow the generic SCSI ioctls if the host can support it. | 213 | * Only allow the generic SCSI ioctls if the host can support it. |
| 214 | */ | 214 | */ |
| 215 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) | 215 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) |
| 216 | return -ENOIOCTLCMD; | 216 | return -ENOTTY; |
| 217 | 217 | ||
| 218 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); | 218 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); |
| 219 | } | 219 | } |
| @@ -360,6 +360,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 360 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | 360 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); |
| 361 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | 361 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); |
| 362 | 362 | ||
| 363 | /* No need to bounce any requests */ | ||
| 364 | blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY); | ||
| 365 | |||
| 363 | /* No real sector limit. */ | 366 | /* No real sector limit. */ |
| 364 | blk_queue_max_sectors(vblk->disk->queue, -1U); | 367 | blk_queue_max_sectors(vblk->disk->queue, -1U); |
| 365 | 368 | ||
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index f08491a3a813..b20abe102a2b 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
| @@ -390,9 +390,10 @@ static inline void ace_dump_mem(void *base, int len) | |||
| 390 | 390 | ||
| 391 | static void ace_dump_regs(struct ace_device *ace) | 391 | static void ace_dump_regs(struct ace_device *ace) |
| 392 | { | 392 | { |
| 393 | dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" | 393 | dev_info(ace->dev, |
| 394 | KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n" | 394 | " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" |
| 395 | KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", | 395 | " status:%.8x mpu_lba:%.8x busmode:%4x\n" |
| 396 | " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", | ||
| 396 | ace_in32(ace, ACE_CTRL), | 397 | ace_in32(ace, ACE_CTRL), |
| 397 | ace_in(ace, ACE_SECCNTCMD), | 398 | ace_in(ace, ACE_SECCNTCMD), |
| 398 | ace_in(ace, ACE_VERSION), | 399 | ace_in(ace, ACE_VERSION), |
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 1df9dda2e377..d5cde6d86f89 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/smp_lock.h> | ||
| 32 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 33 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
| 34 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0bd01f49cfd8..6a06913b01d3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -1029,10 +1029,6 @@ config CS5535_GPIO | |||
| 1029 | 1029 | ||
| 1030 | If compiled as a module, it will be called cs5535_gpio. | 1030 | If compiled as a module, it will be called cs5535_gpio. |
| 1031 | 1031 | ||
| 1032 | config GPIO_VR41XX | ||
| 1033 | tristate "NEC VR4100 series General-purpose I/O Unit support" | ||
| 1034 | depends on CPU_VR41XX | ||
| 1035 | |||
| 1036 | config RAW_DRIVER | 1032 | config RAW_DRIVER |
| 1037 | tristate "RAW driver (/dev/raw/rawN)" | 1033 | tristate "RAW driver (/dev/raw/rawN)" |
| 1038 | depends on BLOCK | 1034 | depends on BLOCK |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 189efcff08ce..66f779ad4f4c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o | |||
| 95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o | 95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o |
| 96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o | 96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o |
| 97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | 97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o |
| 98 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
| 99 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o | 98 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
| 100 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 99 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
| 101 | 100 | ||
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 72429b6b2fa8..6c32fbf07164 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
| @@ -81,6 +81,7 @@ static char *serial_version = "4.30"; | |||
| 81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
| 82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
| 83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
| 84 | #include <linux/smp_lock.h> | ||
| 84 | #include <linux/init.h> | 85 | #include <linux/init.h> |
| 85 | #include <linux/bitops.h> | 86 | #include <linux/bitops.h> |
| 86 | 87 | ||
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 140ea10ecb88..c02db01f736e 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/cdev.h> | 27 | #include <linux/cdev.h> |
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
| 30 | #include <asm/pgtable.h> | ||
| 30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
| 31 | 32 | ||
| 32 | /* | 33 | /* |
| @@ -75,12 +76,13 @@ static struct class *bsr_class; | |||
| 75 | static int bsr_major; | 76 | static int bsr_major; |
| 76 | 77 | ||
| 77 | enum { | 78 | enum { |
| 78 | BSR_8 = 0, | 79 | BSR_8 = 0, |
| 79 | BSR_16 = 1, | 80 | BSR_16 = 1, |
| 80 | BSR_64 = 2, | 81 | BSR_64 = 2, |
| 81 | BSR_128 = 3, | 82 | BSR_128 = 3, |
| 82 | BSR_UNKNOWN = 4, | 83 | BSR_4096 = 4, |
| 83 | BSR_MAX = 5, | 84 | BSR_UNKNOWN = 5, |
| 85 | BSR_MAX = 6, | ||
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 86 | static unsigned bsr_types[BSR_MAX]; | 88 | static unsigned bsr_types[BSR_MAX]; |
| @@ -117,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 117 | { | 119 | { |
| 118 | unsigned long size = vma->vm_end - vma->vm_start; | 120 | unsigned long size = vma->vm_end - vma->vm_start; |
| 119 | struct bsr_dev *dev = filp->private_data; | 121 | struct bsr_dev *dev = filp->private_data; |
| 122 | int ret; | ||
| 120 | 123 | ||
| 121 | if (size > dev->bsr_len || (size & (PAGE_SIZE-1))) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | vma->vm_flags |= (VM_IO | VM_DONTEXPAND); | ||
| 125 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 124 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 126 | 125 | ||
| 127 | if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT, | 126 | /* check for the case of a small BSR device and map one 4k page for it*/ |
| 128 | size, vma->vm_page_prot)) | 127 | if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE) |
| 128 | ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12, | ||
| 129 | vma->vm_page_prot); | ||
| 130 | else if (size <= dev->bsr_len) | ||
| 131 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
| 132 | dev->bsr_addr >> PAGE_SHIFT, | ||
| 133 | size, vma->vm_page_prot); | ||
| 134 | else | ||
| 135 | return -EINVAL; | ||
| 136 | |||
| 137 | if (ret) | ||
| 129 | return -EAGAIN; | 138 | return -EAGAIN; |
| 130 | 139 | ||
| 131 | return 0; | 140 | return 0; |
| @@ -205,6 +214,11 @@ static int bsr_add_node(struct device_node *bn) | |||
| 205 | cur->bsr_stride = bsr_stride[i]; | 214 | cur->bsr_stride = bsr_stride[i]; |
| 206 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); | 215 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
| 207 | 216 | ||
| 217 | /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */ | ||
| 218 | /* we can only map 4k of it, so only advertise the 4k in sysfs */ | ||
| 219 | if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE) | ||
| 220 | cur->bsr_len = 4096; | ||
| 221 | |||
| 208 | switch(cur->bsr_bytes) { | 222 | switch(cur->bsr_bytes) { |
| 209 | case 8: | 223 | case 8: |
| 210 | cur->bsr_type = BSR_8; | 224 | cur->bsr_type = BSR_8; |
| @@ -218,9 +232,11 @@ static int bsr_add_node(struct device_node *bn) | |||
| 218 | case 128: | 232 | case 128: |
| 219 | cur->bsr_type = BSR_128; | 233 | cur->bsr_type = BSR_128; |
| 220 | break; | 234 | break; |
| 235 | case 4096: | ||
| 236 | cur->bsr_type = BSR_4096; | ||
| 237 | break; | ||
| 221 | default: | 238 | default: |
| 222 | cur->bsr_type = BSR_UNKNOWN; | 239 | cur->bsr_type = BSR_UNKNOWN; |
| 223 | printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes); | ||
| 224 | } | 240 | } |
| 225 | 241 | ||
| 226 | cur->bsr_num = bsr_types[cur->bsr_type]; | 242 | cur->bsr_num = bsr_types[cur->bsr_type]; |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index f3366d3f06cf..2dafc2da0648 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
| @@ -633,6 +633,7 @@ | |||
| 633 | #include <linux/tty.h> | 633 | #include <linux/tty.h> |
| 634 | #include <linux/tty_flip.h> | 634 | #include <linux/tty_flip.h> |
| 635 | #include <linux/serial.h> | 635 | #include <linux/serial.h> |
| 636 | #include <linux/smp_lock.h> | ||
| 636 | #include <linux/major.h> | 637 | #include <linux/major.h> |
| 637 | #include <linux/string.h> | 638 | #include <linux/string.h> |
| 638 | #include <linux/fcntl.h> | 639 | #include <linux/fcntl.h> |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index abef1f7d84fe..ff647ca1c489 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/tty.h> | 36 | #include <linux/tty.h> |
| 37 | #include <linux/tty_flip.h> | 37 | #include <linux/tty_flip.h> |
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/smp_lock.h> | ||
| 39 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
| 40 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
| 41 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5dcbe603eca2..91b53eb1c053 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
| @@ -305,10 +305,11 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, | |||
| 305 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) | 305 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) |
| 306 | == BIOS_CNTL_LOCK_ENABLE_MASK) { | 306 | == BIOS_CNTL_LOCK_ENABLE_MASK) { |
| 307 | static __initdata /*const*/ char warning[] = | 307 | static __initdata /*const*/ char warning[] = |
| 308 | KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" | 308 | KERN_WARNING |
| 309 | KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" | 309 | PFX "Firmware space is locked read-only. If you can't or\n" |
| 310 | KERN_WARNING PFX "you are certain that your system has a functional\n" | 310 | PFX "don't want to disable this in firmware setup, and if\n" |
| 311 | KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; | 311 | PFX "you are certain that your system has a functional\n" |
| 312 | PFX "RNG, try using the 'no_fwh_detect' option.\n"; | ||
| 312 | 313 | ||
| 313 | if (no_fwh_detect) | 314 | if (no_fwh_detect) |
| 314 | return -ENODEV; | 315 | return -ENODEV; |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 4159292e35cf..4f1f4cd670da 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
| @@ -122,6 +122,7 @@ | |||
| 122 | #include <linux/fs.h> | 122 | #include <linux/fs.h> |
| 123 | #include <linux/sched.h> | 123 | #include <linux/sched.h> |
| 124 | #include <linux/serial.h> | 124 | #include <linux/serial.h> |
| 125 | #include <linux/smp_lock.h> | ||
| 125 | #include <linux/mm.h> | 126 | #include <linux/mm.h> |
| 126 | #include <linux/interrupt.h> | 127 | #include <linux/interrupt.h> |
| 127 | #include <linux/timer.h> | 128 | #include <linux/timer.h> |
| @@ -1478,10 +1479,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
| 1478 | status = inw(base + 0x4); | 1479 | status = inw(base + 0x4); |
| 1479 | if (status != 0) { | 1480 | if (status != 0) { |
| 1480 | dev_warn(&pdev->dev, "Card%d rejected load header:\n" | 1481 | dev_warn(&pdev->dev, "Card%d rejected load header:\n" |
| 1481 | KERN_WARNING "Address:0x%x\n" | 1482 | "Address:0x%x\n" |
| 1482 | KERN_WARNING "Count:0x%x\n" | 1483 | "Count:0x%x\n" |
| 1483 | KERN_WARNING "Status:0x%x\n", | 1484 | "Status:0x%x\n", |
| 1484 | index + 1, frame->addr, frame->count, status); | 1485 | index + 1, frame->addr, frame->count, status); |
| 1485 | goto errrelfw; | 1486 | goto errrelfw; |
| 1486 | } | 1487 | } |
| 1487 | outsw(base, frame->data, word_count); | 1488 | outsw(base, frame->data, word_count); |
| @@ -1526,10 +1527,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
| 1526 | status = inw(base + 0x4); | 1527 | status = inw(base + 0x4); |
| 1527 | if (status != 0) { | 1528 | if (status != 0) { |
| 1528 | dev_warn(&pdev->dev, "Card%d rejected verify header:\n" | 1529 | dev_warn(&pdev->dev, "Card%d rejected verify header:\n" |
| 1529 | KERN_WARNING "Address:0x%x\n" | 1530 | "Address:0x%x\n" |
| 1530 | KERN_WARNING "Count:0x%x\n" | 1531 | "Count:0x%x\n" |
| 1531 | KERN_WARNING "Status: 0x%x\n", | 1532 | "Status: 0x%x\n", |
| 1532 | index + 1, frame->addr, frame->count, status); | 1533 | index + 1, frame->addr, frame->count, status); |
| 1533 | goto errrelfw; | 1534 | goto errrelfw; |
| 1534 | } | 1535 | } |
| 1535 | 1536 | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 0c999f5bb3db..ab2f3349c5c4 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/smp_lock.h> | ||
| 23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 24 | #include <linux/tty.h> | 25 | #include <linux/tty.h> |
| 25 | #include <linux/tty_flip.h> | 26 | #include <linux/tty_flip.h> |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 65b6ff2442c6..dd0083bbb64a 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/tty.h> | 34 | #include <linux/tty.h> |
| 35 | #include <linux/tty_flip.h> | 35 | #include <linux/tty_flip.h> |
| 36 | #include <linux/major.h> | 36 | #include <linux/major.h> |
| 37 | #include <linux/smp_lock.h> | ||
| 37 | #include <linux/string.h> | 38 | #include <linux/string.h> |
| 38 | #include <linux/fcntl.h> | 39 | #include <linux/fcntl.h> |
| 39 | #include <linux/ptrace.h> | 40 | #include <linux/ptrace.h> |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 9533f43a30bb..dbf8d52f31d0 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
| 24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
| 25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
| 26 | #include <linux/smp_lock.h> | ||
| 26 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
| 27 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
| 28 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
| @@ -1048,8 +1049,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
| 1048 | if (retval) | 1049 | if (retval) |
| 1049 | return retval; | 1050 | return retval; |
| 1050 | 1051 | ||
| 1051 | /* unmark here for very high baud rate (ex. 921600 bps) used */ | ||
| 1052 | tty->low_latency = 1; | ||
| 1053 | return 0; | 1052 | return 0; |
| 1054 | } | 1053 | } |
| 1055 | 1054 | ||
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 1c43c8cdee25..c68118efad84 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
| @@ -97,6 +97,7 @@ | |||
| 97 | #include <linux/slab.h> | 97 | #include <linux/slab.h> |
| 98 | #include <linux/tty.h> | 98 | #include <linux/tty.h> |
| 99 | #include <linux/errno.h> | 99 | #include <linux/errno.h> |
| 100 | #include <linux/smp_lock.h> | ||
| 100 | #include <linux/string.h> /* used in new tty drivers */ | 101 | #include <linux/string.h> /* used in new tty drivers */ |
| 101 | #include <linux/signal.h> /* used in new tty drivers */ | 102 | #include <linux/signal.h> /* used in new tty drivers */ |
| 102 | #include <linux/if.h> | 103 | #include <linux/if.h> |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 2e99158ebb8a..6934025a1ac1 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/ioport.h> | 58 | #include <linux/ioport.h> |
| 59 | #include <linux/in.h> | 59 | #include <linux/in.h> |
| 60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
| 61 | #include <linux/smp_lock.h> | ||
| 61 | #include <linux/tty.h> | 62 | #include <linux/tty.h> |
| 62 | #include <linux/errno.h> | 63 | #include <linux/errno.h> |
| 63 | #include <linux/string.h> /* used in new tty drivers */ | 64 | #include <linux/string.h> /* used in new tty drivers */ |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 94a5d5020abc..ff47907ff1bf 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
| @@ -1331,9 +1331,6 @@ handle_newline: | |||
| 1331 | 1331 | ||
| 1332 | static void n_tty_write_wakeup(struct tty_struct *tty) | 1332 | static void n_tty_write_wakeup(struct tty_struct *tty) |
| 1333 | { | 1333 | { |
| 1334 | /* Write out any echoed characters that are still pending */ | ||
| 1335 | process_echoes(tty); | ||
| 1336 | |||
| 1337 | if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) | 1334 | if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) |
| 1338 | kill_fasync(&tty->fasync, SIGIO, POLL_OUT); | 1335 | kill_fasync(&tty->fasync, SIGIO, POLL_OUT); |
| 1339 | } | 1336 | } |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index d6102b644b55..280b41c507a7 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
| @@ -828,7 +828,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 828 | struct port *port = &dc->port[index]; | 828 | struct port *port = &dc->port[index]; |
| 829 | void __iomem *addr = port->dl_addr[port->toggle_dl]; | 829 | void __iomem *addr = port->dl_addr[port->toggle_dl]; |
| 830 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 830 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
| 831 | int i; | 831 | int i, ret; |
| 832 | 832 | ||
| 833 | if (unlikely(!tty)) { | 833 | if (unlikely(!tty)) { |
| 834 | DBG1("tty not open for port: %d?", index); | 834 | DBG1("tty not open for port: %d?", index); |
| @@ -844,12 +844,14 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 844 | 844 | ||
| 845 | /* disable interrupt in downlink... */ | 845 | /* disable interrupt in downlink... */ |
| 846 | disable_transmit_dl(index, dc); | 846 | disable_transmit_dl(index, dc); |
| 847 | return 0; | 847 | ret = 0; |
| 848 | goto put; | ||
| 848 | } | 849 | } |
| 849 | 850 | ||
| 850 | if (unlikely(size == 0)) { | 851 | if (unlikely(size == 0)) { |
| 851 | dev_err(&dc->pdev->dev, "size == 0?\n"); | 852 | dev_err(&dc->pdev->dev, "size == 0?\n"); |
| 852 | return 1; | 853 | ret = 1; |
| 854 | goto put; | ||
| 853 | } | 855 | } |
| 854 | 856 | ||
| 855 | tty_buffer_request_room(tty, size); | 857 | tty_buffer_request_room(tty, size); |
| @@ -871,8 +873,10 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
| 871 | } | 873 | } |
| 872 | 874 | ||
| 873 | set_bit(index, &dc->flip); | 875 | set_bit(index, &dc->flip); |
| 876 | ret = 1; | ||
| 877 | put: | ||
| 874 | tty_kref_put(tty); | 878 | tty_kref_put(tty); |
| 875 | return 1; | 879 | return ret; |
| 876 | } | 880 | } |
| 877 | 881 | ||
| 878 | /* Debug for interrupts */ | 882 | /* Debug for interrupts */ |
| @@ -1591,8 +1595,6 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
| 1591 | 1595 | ||
| 1592 | /* Enable interrupt downlink for channel */ | 1596 | /* Enable interrupt downlink for channel */ |
| 1593 | if (port->port.count == 1) { | 1597 | if (port->port.count == 1) { |
| 1594 | /* FIXME: is this needed now ? */ | ||
| 1595 | tty->low_latency = 1; | ||
| 1596 | tty->driver_data = port; | 1598 | tty->driver_data = port; |
| 1597 | tty_port_tty_set(&port->port, tty); | 1599 | tty_port_tty_set(&port->port, tty); |
| 1598 | DBG1("open: %d", port->token_dl); | 1600 | DBG1("open: %d", port->token_dl); |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index daebe1ba43d4..6e6942c45f5b 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/major.h> | 22 | #include <linux/major.h> |
| 23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
| 24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
| 25 | #include <linux/smp_lock.h> | ||
| 25 | #include <linux/sysctl.h> | 26 | #include <linux/sysctl.h> |
| 26 | #include <linux/device.h> | 27 | #include <linux/device.h> |
| 27 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
| @@ -75,114 +76,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
| 75 | */ | 76 | */ |
| 76 | static void pty_unthrottle(struct tty_struct *tty) | 77 | static void pty_unthrottle(struct tty_struct *tty) |
| 77 | { | 78 | { |
| 78 | struct tty_struct *o_tty = tty->link; | 79 | tty_wakeup(tty->link); |
| 79 | |||
| 80 | if (!o_tty) | ||
| 81 | return; | ||
| 82 | |||
| 83 | tty_wakeup(o_tty); | ||
| 84 | set_bit(TTY_THROTTLED, &tty->flags); | 80 | set_bit(TTY_THROTTLED, &tty->flags); |
| 85 | } | 81 | } |
| 86 | 82 | ||
| 87 | /* | 83 | /** |
| 88 | * WSH 05/24/97: modified to | 84 | * pty_space - report space left for writing |
| 89 | * (1) use space in tty->flip instead of a shared temp buffer | 85 | * @to: tty we are writing into |
| 90 | * The flip buffers aren't being used for a pty, so there's lots | ||
| 91 | * of space available. The buffer is protected by a per-pty | ||
| 92 | * semaphore that should almost never come under contention. | ||
| 93 | * (2) avoid redundant copying for cases where count >> receive_room | ||
| 94 | * N.B. Calls from user space may now return an error code instead of | ||
| 95 | * a count. | ||
| 96 | * | 86 | * |
| 97 | * FIXME: Our pty_write method is called with our ldisc lock held but | 87 | * The tty buffers allow 64K but we sneak a peak and clip at 8K this |
| 98 | * not our partners. We can't just wait on the other one blindly without | 88 | * allows a lot of overspill room for echo and other fun messes to |
| 99 | * risking deadlocks. At some point when everything has settled down we need | 89 | * be handled properly |
| 100 | * to look into making pty_write at least able to sleep over an ldisc change. | 90 | */ |
| 91 | |||
| 92 | static int pty_space(struct tty_struct *to) | ||
| 93 | { | ||
| 94 | int n = 8192 - to->buf.memory_used; | ||
| 95 | if (n < 0) | ||
| 96 | return 0; | ||
| 97 | return n; | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * pty_write - write to a pty | ||
| 102 | * @tty: the tty we write from | ||
| 103 | * @buf: kernel buffer of data | ||
| 104 | * @count: bytes to write | ||
| 101 | * | 105 | * |
| 102 | * The return on no ldisc is a bit counter intuitive but the logic works | 106 | * Our "hardware" write method. Data is coming from the ldisc which |
| 103 | * like this. During an ldisc change the other end will flush its buffers. We | 107 | * may be in a non sleeping state. We simply throw this at the other |
| 104 | * thus return the full length which is identical to the case where we had | 108 | * end of the link as if we were an IRQ handler receiving stuff for |
| 105 | * proper locking and happened to queue the bytes just before the flush during | 109 | * the other side of the pty/tty pair. |
| 106 | * the ldisc change. | ||
| 107 | */ | 110 | */ |
| 111 | |||
| 108 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, | 112 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, |
| 109 | int count) | 113 | int count) |
| 110 | { | 114 | { |
| 111 | struct tty_struct *to = tty->link; | 115 | struct tty_struct *to = tty->link; |
| 112 | struct tty_ldisc *ld; | 116 | int c; |
| 113 | int c = count; | ||
| 114 | 117 | ||
| 115 | if (!to || tty->stopped) | 118 | if (tty->stopped) |
| 116 | return 0; | 119 | return 0; |
| 117 | ld = tty_ldisc_ref(to); | 120 | |
| 118 | 121 | /* This isn't locked but our 8K is quite sloppy so no | |
| 119 | if (ld) { | 122 | big deal */ |
| 120 | c = to->receive_room; | 123 | |
| 121 | if (c > count) | 124 | c = pty_space(to); |
| 122 | c = count; | 125 | if (c > count) |
| 123 | ld->ops->receive_buf(to, buf, NULL, c); | 126 | c = count; |
| 124 | tty_ldisc_deref(ld); | 127 | if (c > 0) { |
| 128 | /* Stuff the data into the input queue of the other end */ | ||
| 129 | c = tty_insert_flip_string(to, buf, c); | ||
| 130 | /* And shovel */ | ||
| 131 | tty_flip_buffer_push(to); | ||
| 132 | tty_wakeup(tty); | ||
| 125 | } | 133 | } |
| 126 | return c; | 134 | return c; |
| 127 | } | 135 | } |
| 128 | 136 | ||
| 137 | /** | ||
| 138 | * pty_write_room - write space | ||
| 139 | * @tty: tty we are writing from | ||
| 140 | * | ||
| 141 | * Report how many bytes the ldisc can send into the queue for | ||
| 142 | * the other device. | ||
| 143 | */ | ||
| 144 | |||
| 129 | static int pty_write_room(struct tty_struct *tty) | 145 | static int pty_write_room(struct tty_struct *tty) |
| 130 | { | 146 | { |
| 131 | struct tty_struct *to = tty->link; | 147 | return pty_space(tty->link); |
| 132 | |||
| 133 | if (!to || tty->stopped) | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | return to->receive_room; | ||
| 137 | } | 148 | } |
| 138 | 149 | ||
| 139 | /* | 150 | /** |
| 140 | * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior | 151 | * pty_chars_in_buffer - characters currently in our tx queue |
| 141 | * The chars_in_buffer() value is used by the ldisc select() function | 152 | * @tty: our tty |
| 142 | * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). | ||
| 143 | * The pty driver chars_in_buffer() Master/Slave must behave differently: | ||
| 144 | * | ||
| 145 | * The Master side needs to allow typed-ahead commands to accumulate | ||
| 146 | * while being canonicalized, so we report "our buffer" as empty until | ||
| 147 | * some threshold is reached, and then report the count. (Any count > | ||
| 148 | * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock | ||
| 149 | * the count returned must be 0 if no canonical data is available to be | ||
| 150 | * read. (The N_TTY ldisc.chars_in_buffer now knows this.) | ||
| 151 | * | 153 | * |
| 152 | * The Slave side passes all characters in raw mode to the Master side's | 154 | * Report how much we have in the transmit queue. As everything is |
| 153 | * buffer where they can be read immediately, so in this case we can | 155 | * instantly at the other end this is easy to implement. |
| 154 | * return the true count in the buffer. | ||
| 155 | */ | 156 | */ |
| 157 | |||
| 156 | static int pty_chars_in_buffer(struct tty_struct *tty) | 158 | static int pty_chars_in_buffer(struct tty_struct *tty) |
| 157 | { | 159 | { |
| 158 | struct tty_struct *to = tty->link; | 160 | return 0; |
| 159 | struct tty_ldisc *ld; | ||
| 160 | int count = 0; | ||
| 161 | |||
| 162 | /* We should get the line discipline lock for "tty->link" */ | ||
| 163 | if (!to) | ||
| 164 | return 0; | ||
| 165 | /* We cannot take a sleeping reference here without deadlocking with | ||
| 166 | an ldisc change - but it doesn't really matter */ | ||
| 167 | ld = tty_ldisc_ref(to); | ||
| 168 | if (ld == NULL) | ||
| 169 | return 0; | ||
| 170 | |||
| 171 | /* The ldisc must report 0 if no characters available to be read */ | ||
| 172 | if (ld->ops->chars_in_buffer) | ||
| 173 | count = ld->ops->chars_in_buffer(to); | ||
| 174 | |||
| 175 | tty_ldisc_deref(ld); | ||
| 176 | |||
| 177 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | ||
| 178 | return count; | ||
| 179 | |||
| 180 | /* Master side driver ... if the other side's read buffer is less than | ||
| 181 | * half full, return 0 to allow writers to proceed; otherwise return | ||
| 182 | * the count. This leaves a comfortable margin to avoid overflow, | ||
| 183 | * and still allows half a buffer's worth of typed-ahead commands. | ||
| 184 | */ | ||
| 185 | return (count < N_TTY_BUF_SIZE/2) ? 0 : count; | ||
| 186 | } | 161 | } |
| 187 | 162 | ||
| 188 | /* Set the lock flag on a pty */ | 163 | /* Set the lock flag on a pty */ |
| @@ -202,20 +177,10 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
| 202 | { | 177 | { |
| 203 | struct tty_struct *to = tty->link; | 178 | struct tty_struct *to = tty->link; |
| 204 | unsigned long flags; | 179 | unsigned long flags; |
| 205 | struct tty_ldisc *ld; | ||
| 206 | 180 | ||
| 207 | if (!to) | 181 | if (!to) |
| 208 | return; | 182 | return; |
| 209 | ld = tty_ldisc_ref(to); | 183 | /* tty_buffer_flush(to); FIXME */ |
| 210 | |||
| 211 | /* The other end is changing discipline */ | ||
| 212 | if (!ld) | ||
| 213 | return; | ||
| 214 | |||
| 215 | if (ld->ops->flush_buffer) | ||
| 216 | to->ldisc->ops->flush_buffer(to); | ||
| 217 | tty_ldisc_deref(ld); | ||
| 218 | |||
| 219 | if (to->packet) { | 184 | if (to->packet) { |
| 220 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 185 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
| 221 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; | 186 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index ce81da5b2da9..d58c2eb07f07 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/delay.h> | 44 | #include <linux/delay.h> |
| 45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
| 46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
| 47 | #include <linux/smp_lock.h> | ||
| 47 | #include <linux/miscdevice.h> | 48 | #include <linux/miscdevice.h> |
| 48 | #include <linux/init.h> | 49 | #include <linux/init.h> |
| 49 | 50 | ||
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 217660451237..171711acf5cd 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
| 48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
| 49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
| 50 | #include <linux/smp_lock.h> | ||
| 50 | #include <linux/spinlock.h> | 51 | #include <linux/spinlock.h> |
| 51 | #include <linux/device.h> | 52 | #include <linux/device.h> |
| 52 | 53 | ||
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 63d5b628477a..0e29a23ec4c5 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
| @@ -73,6 +73,7 @@ | |||
| 73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
| 74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
| 75 | #include <linux/serial.h> | 75 | #include <linux/serial.h> |
| 76 | #include <linux/smp_lock.h> | ||
| 76 | #include <linux/string.h> | 77 | #include <linux/string.h> |
| 77 | #include <linux/fcntl.h> | 78 | #include <linux/fcntl.h> |
| 78 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f1f24f0ee26f..51e7a46787be 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <linux/interrupt.h> | 52 | #include <linux/interrupt.h> |
| 53 | #include <linux/serial.h> | 53 | #include <linux/serial.h> |
| 54 | #include <linux/serialP.h> | 54 | #include <linux/serialP.h> |
| 55 | #include <linux/smp_lock.h> | ||
| 55 | #include <linux/string.h> | 56 | #include <linux/string.h> |
| 56 | #include <linux/fcntl.h> | 57 | #include <linux/fcntl.h> |
| 57 | #include <linux/ptrace.h> | 58 | #include <linux/ptrace.h> |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index e72be4190a44..bfe4cdb2febb 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
| @@ -87,6 +87,7 @@ | |||
| 87 | #include <linux/tty_flip.h> | 87 | #include <linux/tty_flip.h> |
| 88 | #include <linux/mm.h> | 88 | #include <linux/mm.h> |
| 89 | #include <linux/serial.h> | 89 | #include <linux/serial.h> |
| 90 | #include <linux/smp_lock.h> | ||
| 90 | #include <linux/fcntl.h> | 91 | #include <linux/fcntl.h> |
| 91 | #include <linux/major.h> | 92 | #include <linux/major.h> |
| 92 | #include <linux/delay.h> | 93 | #include <linux/delay.h> |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 518f2a25d91e..a81ec4fcf6ff 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
| @@ -216,6 +216,7 @@ | |||
| 216 | #include <linux/eisa.h> | 216 | #include <linux/eisa.h> |
| 217 | #include <linux/pci.h> | 217 | #include <linux/pci.h> |
| 218 | #include <linux/slab.h> | 218 | #include <linux/slab.h> |
| 219 | #include <linux/smp_lock.h> | ||
| 219 | #include <linux/init.h> | 220 | #include <linux/init.h> |
| 220 | #include <linux/miscdevice.h> | 221 | #include <linux/miscdevice.h> |
| 221 | #include <linux/bitops.h> | 222 | #include <linux/bitops.h> |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index afded3a2379c..813552f14884 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
| @@ -81,6 +81,7 @@ | |||
| 81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
| 82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
| 83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
| 84 | #include <linux/smp_lock.h> | ||
| 84 | #include <linux/delay.h> | 85 | #include <linux/delay.h> |
| 85 | #include <linux/netdevice.h> | 86 | #include <linux/netdevice.h> |
| 86 | #include <linux/vmalloc.h> | 87 | #include <linux/vmalloc.h> |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 1386625fc4ca..91f20a92fddf 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
| 63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
| 64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
| 65 | #include <linux/smp_lock.h> | ||
| 65 | #include <linux/netdevice.h> | 66 | #include <linux/netdevice.h> |
| 66 | #include <linux/vmalloc.h> | 67 | #include <linux/vmalloc.h> |
| 67 | #include <linux/init.h> | 68 | #include <linux/init.h> |
| @@ -467,7 +468,6 @@ static unsigned int free_tbuf_count(struct slgt_info *info); | |||
| 467 | static unsigned int tbuf_bytes(struct slgt_info *info); | 468 | static unsigned int tbuf_bytes(struct slgt_info *info); |
| 468 | static void reset_tbufs(struct slgt_info *info); | 469 | static void reset_tbufs(struct slgt_info *info); |
| 469 | static void tdma_reset(struct slgt_info *info); | 470 | static void tdma_reset(struct slgt_info *info); |
| 470 | static void tdma_start(struct slgt_info *info); | ||
| 471 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | 471 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); |
| 472 | 472 | ||
| 473 | static void get_signals(struct slgt_info *info); | 473 | static void get_signals(struct slgt_info *info); |
| @@ -795,6 +795,18 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
| 795 | } | 795 | } |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | static void update_tx_timer(struct slgt_info *info) | ||
| 799 | { | ||
| 800 | /* | ||
| 801 | * use worst case speed of 1200bps to calculate transmit timeout | ||
| 802 | * based on data in buffers (tbuf_bytes) and FIFO (128 bytes) | ||
| 803 | */ | ||
| 804 | if (info->params.mode == MGSL_MODE_HDLC) { | ||
| 805 | int timeout = (tbuf_bytes(info) * 7) + 1000; | ||
| 806 | mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout)); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 798 | static int write(struct tty_struct *tty, | 810 | static int write(struct tty_struct *tty, |
| 799 | const unsigned char *buf, int count) | 811 | const unsigned char *buf, int count) |
| 800 | { | 812 | { |
| @@ -838,8 +850,18 @@ start: | |||
| 838 | spin_lock_irqsave(&info->lock,flags); | 850 | spin_lock_irqsave(&info->lock,flags); |
| 839 | if (!info->tx_active) | 851 | if (!info->tx_active) |
| 840 | tx_start(info); | 852 | tx_start(info); |
| 841 | else | 853 | else if (!(rd_reg32(info, TDCSR) & BIT0)) { |
| 842 | tdma_start(info); | 854 | /* transmit still active but transmit DMA stopped */ |
| 855 | unsigned int i = info->tbuf_current; | ||
| 856 | if (!i) | ||
| 857 | i = info->tbuf_count; | ||
| 858 | i--; | ||
| 859 | /* if DMA buf unsent must try later after tx idle */ | ||
| 860 | if (desc_count(info->tbufs[i])) | ||
| 861 | ret = 0; | ||
| 862 | } | ||
| 863 | if (ret > 0) | ||
| 864 | update_tx_timer(info); | ||
| 843 | spin_unlock_irqrestore(&info->lock,flags); | 865 | spin_unlock_irqrestore(&info->lock,flags); |
| 844 | } | 866 | } |
| 845 | 867 | ||
| @@ -1502,10 +1524,9 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1502 | /* save start time for transmit timeout detection */ | 1524 | /* save start time for transmit timeout detection */ |
| 1503 | dev->trans_start = jiffies; | 1525 | dev->trans_start = jiffies; |
| 1504 | 1526 | ||
| 1505 | /* start hardware transmitter if necessary */ | ||
| 1506 | spin_lock_irqsave(&info->lock,flags); | 1527 | spin_lock_irqsave(&info->lock,flags); |
| 1507 | if (!info->tx_active) | 1528 | tx_start(info); |
| 1508 | tx_start(info); | 1529 | update_tx_timer(info); |
| 1509 | spin_unlock_irqrestore(&info->lock,flags); | 1530 | spin_unlock_irqrestore(&info->lock,flags); |
| 1510 | 1531 | ||
| 1511 | return 0; | 1532 | return 0; |
| @@ -3946,50 +3967,19 @@ static void tx_start(struct slgt_info *info) | |||
| 3946 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); | 3967 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); |
| 3947 | /* clear tx idle and underrun status bits */ | 3968 | /* clear tx idle and underrun status bits */ |
| 3948 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); | 3969 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); |
| 3949 | if (info->params.mode == MGSL_MODE_HDLC) | ||
| 3950 | mod_timer(&info->tx_timer, jiffies + | ||
| 3951 | msecs_to_jiffies(5000)); | ||
| 3952 | } else { | 3970 | } else { |
| 3953 | slgt_irq_off(info, IRQ_TXDATA); | 3971 | slgt_irq_off(info, IRQ_TXDATA); |
| 3954 | slgt_irq_on(info, IRQ_TXIDLE); | 3972 | slgt_irq_on(info, IRQ_TXIDLE); |
| 3955 | /* clear tx idle status bit */ | 3973 | /* clear tx idle status bit */ |
| 3956 | wr_reg16(info, SSR, IRQ_TXIDLE); | 3974 | wr_reg16(info, SSR, IRQ_TXIDLE); |
| 3957 | } | 3975 | } |
| 3958 | tdma_start(info); | 3976 | /* set 1st descriptor address and start DMA */ |
| 3977 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
| 3978 | wr_reg32(info, TDCSR, BIT2 + BIT0); | ||
| 3959 | info->tx_active = true; | 3979 | info->tx_active = true; |
| 3960 | } | 3980 | } |
| 3961 | } | 3981 | } |
| 3962 | 3982 | ||
| 3963 | /* | ||
| 3964 | * start transmit DMA if inactive and there are unsent buffers | ||
| 3965 | */ | ||
| 3966 | static void tdma_start(struct slgt_info *info) | ||
| 3967 | { | ||
| 3968 | unsigned int i; | ||
| 3969 | |||
| 3970 | if (rd_reg32(info, TDCSR) & BIT0) | ||
| 3971 | return; | ||
| 3972 | |||
| 3973 | /* transmit DMA inactive, check for unsent buffers */ | ||
| 3974 | i = info->tbuf_start; | ||
| 3975 | while (!desc_count(info->tbufs[i])) { | ||
| 3976 | if (++i == info->tbuf_count) | ||
| 3977 | i = 0; | ||
| 3978 | if (i == info->tbuf_current) | ||
| 3979 | return; | ||
| 3980 | } | ||
| 3981 | info->tbuf_start = i; | ||
| 3982 | |||
| 3983 | /* there are unsent buffers, start transmit DMA */ | ||
| 3984 | |||
| 3985 | /* reset needed if previous error condition */ | ||
| 3986 | tdma_reset(info); | ||
| 3987 | |||
| 3988 | /* set 1st descriptor address */ | ||
| 3989 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
| 3990 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
| 3991 | } | ||
| 3992 | |||
| 3993 | static void tx_stop(struct slgt_info *info) | 3983 | static void tx_stop(struct slgt_info *info) |
| 3994 | { | 3984 | { |
| 3995 | unsigned short val; | 3985 | unsigned short val; |
| @@ -5004,8 +4994,7 @@ static void tx_timeout(unsigned long context) | |||
| 5004 | info->icount.txtimeout++; | 4994 | info->icount.txtimeout++; |
| 5005 | } | 4995 | } |
| 5006 | spin_lock_irqsave(&info->lock,flags); | 4996 | spin_lock_irqsave(&info->lock,flags); |
| 5007 | info->tx_active = false; | 4997 | tx_stop(info); |
| 5008 | info->tx_count = 0; | ||
| 5009 | spin_unlock_irqrestore(&info->lock,flags); | 4998 | spin_unlock_irqrestore(&info->lock,flags); |
| 5010 | 4999 | ||
| 5011 | #if SYNCLINK_GENERIC_HDLC | 5000 | #if SYNCLINK_GENERIC_HDLC |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 6f727e3c53ad..8d4a2a8a0a70 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
| 53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
| 54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
| 55 | #include <linux/smp_lock.h> | ||
| 55 | #include <linux/netdevice.h> | 56 | #include <linux/netdevice.h> |
| 56 | #include <linux/vmalloc.h> | 57 | #include <linux/vmalloc.h> |
| 57 | #include <linux/init.h> | 58 | #include <linux/init.h> |
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 6062b62800fd..b3ec9b10e292 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for TANBAC TB0219 base board. | 2 | * Driver for TANBAC TB0219 base board. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -28,7 +28,7 @@ | |||
| 28 | #include <asm/vr41xx/giu.h> | 28 | #include <asm/vr41xx/giu.h> |
| 29 | #include <asm/vr41xx/tb0219.h> | 29 | #include <asm/vr41xx/tb0219.h> |
| 30 | 30 | ||
| 31 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 31 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
| 32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); | 32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); |
| 33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 34 | 34 | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ccdd828adcef..b0603b2e5684 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/poll.h> | 26 | #include <linux/poll.h> |
| 27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
| 28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | 29 | ||
| 31 | #include "tpm.h" | 30 | #include "tpm.h" |
| 32 | 31 | ||
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index b24f6c6a1ea3..ad6ba4ed2808 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <linux/smp_lock.h> | ||
| 25 | 24 | ||
| 26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
| 27 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index a19e935847b0..acd76b767d4c 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/smp_lock.h> | ||
| 25 | #include <linux/device.h> | 24 | #include <linux/device.h> |
| 26 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
| 27 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
| @@ -791,17 +790,20 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
| 791 | * N_TTY. | 790 | * N_TTY. |
| 792 | */ | 791 | */ |
| 793 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | 792 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { |
| 794 | /* Avoid racing set_ldisc */ | 793 | /* Avoid racing set_ldisc or tty_ldisc_release */ |
| 795 | mutex_lock(&tty->ldisc_mutex); | 794 | mutex_lock(&tty->ldisc_mutex); |
| 796 | /* Switch back to N_TTY */ | 795 | if (tty->ldisc) { /* Not yet closed */ |
| 797 | tty_ldisc_halt(tty); | 796 | /* Switch back to N_TTY */ |
| 798 | tty_ldisc_wait_idle(tty); | 797 | tty_ldisc_halt(tty); |
| 799 | tty_ldisc_reinit(tty); | 798 | tty_ldisc_wait_idle(tty); |
| 800 | /* At this point we have a closed ldisc and we want to | 799 | tty_ldisc_reinit(tty); |
| 801 | reopen it. We could defer this to the next open but | 800 | /* At this point we have a closed ldisc and we want to |
| 802 | it means auditing a lot of other paths so this is a FIXME */ | 801 | reopen it. We could defer this to the next open but |
| 803 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | 802 | it means auditing a lot of other paths so this is |
| 804 | tty_ldisc_enable(tty); | 803 | a FIXME */ |
| 804 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | ||
| 805 | tty_ldisc_enable(tty); | ||
| 806 | } | ||
| 805 | mutex_unlock(&tty->ldisc_mutex); | 807 | mutex_unlock(&tty->ldisc_mutex); |
| 806 | tty_reset_termios(tty); | 808 | tty_reset_termios(tty); |
| 807 | } | 809 | } |
| @@ -866,16 +868,25 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
| 866 | 868 | ||
| 867 | tty_ldisc_wait_idle(tty); | 869 | tty_ldisc_wait_idle(tty); |
| 868 | 870 | ||
| 871 | mutex_lock(&tty->ldisc_mutex); | ||
| 869 | /* | 872 | /* |
| 870 | * Shutdown the current line discipline, and reset it to N_TTY. | 873 | * Now kill off the ldisc |
| 871 | * | ||
| 872 | * FIXME: this MUST get fixed for the new reflocking | ||
| 873 | */ | 874 | */ |
| 875 | tty_ldisc_close(tty, tty->ldisc); | ||
| 876 | tty_ldisc_put(tty->ldisc); | ||
| 877 | /* Force an oops if we mess this up */ | ||
| 878 | tty->ldisc = NULL; | ||
| 879 | |||
| 880 | /* Ensure the next open requests the N_TTY ldisc */ | ||
| 881 | tty_set_termios_ldisc(tty, N_TTY); | ||
| 882 | mutex_unlock(&tty->ldisc_mutex); | ||
| 874 | 883 | ||
| 875 | tty_ldisc_reinit(tty); | ||
| 876 | /* This will need doing differently if we need to lock */ | 884 | /* This will need doing differently if we need to lock */ |
| 877 | if (o_tty) | 885 | if (o_tty) |
| 878 | tty_ldisc_release(o_tty, NULL); | 886 | tty_ldisc_release(o_tty, NULL); |
| 887 | |||
| 888 | /* And the memory resources remaining (buffers, termios) will be | ||
| 889 | disposed of when the kref hits zero */ | ||
| 879 | } | 890 | } |
| 880 | 891 | ||
| 881 | /** | 892 | /** |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index 62dadfc95e34..9769b1149f76 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
| @@ -193,7 +193,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 193 | { | 193 | { |
| 194 | int do_clocal = 0, retval; | 194 | int do_clocal = 0, retval; |
| 195 | unsigned long flags; | 195 | unsigned long flags; |
| 196 | DECLARE_WAITQUEUE(wait, current); | 196 | DEFINE_WAIT(wait); |
| 197 | int cd; | 197 | int cd; |
| 198 | 198 | ||
| 199 | /* block if port is in the process of being closed */ | 199 | /* block if port is in the process of being closed */ |
| @@ -267,7 +267,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 267 | if (retval == 0) | 267 | if (retval == 0) |
| 268 | port->flags |= ASYNC_NORMAL_ACTIVE; | 268 | port->flags |= ASYNC_NORMAL_ACTIVE; |
| 269 | spin_unlock_irqrestore(&port->lock, flags); | 269 | spin_unlock_irqrestore(&port->lock, flags); |
| 270 | return 0; | 270 | return retval; |
| 271 | 271 | ||
| 272 | } | 272 | } |
| 273 | EXPORT_SYMBOL(tty_port_block_til_ready); | 273 | EXPORT_SYMBOL(tty_port_block_til_ready); |
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 54c837288d19..e69de29bb2d1 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
| @@ -1,680 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
| 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
| 6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/fs.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/irq.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/smp_lock.h> | ||
| 31 | #include <linux/spinlock.h> | ||
| 32 | #include <linux/types.h> | ||
| 33 | |||
| 34 | #include <asm/io.h> | ||
| 35 | #include <asm/vr41xx/giu.h> | ||
| 36 | #include <asm/vr41xx/irq.h> | ||
| 37 | #include <asm/vr41xx/vr41xx.h> | ||
| 38 | |||
| 39 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | ||
| 40 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
| 41 | MODULE_LICENSE("GPL"); | ||
| 42 | |||
| 43 | static int major; /* default is dynamic major device number */ | ||
| 44 | module_param(major, int, 0); | ||
| 45 | MODULE_PARM_DESC(major, "Major device number"); | ||
| 46 | |||
| 47 | #define GIUIOSELL 0x00 | ||
| 48 | #define GIUIOSELH 0x02 | ||
| 49 | #define GIUPIODL 0x04 | ||
| 50 | #define GIUPIODH 0x06 | ||
| 51 | #define GIUINTSTATL 0x08 | ||
| 52 | #define GIUINTSTATH 0x0a | ||
| 53 | #define GIUINTENL 0x0c | ||
| 54 | #define GIUINTENH 0x0e | ||
| 55 | #define GIUINTTYPL 0x10 | ||
| 56 | #define GIUINTTYPH 0x12 | ||
| 57 | #define GIUINTALSELL 0x14 | ||
| 58 | #define GIUINTALSELH 0x16 | ||
| 59 | #define GIUINTHTSELL 0x18 | ||
| 60 | #define GIUINTHTSELH 0x1a | ||
| 61 | #define GIUPODATL 0x1c | ||
| 62 | #define GIUPODATEN 0x1c | ||
| 63 | #define GIUPODATH 0x1e | ||
| 64 | #define PIOEN0 0x0100 | ||
| 65 | #define PIOEN1 0x0200 | ||
| 66 | #define GIUPODAT 0x1e | ||
| 67 | #define GIUFEDGEINHL 0x20 | ||
| 68 | #define GIUFEDGEINHH 0x22 | ||
| 69 | #define GIUREDGEINHL 0x24 | ||
| 70 | #define GIUREDGEINHH 0x26 | ||
| 71 | |||
| 72 | #define GIUUSEUPDN 0x1e0 | ||
| 73 | #define GIUTERMUPDN 0x1e2 | ||
| 74 | |||
| 75 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
| 76 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
| 77 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
| 78 | |||
| 79 | static spinlock_t giu_lock; | ||
| 80 | static unsigned long giu_flags; | ||
| 81 | static unsigned int giu_nr_pins; | ||
| 82 | |||
| 83 | static void __iomem *giu_base; | ||
| 84 | |||
| 85 | #define giu_read(offset) readw(giu_base + (offset)) | ||
| 86 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
| 87 | |||
| 88 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
| 89 | #define GIUINT_HIGH_OFFSET 16 | ||
| 90 | #define GIUINT_HIGH_MAX 32 | ||
| 91 | |||
| 92 | static inline uint16_t giu_set(uint16_t offset, uint16_t set) | ||
| 93 | { | ||
| 94 | uint16_t data; | ||
| 95 | |||
| 96 | data = giu_read(offset); | ||
| 97 | data |= set; | ||
| 98 | giu_write(offset, data); | ||
| 99 | |||
| 100 | return data; | ||
| 101 | } | ||
| 102 | |||
| 103 | static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | ||
| 104 | { | ||
| 105 | uint16_t data; | ||
| 106 | |||
| 107 | data = giu_read(offset); | ||
| 108 | data &= ~clear; | ||
| 109 | giu_write(offset, data); | ||
| 110 | |||
| 111 | return data; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void ack_giuint_low(unsigned int irq) | ||
| 115 | { | ||
| 116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void mask_giuint_low(unsigned int irq) | ||
| 120 | { | ||
| 121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void mask_ack_giuint_low(unsigned int irq) | ||
| 125 | { | ||
| 126 | unsigned int pin; | ||
| 127 | |||
| 128 | pin = GPIO_PIN_OF_IRQ(irq); | ||
| 129 | giu_clear(GIUINTENL, 1 << pin); | ||
| 130 | giu_write(GIUINTSTATL, 1 << pin); | ||
| 131 | } | ||
| 132 | |||
| 133 | static void unmask_giuint_low(unsigned int irq) | ||
| 134 | { | ||
| 135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 136 | } | ||
| 137 | |||
| 138 | static struct irq_chip giuint_low_irq_chip = { | ||
| 139 | .name = "GIUINTL", | ||
| 140 | .ack = ack_giuint_low, | ||
| 141 | .mask = mask_giuint_low, | ||
| 142 | .mask_ack = mask_ack_giuint_low, | ||
| 143 | .unmask = unmask_giuint_low, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static void ack_giuint_high(unsigned int irq) | ||
| 147 | { | ||
| 148 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void mask_giuint_high(unsigned int irq) | ||
| 152 | { | ||
| 153 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void mask_ack_giuint_high(unsigned int irq) | ||
| 157 | { | ||
| 158 | unsigned int pin; | ||
| 159 | |||
| 160 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
| 161 | giu_clear(GIUINTENH, 1 << pin); | ||
| 162 | giu_write(GIUINTSTATH, 1 << pin); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void unmask_giuint_high(unsigned int irq) | ||
| 166 | { | ||
| 167 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 168 | } | ||
| 169 | |||
| 170 | static struct irq_chip giuint_high_irq_chip = { | ||
| 171 | .name = "GIUINTH", | ||
| 172 | .ack = ack_giuint_high, | ||
| 173 | .mask = mask_giuint_high, | ||
| 174 | .mask_ack = mask_ack_giuint_high, | ||
| 175 | .unmask = unmask_giuint_high, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static int giu_get_irq(unsigned int irq) | ||
| 179 | { | ||
| 180 | uint16_t pendl, pendh, maskl, maskh; | ||
| 181 | int i; | ||
| 182 | |||
| 183 | pendl = giu_read(GIUINTSTATL); | ||
| 184 | pendh = giu_read(GIUINTSTATH); | ||
| 185 | maskl = giu_read(GIUINTENL); | ||
| 186 | maskh = giu_read(GIUINTENH); | ||
| 187 | |||
| 188 | maskl &= pendl; | ||
| 189 | maskh &= pendh; | ||
| 190 | |||
| 191 | if (maskl) { | ||
| 192 | for (i = 0; i < 16; i++) { | ||
| 193 | if (maskl & (1 << i)) | ||
| 194 | return GIU_IRQ(i); | ||
| 195 | } | ||
| 196 | } else if (maskh) { | ||
| 197 | for (i = 0; i < 16; i++) { | ||
| 198 | if (maskh & (1 << i)) | ||
| 199 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
| 204 | maskl, pendl, maskh, pendh); | ||
| 205 | |||
| 206 | atomic_inc(&irq_err_count); | ||
| 207 | |||
| 208 | return -EINVAL; | ||
| 209 | } | ||
| 210 | |||
| 211 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) | ||
| 212 | { | ||
| 213 | uint16_t mask; | ||
| 214 | |||
| 215 | if (pin < GIUINT_HIGH_OFFSET) { | ||
| 216 | mask = 1 << pin; | ||
| 217 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
| 218 | giu_set(GIUINTTYPL, mask); | ||
| 219 | if (signal == IRQ_SIGNAL_HOLD) | ||
| 220 | giu_set(GIUINTHTSELL, mask); | ||
| 221 | else | ||
| 222 | giu_clear(GIUINTHTSELL, mask); | ||
| 223 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
| 224 | switch (trigger) { | ||
| 225 | case IRQ_TRIGGER_EDGE_FALLING: | ||
| 226 | giu_set(GIUFEDGEINHL, mask); | ||
| 227 | giu_clear(GIUREDGEINHL, mask); | ||
| 228 | break; | ||
| 229 | case IRQ_TRIGGER_EDGE_RISING: | ||
| 230 | giu_clear(GIUFEDGEINHL, mask); | ||
| 231 | giu_set(GIUREDGEINHL, mask); | ||
| 232 | break; | ||
| 233 | default: | ||
| 234 | giu_set(GIUFEDGEINHL, mask); | ||
| 235 | giu_set(GIUREDGEINHL, mask); | ||
| 236 | break; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 240 | &giuint_low_irq_chip, | ||
| 241 | handle_edge_irq); | ||
| 242 | } else { | ||
| 243 | giu_clear(GIUINTTYPL, mask); | ||
| 244 | giu_clear(GIUINTHTSELL, mask); | ||
| 245 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 246 | &giuint_low_irq_chip, | ||
| 247 | handle_level_irq); | ||
| 248 | } | ||
| 249 | giu_write(GIUINTSTATL, mask); | ||
| 250 | } else if (pin < GIUINT_HIGH_MAX) { | ||
| 251 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
| 252 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
| 253 | giu_set(GIUINTTYPH, mask); | ||
| 254 | if (signal == IRQ_SIGNAL_HOLD) | ||
| 255 | giu_set(GIUINTHTSELH, mask); | ||
| 256 | else | ||
| 257 | giu_clear(GIUINTHTSELH, mask); | ||
| 258 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
| 259 | switch (trigger) { | ||
| 260 | case IRQ_TRIGGER_EDGE_FALLING: | ||
| 261 | giu_set(GIUFEDGEINHH, mask); | ||
| 262 | giu_clear(GIUREDGEINHH, mask); | ||
| 263 | break; | ||
| 264 | case IRQ_TRIGGER_EDGE_RISING: | ||
| 265 | giu_clear(GIUFEDGEINHH, mask); | ||
| 266 | giu_set(GIUREDGEINHH, mask); | ||
| 267 | break; | ||
| 268 | default: | ||
| 269 | giu_set(GIUFEDGEINHH, mask); | ||
| 270 | giu_set(GIUREDGEINHH, mask); | ||
| 271 | break; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 275 | &giuint_high_irq_chip, | ||
| 276 | handle_edge_irq); | ||
| 277 | } else { | ||
| 278 | giu_clear(GIUINTTYPH, mask); | ||
| 279 | giu_clear(GIUINTHTSELH, mask); | ||
| 280 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 281 | &giuint_high_irq_chip, | ||
| 282 | handle_level_irq); | ||
| 283 | } | ||
| 284 | giu_write(GIUINTSTATH, mask); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
| 288 | |||
| 289 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
| 290 | { | ||
| 291 | uint16_t mask; | ||
| 292 | |||
| 293 | if (pin < GIUINT_HIGH_OFFSET) { | ||
| 294 | mask = 1 << pin; | ||
| 295 | if (level == IRQ_LEVEL_HIGH) | ||
| 296 | giu_set(GIUINTALSELL, mask); | ||
| 297 | else | ||
| 298 | giu_clear(GIUINTALSELL, mask); | ||
| 299 | giu_write(GIUINTSTATL, mask); | ||
| 300 | } else if (pin < GIUINT_HIGH_MAX) { | ||
| 301 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
| 302 | if (level == IRQ_LEVEL_HIGH) | ||
| 303 | giu_set(GIUINTALSELH, mask); | ||
| 304 | else | ||
| 305 | giu_clear(GIUINTALSELH, mask); | ||
| 306 | giu_write(GIUINTSTATH, mask); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
| 310 | |||
| 311 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) | ||
| 312 | { | ||
| 313 | uint16_t reg, mask; | ||
| 314 | |||
| 315 | if (pin >= giu_nr_pins) | ||
| 316 | return GPIO_DATA_INVAL; | ||
| 317 | |||
| 318 | if (pin < 16) { | ||
| 319 | reg = giu_read(GIUPIODL); | ||
| 320 | mask = (uint16_t)1 << pin; | ||
| 321 | } else if (pin < 32) { | ||
| 322 | reg = giu_read(GIUPIODH); | ||
| 323 | mask = (uint16_t)1 << (pin - 16); | ||
| 324 | } else if (pin < 48) { | ||
| 325 | reg = giu_read(GIUPODATL); | ||
| 326 | mask = (uint16_t)1 << (pin - 32); | ||
| 327 | } else { | ||
| 328 | reg = giu_read(GIUPODATH); | ||
| 329 | mask = (uint16_t)1 << (pin - 48); | ||
| 330 | } | ||
| 331 | |||
| 332 | if (reg & mask) | ||
| 333 | return GPIO_DATA_HIGH; | ||
| 334 | |||
| 335 | return GPIO_DATA_LOW; | ||
| 336 | } | ||
| 337 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); | ||
| 338 | |||
| 339 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) | ||
| 340 | { | ||
| 341 | uint16_t offset, mask, reg; | ||
| 342 | unsigned long flags; | ||
| 343 | |||
| 344 | if (pin >= giu_nr_pins) | ||
| 345 | return -EINVAL; | ||
| 346 | |||
| 347 | if (pin < 16) { | ||
| 348 | offset = GIUPIODL; | ||
| 349 | mask = (uint16_t)1 << pin; | ||
| 350 | } else if (pin < 32) { | ||
| 351 | offset = GIUPIODH; | ||
| 352 | mask = (uint16_t)1 << (pin - 16); | ||
| 353 | } else if (pin < 48) { | ||
| 354 | offset = GIUPODATL; | ||
| 355 | mask = (uint16_t)1 << (pin - 32); | ||
| 356 | } else { | ||
| 357 | offset = GIUPODATH; | ||
| 358 | mask = (uint16_t)1 << (pin - 48); | ||
| 359 | } | ||
| 360 | |||
| 361 | spin_lock_irqsave(&giu_lock, flags); | ||
| 362 | |||
| 363 | reg = giu_read(offset); | ||
| 364 | if (data == GPIO_DATA_HIGH) | ||
| 365 | reg |= mask; | ||
| 366 | else | ||
| 367 | reg &= ~mask; | ||
| 368 | giu_write(offset, reg); | ||
| 369 | |||
| 370 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); | ||
| 375 | |||
| 376 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) | ||
| 377 | { | ||
| 378 | uint16_t offset, mask, reg; | ||
| 379 | unsigned long flags; | ||
| 380 | |||
| 381 | if (pin >= giu_nr_pins) | ||
| 382 | return -EINVAL; | ||
| 383 | |||
| 384 | if (pin < 16) { | ||
| 385 | offset = GIUIOSELL; | ||
| 386 | mask = (uint16_t)1 << pin; | ||
| 387 | } else if (pin < 32) { | ||
| 388 | offset = GIUIOSELH; | ||
| 389 | mask = (uint16_t)1 << (pin - 16); | ||
| 390 | } else { | ||
| 391 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
| 392 | offset = GIUPODATEN; | ||
| 393 | mask = (uint16_t)1 << (pin - 32); | ||
| 394 | } else { | ||
| 395 | switch (pin) { | ||
| 396 | case 48: | ||
| 397 | offset = GIUPODATH; | ||
| 398 | mask = PIOEN0; | ||
| 399 | break; | ||
| 400 | case 49: | ||
| 401 | offset = GIUPODATH; | ||
| 402 | mask = PIOEN1; | ||
| 403 | break; | ||
| 404 | default: | ||
| 405 | return -EINVAL; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | spin_lock_irqsave(&giu_lock, flags); | ||
| 411 | |||
| 412 | reg = giu_read(offset); | ||
| 413 | if (dir == GPIO_OUTPUT) | ||
| 414 | reg |= mask; | ||
| 415 | else | ||
| 416 | reg &= ~mask; | ||
| 417 | giu_write(offset, reg); | ||
| 418 | |||
| 419 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 420 | |||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); | ||
| 424 | |||
| 425 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
| 426 | { | ||
| 427 | uint16_t reg, mask; | ||
| 428 | unsigned long flags; | ||
| 429 | |||
| 430 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
| 431 | return -EPERM; | ||
| 432 | |||
| 433 | if (pin >= 15) | ||
| 434 | return -EINVAL; | ||
| 435 | |||
| 436 | mask = (uint16_t)1 << pin; | ||
| 437 | |||
| 438 | spin_lock_irqsave(&giu_lock, flags); | ||
| 439 | |||
| 440 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
| 441 | reg = giu_read(GIUTERMUPDN); | ||
| 442 | if (pull == GPIO_PULL_UP) | ||
| 443 | reg |= mask; | ||
| 444 | else | ||
| 445 | reg &= ~mask; | ||
| 446 | giu_write(GIUTERMUPDN, reg); | ||
| 447 | |||
| 448 | reg = giu_read(GIUUSEUPDN); | ||
| 449 | reg |= mask; | ||
| 450 | giu_write(GIUUSEUPDN, reg); | ||
| 451 | } else { | ||
| 452 | reg = giu_read(GIUUSEUPDN); | ||
| 453 | reg &= ~mask; | ||
| 454 | giu_write(GIUUSEUPDN, reg); | ||
| 455 | } | ||
| 456 | |||
| 457 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 458 | |||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
| 462 | |||
| 463 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, | ||
| 464 | loff_t *ppos) | ||
| 465 | { | ||
| 466 | unsigned int pin; | ||
| 467 | char value = '0'; | ||
| 468 | |||
| 469 | pin = iminor(file->f_path.dentry->d_inode); | ||
| 470 | if (pin >= giu_nr_pins) | ||
| 471 | return -EBADF; | ||
| 472 | |||
| 473 | if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) | ||
| 474 | value = '1'; | ||
| 475 | |||
| 476 | if (len <= 0) | ||
| 477 | return -EFAULT; | ||
| 478 | |||
| 479 | if (put_user(value, buf)) | ||
| 480 | return -EFAULT; | ||
| 481 | |||
| 482 | return 1; | ||
| 483 | } | ||
| 484 | |||
| 485 | static ssize_t gpio_write(struct file *file, const char __user *data, | ||
| 486 | size_t len, loff_t *ppos) | ||
| 487 | { | ||
| 488 | unsigned int pin; | ||
| 489 | size_t i; | ||
| 490 | char c; | ||
| 491 | int retval = 0; | ||
| 492 | |||
| 493 | pin = iminor(file->f_path.dentry->d_inode); | ||
| 494 | if (pin >= giu_nr_pins) | ||
| 495 | return -EBADF; | ||
| 496 | |||
| 497 | for (i = 0; i < len; i++) { | ||
| 498 | if (get_user(c, data + i)) | ||
| 499 | return -EFAULT; | ||
| 500 | |||
| 501 | switch (c) { | ||
| 502 | case '0': | ||
| 503 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); | ||
| 504 | break; | ||
| 505 | case '1': | ||
| 506 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); | ||
| 507 | break; | ||
| 508 | case 'D': | ||
| 509 | printk(KERN_INFO "GPIO%d: pull down\n", pin); | ||
| 510 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); | ||
| 511 | break; | ||
| 512 | case 'd': | ||
| 513 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
| 514 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
| 515 | break; | ||
| 516 | case 'I': | ||
| 517 | printk(KERN_INFO "GPIO%d: input\n", pin); | ||
| 518 | retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); | ||
| 519 | break; | ||
| 520 | case 'O': | ||
| 521 | printk(KERN_INFO "GPIO%d: output\n", pin); | ||
| 522 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); | ||
| 523 | break; | ||
| 524 | case 'o': | ||
| 525 | printk(KERN_INFO "GPIO%d: output disable\n", pin); | ||
| 526 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); | ||
| 527 | break; | ||
| 528 | case 'P': | ||
| 529 | printk(KERN_INFO "GPIO%d: pull up\n", pin); | ||
| 530 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); | ||
| 531 | break; | ||
| 532 | case 'p': | ||
| 533 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
| 534 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
| 535 | break; | ||
| 536 | default: | ||
| 537 | break; | ||
| 538 | } | ||
| 539 | |||
| 540 | if (retval < 0) | ||
| 541 | break; | ||
| 542 | } | ||
| 543 | |||
| 544 | return i; | ||
| 545 | } | ||
| 546 | |||
| 547 | static int gpio_open(struct inode *inode, struct file *file) | ||
| 548 | { | ||
| 549 | unsigned int pin; | ||
| 550 | |||
| 551 | cycle_kernel_lock(); | ||
| 552 | pin = iminor(inode); | ||
| 553 | if (pin >= giu_nr_pins) | ||
| 554 | return -EBADF; | ||
| 555 | |||
| 556 | return nonseekable_open(inode, file); | ||
| 557 | } | ||
| 558 | |||
| 559 | static int gpio_release(struct inode *inode, struct file *file) | ||
| 560 | { | ||
| 561 | unsigned int pin; | ||
| 562 | |||
| 563 | pin = iminor(inode); | ||
| 564 | if (pin >= giu_nr_pins) | ||
| 565 | return -EBADF; | ||
| 566 | |||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | static const struct file_operations gpio_fops = { | ||
| 571 | .owner = THIS_MODULE, | ||
| 572 | .read = gpio_read, | ||
| 573 | .write = gpio_write, | ||
| 574 | .open = gpio_open, | ||
| 575 | .release = gpio_release, | ||
| 576 | }; | ||
| 577 | |||
| 578 | static int __devinit giu_probe(struct platform_device *dev) | ||
| 579 | { | ||
| 580 | struct resource *res; | ||
| 581 | unsigned int trigger, i, pin; | ||
| 582 | struct irq_chip *chip; | ||
| 583 | int irq, retval; | ||
| 584 | |||
| 585 | switch (dev->id) { | ||
| 586 | case GPIO_50PINS_PULLUPDOWN: | ||
| 587 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
| 588 | giu_nr_pins = 50; | ||
| 589 | break; | ||
| 590 | case GPIO_36PINS: | ||
| 591 | giu_nr_pins = 36; | ||
| 592 | break; | ||
| 593 | case GPIO_48PINS_EDGE_SELECT: | ||
| 594 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
| 595 | giu_nr_pins = 48; | ||
| 596 | break; | ||
| 597 | default: | ||
| 598 | printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); | ||
| 599 | return -ENODEV; | ||
| 600 | } | ||
| 601 | |||
| 602 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
| 603 | if (!res) | ||
| 604 | return -EBUSY; | ||
| 605 | |||
| 606 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
| 607 | if (!giu_base) | ||
| 608 | return -ENOMEM; | ||
| 609 | |||
| 610 | retval = register_chrdev(major, "GIU", &gpio_fops); | ||
| 611 | if (retval < 0) { | ||
| 612 | iounmap(giu_base); | ||
| 613 | giu_base = NULL; | ||
| 614 | return retval; | ||
| 615 | } | ||
| 616 | |||
| 617 | if (major == 0) { | ||
| 618 | major = retval; | ||
| 619 | printk(KERN_INFO "GIU: major number %d\n", major); | ||
| 620 | } | ||
| 621 | |||
| 622 | spin_lock_init(&giu_lock); | ||
| 623 | |||
| 624 | giu_write(GIUINTENL, 0); | ||
| 625 | giu_write(GIUINTENH, 0); | ||
| 626 | |||
| 627 | trigger = giu_read(GIUINTTYPH) << 16; | ||
| 628 | trigger |= giu_read(GIUINTTYPL); | ||
| 629 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
| 630 | pin = GPIO_PIN_OF_IRQ(i); | ||
| 631 | if (pin < GIUINT_HIGH_OFFSET) | ||
| 632 | chip = &giuint_low_irq_chip; | ||
| 633 | else | ||
| 634 | chip = &giuint_high_irq_chip; | ||
| 635 | |||
| 636 | if (trigger & (1 << pin)) | ||
| 637 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
| 638 | else | ||
| 639 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
| 640 | |||
| 641 | } | ||
| 642 | |||
| 643 | irq = platform_get_irq(dev, 0); | ||
| 644 | if (irq < 0 || irq >= nr_irqs) | ||
| 645 | return -EBUSY; | ||
| 646 | |||
| 647 | return cascade_irq(irq, giu_get_irq); | ||
| 648 | } | ||
| 649 | |||
| 650 | static int __devexit giu_remove(struct platform_device *dev) | ||
| 651 | { | ||
| 652 | if (giu_base) { | ||
| 653 | iounmap(giu_base); | ||
| 654 | giu_base = NULL; | ||
| 655 | } | ||
| 656 | |||
| 657 | return 0; | ||
| 658 | } | ||
| 659 | |||
| 660 | static struct platform_driver giu_device_driver = { | ||
| 661 | .probe = giu_probe, | ||
| 662 | .remove = __devexit_p(giu_remove), | ||
| 663 | .driver = { | ||
| 664 | .name = "GIU", | ||
| 665 | .owner = THIS_MODULE, | ||
| 666 | }, | ||
| 667 | }; | ||
| 668 | |||
| 669 | static int __init vr41xx_giu_init(void) | ||
| 670 | { | ||
| 671 | return platform_driver_register(&giu_device_driver); | ||
| 672 | } | ||
| 673 | |||
| 674 | static void __exit vr41xx_giu_exit(void) | ||
| 675 | { | ||
| 676 | platform_driver_unregister(&giu_device_driver); | ||
| 677 | } | ||
| 678 | |||
| 679 | module_init(vr41xx_giu_init); | ||
| 680 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index d9113b4c76e3..404f4c1ee431 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
| @@ -89,6 +89,7 @@ | |||
| 89 | #include <linux/mutex.h> | 89 | #include <linux/mutex.h> |
| 90 | #include <linux/vt_kern.h> | 90 | #include <linux/vt_kern.h> |
| 91 | #include <linux/selection.h> | 91 | #include <linux/selection.h> |
| 92 | #include <linux/smp_lock.h> | ||
| 92 | #include <linux/tiocl.h> | 93 | #include <linux/tiocl.h> |
| 93 | #include <linux/kbd_kern.h> | 94 | #include <linux/kbd_kern.h> |
| 94 | #include <linux/consolemap.h> | 95 | #include <linux/consolemap.h> |
| @@ -769,14 +770,12 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
| 769 | visual_init(vc, currcons, 1); | 770 | visual_init(vc, currcons, 1); |
| 770 | if (!*vc->vc_uni_pagedir_loc) | 771 | if (!*vc->vc_uni_pagedir_loc) |
| 771 | con_set_default_unimap(vc); | 772 | con_set_default_unimap(vc); |
| 772 | if (!vc->vc_kmalloced) | 773 | vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); |
| 773 | vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); | ||
| 774 | if (!vc->vc_screenbuf) { | 774 | if (!vc->vc_screenbuf) { |
| 775 | kfree(vc); | 775 | kfree(vc); |
| 776 | vc_cons[currcons].d = NULL; | 776 | vc_cons[currcons].d = NULL; |
| 777 | return -ENOMEM; | 777 | return -ENOMEM; |
| 778 | } | 778 | } |
| 779 | vc->vc_kmalloced = 1; | ||
| 780 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); | 779 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); |
| 781 | vcs_make_sysfs(currcons); | 780 | vcs_make_sysfs(currcons); |
| 782 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); | 781 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); |
| @@ -912,10 +911,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
| 912 | if (new_scr_end > new_origin) | 911 | if (new_scr_end > new_origin) |
| 913 | scr_memsetw((void *)new_origin, vc->vc_video_erase_char, | 912 | scr_memsetw((void *)new_origin, vc->vc_video_erase_char, |
| 914 | new_scr_end - new_origin); | 913 | new_scr_end - new_origin); |
| 915 | if (vc->vc_kmalloced) | 914 | kfree(vc->vc_screenbuf); |
| 916 | kfree(vc->vc_screenbuf); | ||
| 917 | vc->vc_screenbuf = newscreen; | 915 | vc->vc_screenbuf = newscreen; |
| 918 | vc->vc_kmalloced = 1; | ||
| 919 | vc->vc_screenbuf_size = new_screen_size; | 916 | vc->vc_screenbuf_size = new_screen_size; |
| 920 | set_origin(vc); | 917 | set_origin(vc); |
| 921 | 918 | ||
| @@ -994,8 +991,7 @@ void vc_deallocate(unsigned int currcons) | |||
| 994 | vc->vc_sw->con_deinit(vc); | 991 | vc->vc_sw->con_deinit(vc); |
| 995 | put_pid(vc->vt_pid); | 992 | put_pid(vc->vt_pid); |
| 996 | module_put(vc->vc_sw->owner); | 993 | module_put(vc->vc_sw->owner); |
| 997 | if (vc->vc_kmalloced) | 994 | kfree(vc->vc_screenbuf); |
| 998 | kfree(vc->vc_screenbuf); | ||
| 999 | if (currcons >= MIN_NR_CONSOLES) | 995 | if (currcons >= MIN_NR_CONSOLES) |
| 1000 | kfree(vc); | 996 | kfree(vc); |
| 1001 | vc_cons[currcons].d = NULL; | 997 | vc_cons[currcons].d = NULL; |
| @@ -2880,7 +2876,6 @@ static int __init con_init(void) | |||
| 2880 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2876 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
| 2881 | visual_init(vc, currcons, 1); | 2877 | visual_init(vc, currcons, 1); |
| 2882 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); | 2878 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
| 2883 | vc->vc_kmalloced = 0; | ||
| 2884 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2879 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
| 2885 | currcons || !vc->vc_sw->con_save_screen); | 2880 | currcons || !vc->vc_sw->con_save_screen); |
| 2886 | } | 2881 | } |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 7539bed0f7e0..95189f288f8c 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/console.h> | 25 | #include <linux/console.h> |
| 26 | #include <linux/consolemap.h> | 26 | #include <linux/consolemap.h> |
| 27 | #include <linux/signal.h> | 27 | #include <linux/signal.h> |
| 28 | #include <linux/smp_lock.h> | ||
| 28 | #include <linux/timex.h> | 29 | #include <linux/timex.h> |
| 29 | 30 | ||
| 30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 9ffb05f4095d..93c2322feab7 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
| @@ -161,7 +161,7 @@ static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, | |||
| 161 | if (periodic) | 161 | if (periodic) |
| 162 | sh_tmu_write(p, TCOR, delta); | 162 | sh_tmu_write(p, TCOR, delta); |
| 163 | else | 163 | else |
| 164 | sh_tmu_write(p, TCOR, 0); | 164 | sh_tmu_write(p, TCOR, 0xffffffff); |
| 165 | 165 | ||
| 166 | sh_tmu_write(p, TCNT, delta); | 166 | sh_tmu_write(p, TCNT, delta); |
| 167 | 167 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6e2ec0b18948..b90eda8b3440 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = { | |||
| 761 | * cpufreq_add_dev - add a CPU device | 761 | * cpufreq_add_dev - add a CPU device |
| 762 | * | 762 | * |
| 763 | * Adds the cpufreq interface for a CPU device. | 763 | * Adds the cpufreq interface for a CPU device. |
| 764 | * | ||
| 765 | * The Oracle says: try running cpufreq registration/unregistration concurrently | ||
| 766 | * with with cpu hotplugging and all hell will break loose. Tried to clean this | ||
| 767 | * mess up, but more thorough testing is needed. - Mathieu | ||
| 764 | */ | 768 | */ |
| 765 | static int cpufreq_add_dev(struct sys_device *sys_dev) | 769 | static int cpufreq_add_dev(struct sys_device *sys_dev) |
| 766 | { | 770 | { |
| @@ -772,9 +776,6 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 772 | struct sys_device *cpu_sys_dev; | 776 | struct sys_device *cpu_sys_dev; |
| 773 | unsigned long flags; | 777 | unsigned long flags; |
| 774 | unsigned int j; | 778 | unsigned int j; |
| 775 | #ifdef CONFIG_SMP | ||
| 776 | struct cpufreq_policy *managed_policy; | ||
| 777 | #endif | ||
| 778 | 779 | ||
| 779 | if (cpu_is_offline(cpu)) | 780 | if (cpu_is_offline(cpu)) |
| 780 | return 0; | 781 | return 0; |
| @@ -804,15 +805,12 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 804 | goto nomem_out; | 805 | goto nomem_out; |
| 805 | } | 806 | } |
| 806 | if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) { | 807 | if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) { |
| 807 | kfree(policy); | ||
| 808 | ret = -ENOMEM; | 808 | ret = -ENOMEM; |
| 809 | goto nomem_out; | 809 | goto err_free_policy; |
| 810 | } | 810 | } |
| 811 | if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { | 811 | if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { |
| 812 | free_cpumask_var(policy->cpus); | ||
| 813 | kfree(policy); | ||
| 814 | ret = -ENOMEM; | 812 | ret = -ENOMEM; |
| 815 | goto nomem_out; | 813 | goto err_free_cpumask; |
| 816 | } | 814 | } |
| 817 | 815 | ||
| 818 | policy->cpu = cpu; | 816 | policy->cpu = cpu; |
| @@ -820,7 +818,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 820 | 818 | ||
| 821 | /* Initially set CPU itself as the policy_cpu */ | 819 | /* Initially set CPU itself as the policy_cpu */ |
| 822 | per_cpu(policy_cpu, cpu) = cpu; | 820 | per_cpu(policy_cpu, cpu) = cpu; |
| 823 | lock_policy_rwsem_write(cpu); | 821 | ret = (lock_policy_rwsem_write(cpu) < 0); |
| 822 | WARN_ON(ret); | ||
| 824 | 823 | ||
| 825 | init_completion(&policy->kobj_unregister); | 824 | init_completion(&policy->kobj_unregister); |
| 826 | INIT_WORK(&policy->update, handle_update); | 825 | INIT_WORK(&policy->update, handle_update); |
| @@ -833,7 +832,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 833 | ret = cpufreq_driver->init(policy); | 832 | ret = cpufreq_driver->init(policy); |
| 834 | if (ret) { | 833 | if (ret) { |
| 835 | dprintk("initialization failed\n"); | 834 | dprintk("initialization failed\n"); |
| 836 | goto err_out; | 835 | goto err_unlock_policy; |
| 837 | } | 836 | } |
| 838 | policy->user_policy.min = policy->min; | 837 | policy->user_policy.min = policy->min; |
| 839 | policy->user_policy.max = policy->max; | 838 | policy->user_policy.max = policy->max; |
| @@ -852,21 +851,29 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 852 | #endif | 851 | #endif |
| 853 | 852 | ||
| 854 | for_each_cpu(j, policy->cpus) { | 853 | for_each_cpu(j, policy->cpus) { |
| 854 | struct cpufreq_policy *managed_policy; | ||
| 855 | |||
| 855 | if (cpu == j) | 856 | if (cpu == j) |
| 856 | continue; | 857 | continue; |
| 857 | 858 | ||
| 858 | /* Check for existing affected CPUs. | 859 | /* Check for existing affected CPUs. |
| 859 | * They may not be aware of it due to CPU Hotplug. | 860 | * They may not be aware of it due to CPU Hotplug. |
| 860 | */ | 861 | */ |
| 861 | managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */ | 862 | managed_policy = cpufreq_cpu_get(j); |
| 862 | if (unlikely(managed_policy)) { | 863 | if (unlikely(managed_policy)) { |
| 863 | 864 | ||
| 864 | /* Set proper policy_cpu */ | 865 | /* Set proper policy_cpu */ |
| 865 | unlock_policy_rwsem_write(cpu); | 866 | unlock_policy_rwsem_write(cpu); |
| 866 | per_cpu(policy_cpu, cpu) = managed_policy->cpu; | 867 | per_cpu(policy_cpu, cpu) = managed_policy->cpu; |
| 867 | 868 | ||
| 868 | if (lock_policy_rwsem_write(cpu) < 0) | 869 | if (lock_policy_rwsem_write(cpu) < 0) { |
| 869 | goto err_out_driver_exit; | 870 | /* Should not go through policy unlock path */ |
| 871 | if (cpufreq_driver->exit) | ||
| 872 | cpufreq_driver->exit(policy); | ||
| 873 | ret = -EBUSY; | ||
| 874 | cpufreq_cpu_put(managed_policy); | ||
| 875 | goto err_free_cpumask; | ||
| 876 | } | ||
| 870 | 877 | ||
| 871 | spin_lock_irqsave(&cpufreq_driver_lock, flags); | 878 | spin_lock_irqsave(&cpufreq_driver_lock, flags); |
| 872 | cpumask_copy(managed_policy->cpus, policy->cpus); | 879 | cpumask_copy(managed_policy->cpus, policy->cpus); |
| @@ -877,12 +884,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 877 | ret = sysfs_create_link(&sys_dev->kobj, | 884 | ret = sysfs_create_link(&sys_dev->kobj, |
| 878 | &managed_policy->kobj, | 885 | &managed_policy->kobj, |
| 879 | "cpufreq"); | 886 | "cpufreq"); |
| 880 | if (ret) | 887 | if (!ret) |
| 881 | goto err_out_driver_exit; | 888 | cpufreq_cpu_put(managed_policy); |
| 882 | 889 | /* | |
| 883 | cpufreq_debug_enable_ratelimit(); | 890 | * Success. We only needed to be added to the mask. |
| 884 | ret = 0; | 891 | * Call driver->exit() because only the cpu parent of |
| 885 | goto err_out_driver_exit; /* call driver->exit() */ | 892 | * the kobj needed to call init(). |
| 893 | */ | ||
| 894 | goto out_driver_exit; /* call driver->exit() */ | ||
| 886 | } | 895 | } |
| 887 | } | 896 | } |
| 888 | #endif | 897 | #endif |
| @@ -892,25 +901,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 892 | ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, | 901 | ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, |
| 893 | "cpufreq"); | 902 | "cpufreq"); |
| 894 | if (ret) | 903 | if (ret) |
| 895 | goto err_out_driver_exit; | 904 | goto out_driver_exit; |
| 896 | 905 | ||
| 897 | /* set up files for this cpu device */ | 906 | /* set up files for this cpu device */ |
| 898 | drv_attr = cpufreq_driver->attr; | 907 | drv_attr = cpufreq_driver->attr; |
| 899 | while ((drv_attr) && (*drv_attr)) { | 908 | while ((drv_attr) && (*drv_attr)) { |
| 900 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); | 909 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); |
| 901 | if (ret) | 910 | if (ret) |
| 902 | goto err_out_driver_exit; | 911 | goto err_out_kobj_put; |
| 903 | drv_attr++; | 912 | drv_attr++; |
| 904 | } | 913 | } |
| 905 | if (cpufreq_driver->get) { | 914 | if (cpufreq_driver->get) { |
| 906 | ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); | 915 | ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); |
| 907 | if (ret) | 916 | if (ret) |
| 908 | goto err_out_driver_exit; | 917 | goto err_out_kobj_put; |
| 909 | } | 918 | } |
| 910 | if (cpufreq_driver->target) { | 919 | if (cpufreq_driver->target) { |
| 911 | ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); | 920 | ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); |
| 912 | if (ret) | 921 | if (ret) |
| 913 | goto err_out_driver_exit; | 922 | goto err_out_kobj_put; |
| 914 | } | 923 | } |
| 915 | 924 | ||
| 916 | spin_lock_irqsave(&cpufreq_driver_lock, flags); | 925 | spin_lock_irqsave(&cpufreq_driver_lock, flags); |
| @@ -922,18 +931,22 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 922 | 931 | ||
| 923 | /* symlink affected CPUs */ | 932 | /* symlink affected CPUs */ |
| 924 | for_each_cpu(j, policy->cpus) { | 933 | for_each_cpu(j, policy->cpus) { |
| 934 | struct cpufreq_policy *managed_policy; | ||
| 935 | |||
| 925 | if (j == cpu) | 936 | if (j == cpu) |
| 926 | continue; | 937 | continue; |
| 927 | if (!cpu_online(j)) | 938 | if (!cpu_online(j)) |
| 928 | continue; | 939 | continue; |
| 929 | 940 | ||
| 930 | dprintk("CPU %u already managed, adding link\n", j); | 941 | dprintk("CPU %u already managed, adding link\n", j); |
| 931 | cpufreq_cpu_get(cpu); | 942 | managed_policy = cpufreq_cpu_get(cpu); |
| 932 | cpu_sys_dev = get_cpu_sysdev(j); | 943 | cpu_sys_dev = get_cpu_sysdev(j); |
| 933 | ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, | 944 | ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, |
| 934 | "cpufreq"); | 945 | "cpufreq"); |
| 935 | if (ret) | 946 | if (ret) { |
| 947 | cpufreq_cpu_put(managed_policy); | ||
| 936 | goto err_out_unregister; | 948 | goto err_out_unregister; |
| 949 | } | ||
| 937 | } | 950 | } |
| 938 | 951 | ||
| 939 | policy->governor = NULL; /* to assure that the starting sequence is | 952 | policy->governor = NULL; /* to assure that the starting sequence is |
| @@ -965,17 +978,20 @@ err_out_unregister: | |||
| 965 | per_cpu(cpufreq_cpu_data, j) = NULL; | 978 | per_cpu(cpufreq_cpu_data, j) = NULL; |
| 966 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 979 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 967 | 980 | ||
| 981 | err_out_kobj_put: | ||
| 968 | kobject_put(&policy->kobj); | 982 | kobject_put(&policy->kobj); |
| 969 | wait_for_completion(&policy->kobj_unregister); | 983 | wait_for_completion(&policy->kobj_unregister); |
| 970 | 984 | ||
| 971 | err_out_driver_exit: | 985 | out_driver_exit: |
| 972 | if (cpufreq_driver->exit) | 986 | if (cpufreq_driver->exit) |
| 973 | cpufreq_driver->exit(policy); | 987 | cpufreq_driver->exit(policy); |
| 974 | 988 | ||
| 975 | err_out: | 989 | err_unlock_policy: |
| 976 | unlock_policy_rwsem_write(cpu); | 990 | unlock_policy_rwsem_write(cpu); |
| 991 | err_free_cpumask: | ||
| 992 | free_cpumask_var(policy->cpus); | ||
| 993 | err_free_policy: | ||
| 977 | kfree(policy); | 994 | kfree(policy); |
| 978 | |||
| 979 | nomem_out: | 995 | nomem_out: |
| 980 | module_put(cpufreq_driver->owner); | 996 | module_put(cpufreq_driver->owner); |
| 981 | module_out: | 997 | module_out: |
| @@ -1070,8 +1086,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
| 1070 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1086 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1071 | #endif | 1087 | #endif |
| 1072 | 1088 | ||
| 1073 | unlock_policy_rwsem_write(cpu); | ||
| 1074 | |||
| 1075 | if (cpufreq_driver->target) | 1089 | if (cpufreq_driver->target) |
| 1076 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 1090 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
| 1077 | 1091 | ||
| @@ -1088,6 +1102,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) | |||
| 1088 | if (cpufreq_driver->exit) | 1102 | if (cpufreq_driver->exit) |
| 1089 | cpufreq_driver->exit(data); | 1103 | cpufreq_driver->exit(data); |
| 1090 | 1104 | ||
| 1105 | unlock_policy_rwsem_write(cpu); | ||
| 1106 | |||
| 1091 | free_cpumask_var(data->related_cpus); | 1107 | free_cpumask_var(data->related_cpus); |
| 1092 | free_cpumask_var(data->cpus); | 1108 | free_cpumask_var(data->cpus); |
| 1093 | kfree(data); | 1109 | kfree(data); |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 7fc58af748b4..57490502b21c 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
| @@ -63,22 +63,20 @@ struct cpu_dbs_info_s { | |||
| 63 | unsigned int down_skip; | 63 | unsigned int down_skip; |
| 64 | unsigned int requested_freq; | 64 | unsigned int requested_freq; |
| 65 | int cpu; | 65 | int cpu; |
| 66 | unsigned int enable:1; | 66 | /* |
| 67 | * percpu mutex that serializes governor limit change with | ||
| 68 | * do_dbs_timer invocation. We do not want do_dbs_timer to run | ||
| 69 | * when user is changing the governor or limits. | ||
| 70 | */ | ||
| 71 | struct mutex timer_mutex; | ||
| 67 | }; | 72 | }; |
| 68 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 73 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
| 69 | 74 | ||
| 70 | static unsigned int dbs_enable; /* number of CPUs using this policy */ | 75 | static unsigned int dbs_enable; /* number of CPUs using this policy */ |
| 71 | 76 | ||
| 72 | /* | 77 | /* |
| 73 | * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug | 78 | * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on |
| 74 | * lock and dbs_mutex. cpu_hotplug lock should always be held before | 79 | * different CPUs. It protects dbs_enable in governor start/stop. |
| 75 | * dbs_mutex. If any function that can potentially take cpu_hotplug lock | ||
| 76 | * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then | ||
| 77 | * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock | ||
| 78 | * is recursive for the same process. -Venki | ||
| 79 | * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it | ||
| 80 | * would deadlock with cancel_delayed_work_sync(), which is needed for proper | ||
| 81 | * raceless workqueue teardown. | ||
| 82 | */ | 80 | */ |
| 83 | static DEFINE_MUTEX(dbs_mutex); | 81 | static DEFINE_MUTEX(dbs_mutex); |
| 84 | 82 | ||
| @@ -143,9 +141,6 @@ dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
| 143 | 141 | ||
| 144 | struct cpufreq_policy *policy; | 142 | struct cpufreq_policy *policy; |
| 145 | 143 | ||
| 146 | if (!this_dbs_info->enable) | ||
| 147 | return 0; | ||
| 148 | |||
| 149 | policy = this_dbs_info->cur_policy; | 144 | policy = this_dbs_info->cur_policy; |
| 150 | 145 | ||
| 151 | /* | 146 | /* |
| @@ -488,18 +483,12 @@ static void do_dbs_timer(struct work_struct *work) | |||
| 488 | 483 | ||
| 489 | delay -= jiffies % delay; | 484 | delay -= jiffies % delay; |
| 490 | 485 | ||
| 491 | if (lock_policy_rwsem_write(cpu) < 0) | 486 | mutex_lock(&dbs_info->timer_mutex); |
| 492 | return; | ||
| 493 | |||
| 494 | if (!dbs_info->enable) { | ||
| 495 | unlock_policy_rwsem_write(cpu); | ||
| 496 | return; | ||
| 497 | } | ||
| 498 | 487 | ||
| 499 | dbs_check_cpu(dbs_info); | 488 | dbs_check_cpu(dbs_info); |
| 500 | 489 | ||
| 501 | queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); | 490 | queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); |
| 502 | unlock_policy_rwsem_write(cpu); | 491 | mutex_unlock(&dbs_info->timer_mutex); |
| 503 | } | 492 | } |
| 504 | 493 | ||
| 505 | static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | 494 | static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) |
| @@ -508,7 +497,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | |||
| 508 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | 497 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); |
| 509 | delay -= jiffies % delay; | 498 | delay -= jiffies % delay; |
| 510 | 499 | ||
| 511 | dbs_info->enable = 1; | ||
| 512 | INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); | 500 | INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); |
| 513 | queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work, | 501 | queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work, |
| 514 | delay); | 502 | delay); |
| @@ -516,7 +504,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | |||
| 516 | 504 | ||
| 517 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | 505 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) |
| 518 | { | 506 | { |
| 519 | dbs_info->enable = 0; | ||
| 520 | cancel_delayed_work_sync(&dbs_info->work); | 507 | cancel_delayed_work_sync(&dbs_info->work); |
| 521 | } | 508 | } |
| 522 | 509 | ||
| @@ -535,9 +522,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 535 | if ((!cpu_online(cpu)) || (!policy->cur)) | 522 | if ((!cpu_online(cpu)) || (!policy->cur)) |
| 536 | return -EINVAL; | 523 | return -EINVAL; |
| 537 | 524 | ||
| 538 | if (this_dbs_info->enable) /* Already enabled */ | ||
| 539 | break; | ||
| 540 | |||
| 541 | mutex_lock(&dbs_mutex); | 525 | mutex_lock(&dbs_mutex); |
| 542 | 526 | ||
| 543 | rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); | 527 | rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); |
| @@ -561,6 +545,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 561 | this_dbs_info->down_skip = 0; | 545 | this_dbs_info->down_skip = 0; |
| 562 | this_dbs_info->requested_freq = policy->cur; | 546 | this_dbs_info->requested_freq = policy->cur; |
| 563 | 547 | ||
| 548 | mutex_init(&this_dbs_info->timer_mutex); | ||
| 564 | dbs_enable++; | 549 | dbs_enable++; |
| 565 | /* | 550 | /* |
| 566 | * Start the timerschedule work, when this governor | 551 | * Start the timerschedule work, when this governor |
| @@ -590,17 +575,19 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 590 | &dbs_cpufreq_notifier_block, | 575 | &dbs_cpufreq_notifier_block, |
| 591 | CPUFREQ_TRANSITION_NOTIFIER); | 576 | CPUFREQ_TRANSITION_NOTIFIER); |
| 592 | } | 577 | } |
| 593 | dbs_timer_init(this_dbs_info); | ||
| 594 | |||
| 595 | mutex_unlock(&dbs_mutex); | 578 | mutex_unlock(&dbs_mutex); |
| 596 | 579 | ||
| 580 | dbs_timer_init(this_dbs_info); | ||
| 581 | |||
| 597 | break; | 582 | break; |
| 598 | 583 | ||
| 599 | case CPUFREQ_GOV_STOP: | 584 | case CPUFREQ_GOV_STOP: |
| 600 | mutex_lock(&dbs_mutex); | ||
| 601 | dbs_timer_exit(this_dbs_info); | 585 | dbs_timer_exit(this_dbs_info); |
| 586 | |||
| 587 | mutex_lock(&dbs_mutex); | ||
| 602 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); | 588 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); |
| 603 | dbs_enable--; | 589 | dbs_enable--; |
| 590 | mutex_destroy(&this_dbs_info->timer_mutex); | ||
| 604 | 591 | ||
| 605 | /* | 592 | /* |
| 606 | * Stop the timerschedule work, when this governor | 593 | * Stop the timerschedule work, when this governor |
| @@ -616,7 +603,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 616 | break; | 603 | break; |
| 617 | 604 | ||
| 618 | case CPUFREQ_GOV_LIMITS: | 605 | case CPUFREQ_GOV_LIMITS: |
| 619 | mutex_lock(&dbs_mutex); | 606 | mutex_lock(&this_dbs_info->timer_mutex); |
| 620 | if (policy->max < this_dbs_info->cur_policy->cur) | 607 | if (policy->max < this_dbs_info->cur_policy->cur) |
| 621 | __cpufreq_driver_target( | 608 | __cpufreq_driver_target( |
| 622 | this_dbs_info->cur_policy, | 609 | this_dbs_info->cur_policy, |
| @@ -625,7 +612,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 625 | __cpufreq_driver_target( | 612 | __cpufreq_driver_target( |
| 626 | this_dbs_info->cur_policy, | 613 | this_dbs_info->cur_policy, |
| 627 | policy->min, CPUFREQ_RELATION_L); | 614 | policy->min, CPUFREQ_RELATION_L); |
| 628 | mutex_unlock(&dbs_mutex); | 615 | mutex_unlock(&this_dbs_info->timer_mutex); |
| 629 | 616 | ||
| 630 | break; | 617 | break; |
| 631 | } | 618 | } |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 1911d1729353..d6ba14276bb1 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -70,23 +70,21 @@ struct cpu_dbs_info_s { | |||
| 70 | unsigned int freq_lo_jiffies; | 70 | unsigned int freq_lo_jiffies; |
| 71 | unsigned int freq_hi_jiffies; | 71 | unsigned int freq_hi_jiffies; |
| 72 | int cpu; | 72 | int cpu; |
| 73 | unsigned int enable:1, | 73 | unsigned int sample_type:1; |
| 74 | sample_type:1; | 74 | /* |
| 75 | * percpu mutex that serializes governor limit change with | ||
| 76 | * do_dbs_timer invocation. We do not want do_dbs_timer to run | ||
| 77 | * when user is changing the governor or limits. | ||
| 78 | */ | ||
| 79 | struct mutex timer_mutex; | ||
| 75 | }; | 80 | }; |
| 76 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 81 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
| 77 | 82 | ||
| 78 | static unsigned int dbs_enable; /* number of CPUs using this policy */ | 83 | static unsigned int dbs_enable; /* number of CPUs using this policy */ |
| 79 | 84 | ||
| 80 | /* | 85 | /* |
| 81 | * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug | 86 | * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on |
| 82 | * lock and dbs_mutex. cpu_hotplug lock should always be held before | 87 | * different CPUs. It protects dbs_enable in governor start/stop. |
| 83 | * dbs_mutex. If any function that can potentially take cpu_hotplug lock | ||
| 84 | * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then | ||
| 85 | * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock | ||
| 86 | * is recursive for the same process. -Venki | ||
| 87 | * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it | ||
| 88 | * would deadlock with cancel_delayed_work_sync(), which is needed for proper | ||
| 89 | * raceless workqueue teardown. | ||
| 90 | */ | 88 | */ |
| 91 | static DEFINE_MUTEX(dbs_mutex); | 89 | static DEFINE_MUTEX(dbs_mutex); |
| 92 | 90 | ||
| @@ -192,13 +190,18 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy, | |||
| 192 | return freq_hi; | 190 | return freq_hi; |
| 193 | } | 191 | } |
| 194 | 192 | ||
| 193 | static void ondemand_powersave_bias_init_cpu(int cpu) | ||
| 194 | { | ||
| 195 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); | ||
| 196 | dbs_info->freq_table = cpufreq_frequency_get_table(cpu); | ||
| 197 | dbs_info->freq_lo = 0; | ||
| 198 | } | ||
| 199 | |||
| 195 | static void ondemand_powersave_bias_init(void) | 200 | static void ondemand_powersave_bias_init(void) |
| 196 | { | 201 | { |
| 197 | int i; | 202 | int i; |
| 198 | for_each_online_cpu(i) { | 203 | for_each_online_cpu(i) { |
| 199 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i); | 204 | ondemand_powersave_bias_init_cpu(i); |
| 200 | dbs_info->freq_table = cpufreq_frequency_get_table(i); | ||
| 201 | dbs_info->freq_lo = 0; | ||
| 202 | } | 205 | } |
| 203 | } | 206 | } |
| 204 | 207 | ||
| @@ -240,12 +243,10 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, | |||
| 240 | unsigned int input; | 243 | unsigned int input; |
| 241 | int ret; | 244 | int ret; |
| 242 | ret = sscanf(buf, "%u", &input); | 245 | ret = sscanf(buf, "%u", &input); |
| 246 | if (ret != 1) | ||
| 247 | return -EINVAL; | ||
| 243 | 248 | ||
| 244 | mutex_lock(&dbs_mutex); | 249 | mutex_lock(&dbs_mutex); |
| 245 | if (ret != 1) { | ||
| 246 | mutex_unlock(&dbs_mutex); | ||
| 247 | return -EINVAL; | ||
| 248 | } | ||
| 249 | dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); | 250 | dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); |
| 250 | mutex_unlock(&dbs_mutex); | 251 | mutex_unlock(&dbs_mutex); |
| 251 | 252 | ||
| @@ -259,13 +260,12 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, | |||
| 259 | int ret; | 260 | int ret; |
| 260 | ret = sscanf(buf, "%u", &input); | 261 | ret = sscanf(buf, "%u", &input); |
| 261 | 262 | ||
| 262 | mutex_lock(&dbs_mutex); | ||
| 263 | if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || | 263 | if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || |
| 264 | input < MIN_FREQUENCY_UP_THRESHOLD) { | 264 | input < MIN_FREQUENCY_UP_THRESHOLD) { |
| 265 | mutex_unlock(&dbs_mutex); | ||
| 266 | return -EINVAL; | 265 | return -EINVAL; |
| 267 | } | 266 | } |
| 268 | 267 | ||
| 268 | mutex_lock(&dbs_mutex); | ||
| 269 | dbs_tuners_ins.up_threshold = input; | 269 | dbs_tuners_ins.up_threshold = input; |
| 270 | mutex_unlock(&dbs_mutex); | 270 | mutex_unlock(&dbs_mutex); |
| 271 | 271 | ||
| @@ -363,9 +363,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 363 | struct cpufreq_policy *policy; | 363 | struct cpufreq_policy *policy; |
| 364 | unsigned int j; | 364 | unsigned int j; |
| 365 | 365 | ||
| 366 | if (!this_dbs_info->enable) | ||
| 367 | return; | ||
| 368 | |||
| 369 | this_dbs_info->freq_lo = 0; | 366 | this_dbs_info->freq_lo = 0; |
| 370 | policy = this_dbs_info->cur_policy; | 367 | policy = this_dbs_info->cur_policy; |
| 371 | 368 | ||
| @@ -493,14 +490,7 @@ static void do_dbs_timer(struct work_struct *work) | |||
| 493 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | 490 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); |
| 494 | 491 | ||
| 495 | delay -= jiffies % delay; | 492 | delay -= jiffies % delay; |
| 496 | 493 | mutex_lock(&dbs_info->timer_mutex); | |
| 497 | if (lock_policy_rwsem_write(cpu) < 0) | ||
| 498 | return; | ||
| 499 | |||
| 500 | if (!dbs_info->enable) { | ||
| 501 | unlock_policy_rwsem_write(cpu); | ||
| 502 | return; | ||
| 503 | } | ||
| 504 | 494 | ||
| 505 | /* Common NORMAL_SAMPLE setup */ | 495 | /* Common NORMAL_SAMPLE setup */ |
| 506 | dbs_info->sample_type = DBS_NORMAL_SAMPLE; | 496 | dbs_info->sample_type = DBS_NORMAL_SAMPLE; |
| @@ -517,7 +507,7 @@ static void do_dbs_timer(struct work_struct *work) | |||
| 517 | dbs_info->freq_lo, CPUFREQ_RELATION_H); | 507 | dbs_info->freq_lo, CPUFREQ_RELATION_H); |
| 518 | } | 508 | } |
| 519 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); | 509 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); |
| 520 | unlock_policy_rwsem_write(cpu); | 510 | mutex_unlock(&dbs_info->timer_mutex); |
| 521 | } | 511 | } |
| 522 | 512 | ||
| 523 | static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | 513 | static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) |
| @@ -526,8 +516,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | |||
| 526 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | 516 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); |
| 527 | delay -= jiffies % delay; | 517 | delay -= jiffies % delay; |
| 528 | 518 | ||
| 529 | dbs_info->enable = 1; | ||
| 530 | ondemand_powersave_bias_init(); | ||
| 531 | dbs_info->sample_type = DBS_NORMAL_SAMPLE; | 519 | dbs_info->sample_type = DBS_NORMAL_SAMPLE; |
| 532 | INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); | 520 | INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); |
| 533 | queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work, | 521 | queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work, |
| @@ -536,7 +524,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | |||
| 536 | 524 | ||
| 537 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | 525 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) |
| 538 | { | 526 | { |
| 539 | dbs_info->enable = 0; | ||
| 540 | cancel_delayed_work_sync(&dbs_info->work); | 527 | cancel_delayed_work_sync(&dbs_info->work); |
| 541 | } | 528 | } |
| 542 | 529 | ||
| @@ -555,19 +542,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 555 | if ((!cpu_online(cpu)) || (!policy->cur)) | 542 | if ((!cpu_online(cpu)) || (!policy->cur)) |
| 556 | return -EINVAL; | 543 | return -EINVAL; |
| 557 | 544 | ||
| 558 | if (this_dbs_info->enable) /* Already enabled */ | ||
| 559 | break; | ||
| 560 | |||
| 561 | mutex_lock(&dbs_mutex); | 545 | mutex_lock(&dbs_mutex); |
| 562 | dbs_enable++; | ||
| 563 | 546 | ||
| 564 | rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); | 547 | rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); |
| 565 | if (rc) { | 548 | if (rc) { |
| 566 | dbs_enable--; | ||
| 567 | mutex_unlock(&dbs_mutex); | 549 | mutex_unlock(&dbs_mutex); |
| 568 | return rc; | 550 | return rc; |
| 569 | } | 551 | } |
| 570 | 552 | ||
| 553 | dbs_enable++; | ||
| 571 | for_each_cpu(j, policy->cpus) { | 554 | for_each_cpu(j, policy->cpus) { |
| 572 | struct cpu_dbs_info_s *j_dbs_info; | 555 | struct cpu_dbs_info_s *j_dbs_info; |
| 573 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 556 | j_dbs_info = &per_cpu(cpu_dbs_info, j); |
| @@ -581,6 +564,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 581 | } | 564 | } |
| 582 | } | 565 | } |
| 583 | this_dbs_info->cpu = cpu; | 566 | this_dbs_info->cpu = cpu; |
| 567 | ondemand_powersave_bias_init_cpu(cpu); | ||
| 568 | mutex_init(&this_dbs_info->timer_mutex); | ||
| 584 | /* | 569 | /* |
| 585 | * Start the timerschedule work, when this governor | 570 | * Start the timerschedule work, when this governor |
| 586 | * is used for first time | 571 | * is used for first time |
| @@ -598,29 +583,31 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 598 | max(min_sampling_rate, | 583 | max(min_sampling_rate, |
| 599 | latency * LATENCY_MULTIPLIER); | 584 | latency * LATENCY_MULTIPLIER); |
| 600 | } | 585 | } |
| 601 | dbs_timer_init(this_dbs_info); | ||
| 602 | |||
| 603 | mutex_unlock(&dbs_mutex); | 586 | mutex_unlock(&dbs_mutex); |
| 587 | |||
| 588 | dbs_timer_init(this_dbs_info); | ||
| 604 | break; | 589 | break; |
| 605 | 590 | ||
| 606 | case CPUFREQ_GOV_STOP: | 591 | case CPUFREQ_GOV_STOP: |
| 607 | mutex_lock(&dbs_mutex); | ||
| 608 | dbs_timer_exit(this_dbs_info); | 592 | dbs_timer_exit(this_dbs_info); |
| 593 | |||
| 594 | mutex_lock(&dbs_mutex); | ||
| 609 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); | 595 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); |
| 596 | mutex_destroy(&this_dbs_info->timer_mutex); | ||
| 610 | dbs_enable--; | 597 | dbs_enable--; |
| 611 | mutex_unlock(&dbs_mutex); | 598 | mutex_unlock(&dbs_mutex); |
| 612 | 599 | ||
| 613 | break; | 600 | break; |
| 614 | 601 | ||
| 615 | case CPUFREQ_GOV_LIMITS: | 602 | case CPUFREQ_GOV_LIMITS: |
| 616 | mutex_lock(&dbs_mutex); | 603 | mutex_lock(&this_dbs_info->timer_mutex); |
| 617 | if (policy->max < this_dbs_info->cur_policy->cur) | 604 | if (policy->max < this_dbs_info->cur_policy->cur) |
| 618 | __cpufreq_driver_target(this_dbs_info->cur_policy, | 605 | __cpufreq_driver_target(this_dbs_info->cur_policy, |
| 619 | policy->max, CPUFREQ_RELATION_H); | 606 | policy->max, CPUFREQ_RELATION_H); |
| 620 | else if (policy->min > this_dbs_info->cur_policy->cur) | 607 | else if (policy->min > this_dbs_info->cur_policy->cur) |
| 621 | __cpufreq_driver_target(this_dbs_info->cur_policy, | 608 | __cpufreq_driver_target(this_dbs_info->cur_policy, |
| 622 | policy->min, CPUFREQ_RELATION_L); | 609 | policy->min, CPUFREQ_RELATION_L); |
| 623 | mutex_unlock(&dbs_mutex); | 610 | mutex_unlock(&this_dbs_info->timer_mutex); |
| 624 | break; | 611 | break; |
| 625 | } | 612 | } |
| 626 | return 0; | 613 | return 0; |
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index 9aa9ea9822c8..88dab52926f4 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c | |||
| @@ -432,23 +432,27 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc, | |||
| 432 | list_splice_init(&txd->tx_list, &dc->free_list); | 432 | list_splice_init(&txd->tx_list, &dc->free_list); |
| 433 | list_move(&desc->desc_node, &dc->free_list); | 433 | list_move(&desc->desc_node, &dc->free_list); |
| 434 | 434 | ||
| 435 | /* | ||
| 436 | * We use dma_unmap_page() regardless of how the buffers were | ||
| 437 | * mapped before they were submitted... | ||
| 438 | */ | ||
| 439 | if (!ds) { | 435 | if (!ds) { |
| 440 | dma_addr_t dmaaddr; | 436 | dma_addr_t dmaaddr; |
| 441 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | 437 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { |
| 442 | dmaaddr = is_dmac64(dc) ? | 438 | dmaaddr = is_dmac64(dc) ? |
| 443 | desc->hwdesc.DAR : desc->hwdesc32.DAR; | 439 | desc->hwdesc.DAR : desc->hwdesc32.DAR; |
| 444 | dma_unmap_page(chan2parent(&dc->chan), dmaaddr, | 440 | if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE) |
| 445 | desc->len, DMA_FROM_DEVICE); | 441 | dma_unmap_single(chan2parent(&dc->chan), |
| 442 | dmaaddr, desc->len, DMA_FROM_DEVICE); | ||
| 443 | else | ||
| 444 | dma_unmap_page(chan2parent(&dc->chan), | ||
| 445 | dmaaddr, desc->len, DMA_FROM_DEVICE); | ||
| 446 | } | 446 | } |
| 447 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | 447 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) { |
| 448 | dmaaddr = is_dmac64(dc) ? | 448 | dmaaddr = is_dmac64(dc) ? |
| 449 | desc->hwdesc.SAR : desc->hwdesc32.SAR; | 449 | desc->hwdesc.SAR : desc->hwdesc32.SAR; |
| 450 | dma_unmap_page(chan2parent(&dc->chan), dmaaddr, | 450 | if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE) |
| 451 | desc->len, DMA_TO_DEVICE); | 451 | dma_unmap_single(chan2parent(&dc->chan), |
| 452 | dmaaddr, desc->len, DMA_TO_DEVICE); | ||
| 453 | else | ||
| 454 | dma_unmap_page(chan2parent(&dc->chan), | ||
| 455 | dmaaddr, desc->len, DMA_TO_DEVICE); | ||
| 452 | } | 456 | } |
| 453 | } | 457 | } |
| 454 | 458 | ||
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c36bf40568cf..858fe6037223 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
| @@ -754,13 +754,13 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt) | |||
| 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) | 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) |
| 755 | { | 755 | { |
| 756 | int bit; | 756 | int bit; |
| 757 | enum dev_type edac_cap = EDAC_NONE; | 757 | enum dev_type edac_cap = EDAC_FLAG_NONE; |
| 758 | 758 | ||
| 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) | 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) |
| 760 | ? 19 | 760 | ? 19 |
| 761 | : 17; | 761 | : 17; |
| 762 | 762 | ||
| 763 | if (pvt->dclr0 >> BIT(bit)) | 763 | if (pvt->dclr0 & BIT(bit)) |
| 764 | edac_cap = EDAC_FLAG_SECDED; | 764 | edac_cap = EDAC_FLAG_SECDED; |
| 765 | 765 | ||
| 766 | return edac_cap; | 766 | return edac_cap; |
| @@ -1269,7 +1269,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
| 1269 | if (channels == 0) | 1269 | if (channels == 0) |
| 1270 | channels = 1; | 1270 | channels = 1; |
| 1271 | 1271 | ||
| 1272 | debugf0("DIMM count= %d\n", channels); | 1272 | debugf0("MCT channel count: %d\n", channels); |
| 1273 | 1273 | ||
| 1274 | return channels; | 1274 | return channels; |
| 1275 | 1275 | ||
| @@ -2966,7 +2966,12 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | |||
| 2966 | " Use of the override can cause " | 2966 | " Use of the override can cause " |
| 2967 | "unknown side effects.\n"); | 2967 | "unknown side effects.\n"); |
| 2968 | ret = -ENODEV; | 2968 | ret = -ENODEV; |
| 2969 | } | 2969 | } else |
| 2970 | /* | ||
| 2971 | * enable further driver loading if ECC enable is | ||
| 2972 | * overridden. | ||
| 2973 | */ | ||
| 2974 | ret = 0; | ||
| 2970 | } else { | 2975 | } else { |
| 2971 | amd64_printk(KERN_INFO, | 2976 | amd64_printk(KERN_INFO, |
| 2972 | "ECC is enabled by BIOS, Proceeding " | 2977 | "ECC is enabled by BIOS, Proceeding " |
| @@ -3006,7 +3011,6 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
| 3006 | 3011 | ||
| 3007 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; | 3012 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; |
| 3008 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 3013 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
| 3009 | mci->edac_cap = EDAC_FLAG_NONE; | ||
| 3010 | 3014 | ||
| 3011 | if (pvt->nbcap & K8_NBCAP_SECDED) | 3015 | if (pvt->nbcap & K8_NBCAP_SECDED) |
| 3012 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; | 3016 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; |
| @@ -3052,7 +3056,7 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | |||
| 3052 | if (!pvt) | 3056 | if (!pvt) |
| 3053 | goto err_exit; | 3057 | goto err_exit; |
| 3054 | 3058 | ||
| 3055 | pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl); | 3059 | pvt->mc_node_id = get_node_id(dram_f2_ctl); |
| 3056 | 3060 | ||
| 3057 | pvt->dram_f2_ctl = dram_f2_ctl; | 3061 | pvt->dram_f2_ctl = dram_f2_ctl; |
| 3058 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | 3062 | pvt->ext_model = boot_cpu_data.x86_model >> 4; |
| @@ -3179,8 +3183,7 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | |||
| 3179 | { | 3183 | { |
| 3180 | int ret = 0; | 3184 | int ret = 0; |
| 3181 | 3185 | ||
| 3182 | debugf0("(MC node=%d,mc_type='%s')\n", | 3186 | debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), |
| 3183 | get_mc_node_id_from_pdev(pdev), | ||
| 3184 | get_amd_family_name(mc_type->driver_data)); | 3187 | get_amd_family_name(mc_type->driver_data)); |
| 3185 | 3188 | ||
| 3186 | ret = pci_enable_device(pdev); | 3189 | ret = pci_enable_device(pdev); |
| @@ -3319,15 +3322,17 @@ static int __init amd64_edac_init(void) | |||
| 3319 | 3322 | ||
| 3320 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | 3323 | err = amd64_init_2nd_stage(pvt_lookup[nb]); |
| 3321 | if (err) | 3324 | if (err) |
| 3322 | goto err_exit; | 3325 | goto err_2nd_stage; |
| 3323 | } | 3326 | } |
| 3324 | 3327 | ||
| 3325 | amd64_setup_pci_device(); | 3328 | amd64_setup_pci_device(); |
| 3326 | 3329 | ||
| 3327 | return 0; | 3330 | return 0; |
| 3328 | 3331 | ||
| 3332 | err_2nd_stage: | ||
| 3333 | debugf0("2nd stage failed\n"); | ||
| 3334 | |||
| 3329 | err_exit: | 3335 | err_exit: |
| 3330 | debugf0("'finish_setup' stage failed\n"); | ||
| 3331 | pci_unregister_driver(&amd64_pci_driver); | 3336 | pci_unregister_driver(&amd64_pci_driver); |
| 3332 | 3337 | ||
| 3333 | return err; | 3338 | return err; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index a159957e167b..ba73015af8e4 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
| @@ -444,7 +444,7 @@ enum { | |||
| 444 | #define K8_MSR_MC4ADDR 0x0412 | 444 | #define K8_MSR_MC4ADDR 0x0412 |
| 445 | 445 | ||
| 446 | /* AMD sets the first MC device at device ID 0x18. */ | 446 | /* AMD sets the first MC device at device ID 0x18. */ |
| 447 | static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev) | 447 | static inline int get_node_id(struct pci_dev *pdev) |
| 448 | { | 448 | { |
| 449 | return PCI_SLOT(pdev->devfn) - 0x18; | 449 | return PCI_SLOT(pdev->devfn) - 0x18; |
| 450 | } | 450 | } |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 3493c6bdb820..871c13b4c148 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
| @@ -150,6 +150,8 @@ enum mem_type { | |||
| 150 | MEM_FB_DDR2, /* fully buffered DDR2 */ | 150 | MEM_FB_DDR2, /* fully buffered DDR2 */ |
| 151 | MEM_RDDR2, /* Registered DDR2 RAM */ | 151 | MEM_RDDR2, /* Registered DDR2 RAM */ |
| 152 | MEM_XDR, /* Rambus XDR */ | 152 | MEM_XDR, /* Rambus XDR */ |
| 153 | MEM_DDR3, /* DDR3 RAM */ | ||
| 154 | MEM_RDDR3, /* Registered DDR3 RAM */ | ||
| 153 | }; | 155 | }; |
| 154 | 156 | ||
| 155 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) | 157 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) |
| @@ -167,6 +169,8 @@ enum mem_type { | |||
| 167 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) | 169 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) |
| 168 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) | 170 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) |
| 169 | #define MEM_FLAG_XDR BIT(MEM_XDR) | 171 | #define MEM_FLAG_XDR BIT(MEM_XDR) |
| 172 | #define MEM_FLAG_DDR3 BIT(MEM_DDR3) | ||
| 173 | #define MEM_FLAG_RDDR3 BIT(MEM_RDDR3) | ||
| 170 | 174 | ||
| 171 | /* chipset Error Detection and Correction capabilities and mode */ | 175 | /* chipset Error Detection and Correction capabilities and mode */ |
| 172 | enum edac_type { | 176 | enum edac_type { |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index ad218fe4942d..e1d4ce083481 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -94,7 +94,9 @@ static const char *mem_types[] = { | |||
| 94 | [MEM_DDR2] = "Unbuffered-DDR2", | 94 | [MEM_DDR2] = "Unbuffered-DDR2", |
| 95 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", | 95 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", |
| 96 | [MEM_RDDR2] = "Registered-DDR2", | 96 | [MEM_RDDR2] = "Registered-DDR2", |
| 97 | [MEM_XDR] = "XDR" | 97 | [MEM_XDR] = "XDR", |
| 98 | [MEM_DDR3] = "Unbuffered-DDR3", | ||
| 99 | [MEM_RDDR3] = "Registered-DDR3" | ||
| 98 | }; | 100 | }; |
| 99 | 101 | ||
| 100 | static const char *dev_types[] = { | 102 | static const char *dev_types[] = { |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 7c8c2d72916f..3f2ccfc6407c 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
| @@ -757,6 +757,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
| 757 | case DSC_SDTYPE_DDR2: | 757 | case DSC_SDTYPE_DDR2: |
| 758 | mtype = MEM_RDDR2; | 758 | mtype = MEM_RDDR2; |
| 759 | break; | 759 | break; |
| 760 | case DSC_SDTYPE_DDR3: | ||
| 761 | mtype = MEM_RDDR3; | ||
| 762 | break; | ||
| 760 | default: | 763 | default: |
| 761 | mtype = MEM_UNKNOWN; | 764 | mtype = MEM_UNKNOWN; |
| 762 | break; | 765 | break; |
| @@ -769,6 +772,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
| 769 | case DSC_SDTYPE_DDR2: | 772 | case DSC_SDTYPE_DDR2: |
| 770 | mtype = MEM_DDR2; | 773 | mtype = MEM_DDR2; |
| 771 | break; | 774 | break; |
| 775 | case DSC_SDTYPE_DDR3: | ||
| 776 | mtype = MEM_DDR3; | ||
| 777 | break; | ||
| 772 | default: | 778 | default: |
| 773 | mtype = MEM_UNKNOWN; | 779 | mtype = MEM_UNKNOWN; |
| 774 | break; | 780 | break; |
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 135b3539a030..52432ee7c4b9 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | 53 | ||
| 54 | #define DSC_SDTYPE_DDR 0x02000000 | 54 | #define DSC_SDTYPE_DDR 0x02000000 |
| 55 | #define DSC_SDTYPE_DDR2 0x03000000 | 55 | #define DSC_SDTYPE_DDR2 0x03000000 |
| 56 | #define DSC_SDTYPE_DDR3 0x07000000 | ||
| 56 | #define DSC_X32_EN 0x00000020 | 57 | #define DSC_X32_EN 0x00000020 |
| 57 | 58 | ||
| 58 | /* Err_Int_En */ | 59 | /* Err_Int_En */ |
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81bb..f74edae5cb4c 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
| @@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) | |||
| 196 | { | 196 | { |
| 197 | int channel, bandwidth = 0; | 197 | int channel, bandwidth = 0; |
| 198 | 198 | ||
| 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, | 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, |
| 200 | &channel, &bandwidth, true); | 200 | &bandwidth, true, card->bm_transaction_data); |
| 201 | if (channel == 31) { | 201 | if (channel == 31) { |
| 202 | card->broadcast_channel_allocated = true; | 202 | card->broadcast_channel_allocated = true; |
| 203 | device_for_each_child(card->device, (void *)(long)generation, | 203 | device_for_each_child(card->device, (void *)(long)generation, |
| @@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
| 230 | bool do_reset = false; | 230 | bool do_reset = false; |
| 231 | bool root_device_is_running; | 231 | bool root_device_is_running; |
| 232 | bool root_device_is_cmc; | 232 | bool root_device_is_cmc; |
| 233 | __be32 lock_data[2]; | ||
| 234 | 233 | ||
| 235 | spin_lock_irqsave(&card->lock, flags); | 234 | spin_lock_irqsave(&card->lock, flags); |
| 236 | 235 | ||
| @@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) | |||
| 273 | goto pick_me; | 272 | goto pick_me; |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | lock_data[0] = cpu_to_be32(0x3f); | 275 | card->bm_transaction_data[0] = cpu_to_be32(0x3f); |
| 277 | lock_data[1] = cpu_to_be32(local_id); | 276 | card->bm_transaction_data[1] = cpu_to_be32(local_id); |
| 278 | 277 | ||
| 279 | spin_unlock_irqrestore(&card->lock, flags); | 278 | spin_unlock_irqrestore(&card->lock, flags); |
| 280 | 279 | ||
| 281 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | 280 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
| 282 | irm_id, generation, SCODE_100, | 281 | irm_id, generation, SCODE_100, |
| 283 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, | 282 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, |
| 284 | lock_data, sizeof(lock_data)); | 283 | card->bm_transaction_data, |
| 284 | sizeof(card->bm_transaction_data)); | ||
| 285 | 285 | ||
| 286 | if (rcode == RCODE_GENERATION) | 286 | if (rcode == RCODE_GENERATION) |
| 287 | /* Another bus reset, BM work has been rescheduled. */ | 287 | /* Another bus reset, BM work has been rescheduled. */ |
| 288 | goto out; | 288 | goto out; |
| 289 | 289 | ||
| 290 | if (rcode == RCODE_COMPLETE && | 290 | if (rcode == RCODE_COMPLETE && |
| 291 | lock_data[0] != cpu_to_be32(0x3f)) { | 291 | card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { |
| 292 | 292 | ||
| 293 | /* Somebody else is BM. Only act as IRM. */ | 293 | /* Somebody else is BM. Only act as IRM. */ |
| 294 | if (local_id == irm_id) | 294 | if (local_id == irm_id) |
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0f..ced186d7e9a9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
| @@ -125,6 +125,7 @@ struct iso_resource { | |||
| 125 | int generation; | 125 | int generation; |
| 126 | u64 channels; | 126 | u64 channels; |
| 127 | s32 bandwidth; | 127 | s32 bandwidth; |
| 128 | __be32 transaction_data[2]; | ||
| 128 | struct iso_resource_event *e_alloc, *e_dealloc; | 129 | struct iso_resource_event *e_alloc, *e_dealloc; |
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| @@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) | |||
| 1049 | r->channels, &channel, &bandwidth, | 1050 | r->channels, &channel, &bandwidth, |
| 1050 | todo == ISO_RES_ALLOC || | 1051 | todo == ISO_RES_ALLOC || |
| 1051 | todo == ISO_RES_REALLOC || | 1052 | todo == ISO_RES_REALLOC || |
| 1052 | todo == ISO_RES_ALLOC_ONCE); | 1053 | todo == ISO_RES_ALLOC_ONCE, |
| 1054 | r->transaction_data); | ||
| 1053 | /* | 1055 | /* |
| 1054 | * Is this generation outdated already? As long as this resource sticks | 1056 | * Is this generation outdated already? As long as this resource sticks |
| 1055 | * in the idr, it will be scheduled again for a newer generation or at | 1057 | * in the idr, it will be scheduled again for a newer generation or at |
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38d..110e731f5574 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
| @@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); | |||
| 177 | */ | 177 | */ |
| 178 | 178 | ||
| 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
| 180 | int bandwidth, bool allocate) | 180 | int bandwidth, bool allocate, __be32 data[2]) |
| 181 | { | 181 | { |
| 182 | __be32 data[2]; | ||
| 183 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | 182 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
| 184 | 183 | ||
| 185 | /* | 184 | /* |
| @@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | |||
| 215 | } | 214 | } |
| 216 | 215 | ||
| 217 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | 216 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
| 218 | u32 channels_mask, u64 offset, bool allocate) | 217 | u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) |
| 219 | { | 218 | { |
| 220 | __be32 data[2], c, all, old; | 219 | __be32 c, all, old; |
| 221 | int i, retry = 5; | 220 | int i, retry = 5; |
| 222 | 221 | ||
| 223 | old = all = allocate ? cpu_to_be32(~0) : 0; | 222 | old = all = allocate ? cpu_to_be32(~0) : 0; |
| @@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, | |||
| 260 | } | 259 | } |
| 261 | 260 | ||
| 262 | static void deallocate_channel(struct fw_card *card, int irm_id, | 261 | static void deallocate_channel(struct fw_card *card, int irm_id, |
| 263 | int generation, int channel) | 262 | int generation, int channel, __be32 buffer[2]) |
| 264 | { | 263 | { |
| 265 | u32 mask; | 264 | u32 mask; |
| 266 | u64 offset; | 265 | u64 offset; |
| @@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
| 269 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | 268 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
| 270 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | 269 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
| 271 | 270 | ||
| 272 | manage_channel(card, irm_id, generation, mask, offset, false); | 271 | manage_channel(card, irm_id, generation, mask, offset, false, buffer); |
| 273 | } | 272 | } |
| 274 | 273 | ||
| 275 | /** | 274 | /** |
| @@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
| 298 | */ | 297 | */ |
| 299 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 298 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
| 300 | u64 channels_mask, int *channel, int *bandwidth, | 299 | u64 channels_mask, int *channel, int *bandwidth, |
| 301 | bool allocate) | 300 | bool allocate, __be32 buffer[2]) |
| 302 | { | 301 | { |
| 303 | u32 channels_hi = channels_mask; /* channels 31...0 */ | 302 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
| 304 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | 303 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
| @@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
| 310 | 309 | ||
| 311 | if (channels_hi) | 310 | if (channels_hi) |
| 312 | c = manage_channel(card, irm_id, generation, channels_hi, | 311 | c = manage_channel(card, irm_id, generation, channels_hi, |
| 313 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); | 312 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
| 313 | allocate, buffer); | ||
| 314 | if (channels_lo && c < 0) { | 314 | if (channels_lo && c < 0) { |
| 315 | c = manage_channel(card, irm_id, generation, channels_lo, | 315 | c = manage_channel(card, irm_id, generation, channels_lo, |
| 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); | 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
| 317 | allocate, buffer); | ||
| 317 | if (c >= 0) | 318 | if (c >= 0) |
| 318 | c += 32; | 319 | c += 32; |
| 319 | } | 320 | } |
| @@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
| 325 | if (*bandwidth == 0) | 326 | if (*bandwidth == 0) |
| 326 | return; | 327 | return; |
| 327 | 328 | ||
| 328 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | 329 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, |
| 330 | allocate, buffer); | ||
| 329 | if (ret < 0) | 331 | if (ret < 0) |
| 330 | *bandwidth = 0; | 332 | *bandwidth = 0; |
| 331 | 333 | ||
| 332 | if (allocate && ret < 0 && c >= 0) { | 334 | if (allocate && ret < 0 && c >= 0) { |
| 333 | deallocate_channel(card, irm_id, generation, c); | 335 | deallocate_channel(card, irm_id, generation, c, buffer); |
| 334 | *channel = ret; | 336 | *channel = ret; |
| 335 | } | 337 | } |
| 336 | } | 338 | } |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e3..6052816be353 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
| @@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); | |||
| 120 | 120 | ||
| 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
| 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
| 123 | u64 channels_mask, int *channel, int *bandwidth, bool allocate); | 123 | u64 channels_mask, int *channel, int *bandwidth, |
| 124 | bool allocate, __be32 buffer[2]); | ||
| 124 | 125 | ||
| 125 | 126 | ||
| 126 | /* -topology */ | 127 | /* -topology */ |
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 24c45635376a..8d51568ee143 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
| @@ -201,6 +201,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) | |||
| 201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ | 201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ |
| 202 | 202 | ||
| 203 | /* | 203 | /* |
| 204 | * There is no transport protocol limit to the CDB length, but we implement | ||
| 205 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
| 206 | */ | ||
| 207 | #define SBP2_MAX_CDB_SIZE 16 | ||
| 208 | |||
| 209 | /* | ||
| 204 | * The default maximum s/g segment size of a FireWire controller is | 210 | * The default maximum s/g segment size of a FireWire controller is |
| 205 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to | 211 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to |
| 206 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. | 212 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. |
| @@ -312,7 +318,7 @@ struct sbp2_command_orb { | |||
| 312 | struct sbp2_pointer next; | 318 | struct sbp2_pointer next; |
| 313 | struct sbp2_pointer data_descriptor; | 319 | struct sbp2_pointer data_descriptor; |
| 314 | __be32 misc; | 320 | __be32 misc; |
| 315 | u8 command_block[12]; | 321 | u8 command_block[SBP2_MAX_CDB_SIZE]; |
| 316 | } request; | 322 | } request; |
| 317 | struct scsi_cmnd *cmd; | 323 | struct scsi_cmnd *cmd; |
| 318 | scsi_done_fn_t done; | 324 | scsi_done_fn_t done; |
| @@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) | |||
| 1146 | if (fw_device_enable_phys_dma(device) < 0) | 1152 | if (fw_device_enable_phys_dma(device) < 0) |
| 1147 | goto fail_shost_put; | 1153 | goto fail_shost_put; |
| 1148 | 1154 | ||
| 1155 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
| 1156 | |||
| 1149 | if (scsi_add_host(shost, &unit->device) < 0) | 1157 | if (scsi_add_host(shost, &unit->device) < 0) |
| 1150 | goto fail_shost_put; | 1158 | goto fail_shost_put; |
| 1151 | 1159 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3582c39f9725..96dda81c9228 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -79,6 +79,12 @@ config GPIO_XILINX | |||
| 79 | help | 79 | help |
| 80 | Say yes here to support the Xilinx FPGA GPIO device | 80 | Say yes here to support the Xilinx FPGA GPIO device |
| 81 | 81 | ||
| 82 | config GPIO_VR41XX | ||
| 83 | tristate "NEC VR4100 series General-purpose I/O Uint support" | ||
| 84 | depends on CPU_VR41XX | ||
| 85 | help | ||
| 86 | Say yes here to support the NEC VR4100 series General-purpose I/O Uint | ||
| 87 | |||
| 82 | comment "I2C GPIO expanders:" | 88 | comment "I2C GPIO expanders:" |
| 83 | 89 | ||
| 84 | config GPIO_MAX732X | 90 | config GPIO_MAX732X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ef90203e8f3c..9244c6fcd8be 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o | |||
| 13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
| 14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
| 15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
| 16 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index aa8e7cb020d9..4ee4c8367a3f 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c | |||
| @@ -109,6 +109,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) | |||
| 109 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); | 109 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 113 | { | ||
| 114 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 115 | |||
| 116 | if (chip->irq_base == (unsigned) -1) | ||
| 117 | return -EINVAL; | ||
| 118 | |||
| 119 | return chip->irq_base + offset; | ||
| 120 | } | ||
| 121 | |||
| 112 | /* | 122 | /* |
| 113 | * PL061 GPIO IRQ | 123 | * PL061 GPIO IRQ |
| 114 | */ | 124 | */ |
| @@ -200,7 +210,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 200 | desc->chip->ack(irq); | 210 | desc->chip->ack(irq); |
| 201 | list_for_each(ptr, chip_list) { | 211 | list_for_each(ptr, chip_list) { |
| 202 | unsigned long pending; | 212 | unsigned long pending; |
| 203 | int gpio; | 213 | int offset; |
| 204 | 214 | ||
| 205 | chip = list_entry(ptr, struct pl061_gpio, list); | 215 | chip = list_entry(ptr, struct pl061_gpio, list); |
| 206 | pending = readb(chip->base + GPIOMIS); | 216 | pending = readb(chip->base + GPIOMIS); |
| @@ -209,8 +219,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 209 | if (pending == 0) | 219 | if (pending == 0) |
| 210 | continue; | 220 | continue; |
| 211 | 221 | ||
| 212 | for_each_bit(gpio, &pending, PL061_GPIO_NR) | 222 | for_each_bit(offset, &pending, PL061_GPIO_NR) |
| 213 | generic_handle_irq(gpio_to_irq(gpio)); | 223 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); |
| 214 | } | 224 | } |
| 215 | desc->chip->unmask(irq); | 225 | desc->chip->unmask(irq); |
| 216 | } | 226 | } |
| @@ -221,7 +231,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
| 221 | struct pl061_gpio *chip; | 231 | struct pl061_gpio *chip; |
| 222 | struct list_head *chip_list; | 232 | struct list_head *chip_list; |
| 223 | int ret, irq, i; | 233 | int ret, irq, i; |
| 224 | static unsigned long init_irq[BITS_TO_LONGS(NR_IRQS)]; | 234 | static DECLARE_BITMAP(init_irq, NR_IRQS); |
| 225 | 235 | ||
| 226 | pdata = dev->dev.platform_data; | 236 | pdata = dev->dev.platform_data; |
| 227 | if (pdata == NULL) | 237 | if (pdata == NULL) |
| @@ -251,6 +261,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
| 251 | chip->gc.direction_output = pl061_direction_output; | 261 | chip->gc.direction_output = pl061_direction_output; |
| 252 | chip->gc.get = pl061_get_value; | 262 | chip->gc.get = pl061_get_value; |
| 253 | chip->gc.set = pl061_set_value; | 263 | chip->gc.set = pl061_set_value; |
| 264 | chip->gc.to_irq = pl061_to_irq; | ||
| 254 | chip->gc.base = pdata->gpio_base; | 265 | chip->gc.base = pdata->gpio_base; |
| 255 | chip->gc.ngpio = PL061_GPIO_NR; | 266 | chip->gc.ngpio = PL061_GPIO_NR; |
| 256 | chip->gc.label = dev_name(&dev->dev); | 267 | chip->gc.label = dev_name(&dev->dev); |
| @@ -280,6 +291,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) | |||
| 280 | if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ | 291 | if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ |
| 281 | chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); | 292 | chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); |
| 282 | if (chip_list == NULL) { | 293 | if (chip_list == NULL) { |
| 294 | clear_bit(irq, init_irq); | ||
| 283 | ret = -ENOMEM; | 295 | ret = -ENOMEM; |
| 284 | goto iounmap; | 296 | goto iounmap; |
| 285 | } | 297 | } |
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c new file mode 100644 index 000000000000..b16c9a8c03f5 --- /dev/null +++ b/drivers/gpio/vr41xx_giu.c | |||
| @@ -0,0 +1,585 @@ | |||
| 1 | /* | ||
| 2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
| 5 | * Author: Yoichi Yuasa <source@mvista.com> | ||
| 6 | * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/fs.h> | ||
| 24 | #include <linux/gpio.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | #include <linux/irq.h> | ||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/platform_device.h> | ||
| 32 | #include <linux/spinlock.h> | ||
| 33 | #include <linux/types.h> | ||
| 34 | |||
| 35 | #include <asm/vr41xx/giu.h> | ||
| 36 | #include <asm/vr41xx/irq.h> | ||
| 37 | #include <asm/vr41xx/vr41xx.h> | ||
| 38 | |||
| 39 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); | ||
| 40 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
| 41 | MODULE_LICENSE("GPL"); | ||
| 42 | |||
| 43 | #define GIUIOSELL 0x00 | ||
| 44 | #define GIUIOSELH 0x02 | ||
| 45 | #define GIUPIODL 0x04 | ||
| 46 | #define GIUPIODH 0x06 | ||
| 47 | #define GIUINTSTATL 0x08 | ||
| 48 | #define GIUINTSTATH 0x0a | ||
| 49 | #define GIUINTENL 0x0c | ||
| 50 | #define GIUINTENH 0x0e | ||
| 51 | #define GIUINTTYPL 0x10 | ||
| 52 | #define GIUINTTYPH 0x12 | ||
| 53 | #define GIUINTALSELL 0x14 | ||
| 54 | #define GIUINTALSELH 0x16 | ||
| 55 | #define GIUINTHTSELL 0x18 | ||
| 56 | #define GIUINTHTSELH 0x1a | ||
| 57 | #define GIUPODATL 0x1c | ||
| 58 | #define GIUPODATEN 0x1c | ||
| 59 | #define GIUPODATH 0x1e | ||
| 60 | #define PIOEN0 0x0100 | ||
| 61 | #define PIOEN1 0x0200 | ||
| 62 | #define GIUPODAT 0x1e | ||
| 63 | #define GIUFEDGEINHL 0x20 | ||
| 64 | #define GIUFEDGEINHH 0x22 | ||
| 65 | #define GIUREDGEINHL 0x24 | ||
| 66 | #define GIUREDGEINHH 0x26 | ||
| 67 | |||
| 68 | #define GIUUSEUPDN 0x1e0 | ||
| 69 | #define GIUTERMUPDN 0x1e2 | ||
| 70 | |||
| 71 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
| 72 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
| 73 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
| 74 | |||
| 75 | enum { | ||
| 76 | GPIO_INPUT, | ||
| 77 | GPIO_OUTPUT, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static DEFINE_SPINLOCK(giu_lock); | ||
| 81 | static unsigned long giu_flags; | ||
| 82 | |||
| 83 | static void __iomem *giu_base; | ||
| 84 | |||
| 85 | #define giu_read(offset) readw(giu_base + (offset)) | ||
| 86 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
| 87 | |||
| 88 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
| 89 | #define GIUINT_HIGH_OFFSET 16 | ||
| 90 | #define GIUINT_HIGH_MAX 32 | ||
| 91 | |||
| 92 | static inline u16 giu_set(u16 offset, u16 set) | ||
| 93 | { | ||
| 94 | u16 data; | ||
| 95 | |||
| 96 | data = giu_read(offset); | ||
| 97 | data |= set; | ||
| 98 | giu_write(offset, data); | ||
| 99 | |||
| 100 | return data; | ||
| 101 | } | ||
| 102 | |||
| 103 | static inline u16 giu_clear(u16 offset, u16 clear) | ||
| 104 | { | ||
| 105 | u16 data; | ||
| 106 | |||
| 107 | data = giu_read(offset); | ||
| 108 | data &= ~clear; | ||
| 109 | giu_write(offset, data); | ||
| 110 | |||
| 111 | return data; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void ack_giuint_low(unsigned int irq) | ||
| 115 | { | ||
| 116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void mask_giuint_low(unsigned int irq) | ||
| 120 | { | ||
| 121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void mask_ack_giuint_low(unsigned int irq) | ||
| 125 | { | ||
| 126 | unsigned int pin; | ||
| 127 | |||
| 128 | pin = GPIO_PIN_OF_IRQ(irq); | ||
| 129 | giu_clear(GIUINTENL, 1 << pin); | ||
| 130 | giu_write(GIUINTSTATL, 1 << pin); | ||
| 131 | } | ||
| 132 | |||
| 133 | static void unmask_giuint_low(unsigned int irq) | ||
| 134 | { | ||
| 135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
| 136 | } | ||
| 137 | |||
| 138 | static struct irq_chip giuint_low_irq_chip = { | ||
| 139 | .name = "GIUINTL", | ||
| 140 | .ack = ack_giuint_low, | ||
| 141 | .mask = mask_giuint_low, | ||
| 142 | .mask_ack = mask_ack_giuint_low, | ||
| 143 | .unmask = unmask_giuint_low, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static void ack_giuint_high(unsigned int irq) | ||
| 147 | { | ||
| 148 | giu_write(GIUINTSTATH, | ||
| 149 | 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 150 | } | ||
| 151 | |||
| 152 | static void mask_giuint_high(unsigned int irq) | ||
| 153 | { | ||
| 154 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void mask_ack_giuint_high(unsigned int irq) | ||
| 158 | { | ||
| 159 | unsigned int pin; | ||
| 160 | |||
| 161 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
| 162 | giu_clear(GIUINTENH, 1 << pin); | ||
| 163 | giu_write(GIUINTSTATH, 1 << pin); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void unmask_giuint_high(unsigned int irq) | ||
| 167 | { | ||
| 168 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
| 169 | } | ||
| 170 | |||
| 171 | static struct irq_chip giuint_high_irq_chip = { | ||
| 172 | .name = "GIUINTH", | ||
| 173 | .ack = ack_giuint_high, | ||
| 174 | .mask = mask_giuint_high, | ||
| 175 | .mask_ack = mask_ack_giuint_high, | ||
| 176 | .unmask = unmask_giuint_high, | ||
| 177 | }; | ||
| 178 | |||
| 179 | static int giu_get_irq(unsigned int irq) | ||
| 180 | { | ||
| 181 | u16 pendl, pendh, maskl, maskh; | ||
| 182 | int i; | ||
| 183 | |||
| 184 | pendl = giu_read(GIUINTSTATL); | ||
| 185 | pendh = giu_read(GIUINTSTATH); | ||
| 186 | maskl = giu_read(GIUINTENL); | ||
| 187 | maskh = giu_read(GIUINTENH); | ||
| 188 | |||
| 189 | maskl &= pendl; | ||
| 190 | maskh &= pendh; | ||
| 191 | |||
| 192 | if (maskl) { | ||
| 193 | for (i = 0; i < 16; i++) { | ||
| 194 | if (maskl & (1 << i)) | ||
| 195 | return GIU_IRQ(i); | ||
| 196 | } | ||
| 197 | } else if (maskh) { | ||
| 198 | for (i = 0; i < 16; i++) { | ||
| 199 | if (maskh & (1 << i)) | ||
| 200 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
| 205 | maskl, pendl, maskh, pendh); | ||
| 206 | |||
| 207 | atomic_inc(&irq_err_count); | ||
| 208 | |||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | |||
| 212 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, | ||
| 213 | irq_signal_t signal) | ||
| 214 | { | ||
| 215 | u16 mask; | ||
| 216 | |||
| 217 | if (pin < GIUINT_HIGH_OFFSET) { | ||
| 218 | mask = 1 << pin; | ||
| 219 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
| 220 | giu_set(GIUINTTYPL, mask); | ||
| 221 | if (signal == IRQ_SIGNAL_HOLD) | ||
| 222 | giu_set(GIUINTHTSELL, mask); | ||
| 223 | else | ||
| 224 | giu_clear(GIUINTHTSELL, mask); | ||
| 225 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
| 226 | switch (trigger) { | ||
| 227 | case IRQ_TRIGGER_EDGE_FALLING: | ||
| 228 | giu_set(GIUFEDGEINHL, mask); | ||
| 229 | giu_clear(GIUREDGEINHL, mask); | ||
| 230 | break; | ||
| 231 | case IRQ_TRIGGER_EDGE_RISING: | ||
| 232 | giu_clear(GIUFEDGEINHL, mask); | ||
| 233 | giu_set(GIUREDGEINHL, mask); | ||
| 234 | break; | ||
| 235 | default: | ||
| 236 | giu_set(GIUFEDGEINHL, mask); | ||
| 237 | giu_set(GIUREDGEINHL, mask); | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 242 | &giuint_low_irq_chip, | ||
| 243 | handle_edge_irq); | ||
| 244 | } else { | ||
| 245 | giu_clear(GIUINTTYPL, mask); | ||
| 246 | giu_clear(GIUINTHTSELL, mask); | ||
| 247 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 248 | &giuint_low_irq_chip, | ||
| 249 | handle_level_irq); | ||
| 250 | } | ||
| 251 | giu_write(GIUINTSTATL, mask); | ||
| 252 | } else if (pin < GIUINT_HIGH_MAX) { | ||
| 253 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
| 254 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
| 255 | giu_set(GIUINTTYPH, mask); | ||
| 256 | if (signal == IRQ_SIGNAL_HOLD) | ||
| 257 | giu_set(GIUINTHTSELH, mask); | ||
| 258 | else | ||
| 259 | giu_clear(GIUINTHTSELH, mask); | ||
| 260 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
| 261 | switch (trigger) { | ||
| 262 | case IRQ_TRIGGER_EDGE_FALLING: | ||
| 263 | giu_set(GIUFEDGEINHH, mask); | ||
| 264 | giu_clear(GIUREDGEINHH, mask); | ||
| 265 | break; | ||
| 266 | case IRQ_TRIGGER_EDGE_RISING: | ||
| 267 | giu_clear(GIUFEDGEINHH, mask); | ||
| 268 | giu_set(GIUREDGEINHH, mask); | ||
| 269 | break; | ||
| 270 | default: | ||
| 271 | giu_set(GIUFEDGEINHH, mask); | ||
| 272 | giu_set(GIUREDGEINHH, mask); | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 277 | &giuint_high_irq_chip, | ||
| 278 | handle_edge_irq); | ||
| 279 | } else { | ||
| 280 | giu_clear(GIUINTTYPH, mask); | ||
| 281 | giu_clear(GIUINTHTSELH, mask); | ||
| 282 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
| 283 | &giuint_high_irq_chip, | ||
| 284 | handle_level_irq); | ||
| 285 | } | ||
| 286 | giu_write(GIUINTSTATH, mask); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
| 290 | |||
| 291 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
| 292 | { | ||
| 293 | u16 mask; | ||
| 294 | |||
| 295 | if (pin < GIUINT_HIGH_OFFSET) { | ||
| 296 | mask = 1 << pin; | ||
| 297 | if (level == IRQ_LEVEL_HIGH) | ||
| 298 | giu_set(GIUINTALSELL, mask); | ||
| 299 | else | ||
| 300 | giu_clear(GIUINTALSELL, mask); | ||
| 301 | giu_write(GIUINTSTATL, mask); | ||
| 302 | } else if (pin < GIUINT_HIGH_MAX) { | ||
| 303 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
| 304 | if (level == IRQ_LEVEL_HIGH) | ||
| 305 | giu_set(GIUINTALSELH, mask); | ||
| 306 | else | ||
| 307 | giu_clear(GIUINTALSELH, mask); | ||
| 308 | giu_write(GIUINTSTATH, mask); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
| 312 | |||
| 313 | static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) | ||
| 314 | { | ||
| 315 | u16 offset, mask, reg; | ||
| 316 | unsigned long flags; | ||
| 317 | |||
| 318 | if (pin >= chip->ngpio) | ||
| 319 | return -EINVAL; | ||
| 320 | |||
| 321 | if (pin < 16) { | ||
| 322 | offset = GIUIOSELL; | ||
| 323 | mask = 1 << pin; | ||
| 324 | } else if (pin < 32) { | ||
| 325 | offset = GIUIOSELH; | ||
| 326 | mask = 1 << (pin - 16); | ||
| 327 | } else { | ||
| 328 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
| 329 | offset = GIUPODATEN; | ||
| 330 | mask = 1 << (pin - 32); | ||
| 331 | } else { | ||
| 332 | switch (pin) { | ||
| 333 | case 48: | ||
| 334 | offset = GIUPODATH; | ||
| 335 | mask = PIOEN0; | ||
| 336 | break; | ||
| 337 | case 49: | ||
| 338 | offset = GIUPODATH; | ||
| 339 | mask = PIOEN1; | ||
| 340 | break; | ||
| 341 | default: | ||
| 342 | return -EINVAL; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | spin_lock_irqsave(&giu_lock, flags); | ||
| 348 | |||
| 349 | reg = giu_read(offset); | ||
| 350 | if (dir == GPIO_OUTPUT) | ||
| 351 | reg |= mask; | ||
| 352 | else | ||
| 353 | reg &= ~mask; | ||
| 354 | giu_write(offset, reg); | ||
| 355 | |||
| 356 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 357 | |||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
| 362 | { | ||
| 363 | u16 reg, mask; | ||
| 364 | unsigned long flags; | ||
| 365 | |||
| 366 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
| 367 | return -EPERM; | ||
| 368 | |||
| 369 | if (pin >= 15) | ||
| 370 | return -EINVAL; | ||
| 371 | |||
| 372 | mask = 1 << pin; | ||
| 373 | |||
| 374 | spin_lock_irqsave(&giu_lock, flags); | ||
| 375 | |||
| 376 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
| 377 | reg = giu_read(GIUTERMUPDN); | ||
| 378 | if (pull == GPIO_PULL_UP) | ||
| 379 | reg |= mask; | ||
| 380 | else | ||
| 381 | reg &= ~mask; | ||
| 382 | giu_write(GIUTERMUPDN, reg); | ||
| 383 | |||
| 384 | reg = giu_read(GIUUSEUPDN); | ||
| 385 | reg |= mask; | ||
| 386 | giu_write(GIUUSEUPDN, reg); | ||
| 387 | } else { | ||
| 388 | reg = giu_read(GIUUSEUPDN); | ||
| 389 | reg &= ~mask; | ||
| 390 | giu_write(GIUUSEUPDN, reg); | ||
| 391 | } | ||
| 392 | |||
| 393 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
| 398 | |||
| 399 | static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) | ||
| 400 | { | ||
| 401 | u16 reg, mask; | ||
| 402 | |||
| 403 | if (pin >= chip->ngpio) | ||
| 404 | return -EINVAL; | ||
| 405 | |||
| 406 | if (pin < 16) { | ||
| 407 | reg = giu_read(GIUPIODL); | ||
| 408 | mask = 1 << pin; | ||
| 409 | } else if (pin < 32) { | ||
| 410 | reg = giu_read(GIUPIODH); | ||
| 411 | mask = 1 << (pin - 16); | ||
| 412 | } else if (pin < 48) { | ||
| 413 | reg = giu_read(GIUPODATL); | ||
| 414 | mask = 1 << (pin - 32); | ||
| 415 | } else { | ||
| 416 | reg = giu_read(GIUPODATH); | ||
| 417 | mask = 1 << (pin - 48); | ||
| 418 | } | ||
| 419 | |||
| 420 | if (reg & mask) | ||
| 421 | return 1; | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, | ||
| 427 | int value) | ||
| 428 | { | ||
| 429 | u16 offset, mask, reg; | ||
| 430 | unsigned long flags; | ||
| 431 | |||
| 432 | if (pin >= chip->ngpio) | ||
| 433 | return; | ||
| 434 | |||
| 435 | if (pin < 16) { | ||
| 436 | offset = GIUPIODL; | ||
| 437 | mask = 1 << pin; | ||
| 438 | } else if (pin < 32) { | ||
| 439 | offset = GIUPIODH; | ||
| 440 | mask = 1 << (pin - 16); | ||
| 441 | } else if (pin < 48) { | ||
| 442 | offset = GIUPODATL; | ||
| 443 | mask = 1 << (pin - 32); | ||
| 444 | } else { | ||
| 445 | offset = GIUPODATH; | ||
| 446 | mask = 1 << (pin - 48); | ||
| 447 | } | ||
| 448 | |||
| 449 | spin_lock_irqsave(&giu_lock, flags); | ||
| 450 | |||
| 451 | reg = giu_read(offset); | ||
| 452 | if (value) | ||
| 453 | reg |= mask; | ||
| 454 | else | ||
| 455 | reg &= ~mask; | ||
| 456 | giu_write(offset, reg); | ||
| 457 | |||
| 458 | spin_unlock_irqrestore(&giu_lock, flags); | ||
| 459 | } | ||
| 460 | |||
| 461 | |||
| 462 | static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
| 463 | { | ||
| 464 | return giu_set_direction(chip, offset, GPIO_INPUT); | ||
| 465 | } | ||
| 466 | |||
| 467 | static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
| 468 | int value) | ||
| 469 | { | ||
| 470 | vr41xx_gpio_set(chip, offset, value); | ||
| 471 | |||
| 472 | return giu_set_direction(chip, offset, GPIO_OUTPUT); | ||
| 473 | } | ||
| 474 | |||
| 475 | static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
| 476 | { | ||
| 477 | if (offset >= chip->ngpio) | ||
| 478 | return -EINVAL; | ||
| 479 | |||
| 480 | return GIU_IRQ_BASE + offset; | ||
| 481 | } | ||
| 482 | |||
| 483 | static struct gpio_chip vr41xx_gpio_chip = { | ||
| 484 | .label = "vr41xx", | ||
| 485 | .owner = THIS_MODULE, | ||
| 486 | .direction_input = vr41xx_gpio_direction_input, | ||
| 487 | .get = vr41xx_gpio_get, | ||
| 488 | .direction_output = vr41xx_gpio_direction_output, | ||
| 489 | .set = vr41xx_gpio_set, | ||
| 490 | .to_irq = vr41xx_gpio_to_irq, | ||
| 491 | }; | ||
| 492 | |||
| 493 | static int __devinit giu_probe(struct platform_device *pdev) | ||
| 494 | { | ||
| 495 | struct resource *res; | ||
| 496 | unsigned int trigger, i, pin; | ||
| 497 | struct irq_chip *chip; | ||
| 498 | int irq, retval; | ||
| 499 | |||
| 500 | switch (pdev->id) { | ||
| 501 | case GPIO_50PINS_PULLUPDOWN: | ||
| 502 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
| 503 | vr41xx_gpio_chip.ngpio = 50; | ||
| 504 | break; | ||
| 505 | case GPIO_36PINS: | ||
| 506 | vr41xx_gpio_chip.ngpio = 36; | ||
| 507 | break; | ||
| 508 | case GPIO_48PINS_EDGE_SELECT: | ||
| 509 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
| 510 | vr41xx_gpio_chip.ngpio = 48; | ||
| 511 | break; | ||
| 512 | default: | ||
| 513 | dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); | ||
| 514 | return -ENODEV; | ||
| 515 | } | ||
| 516 | |||
| 517 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 518 | if (!res) | ||
| 519 | return -EBUSY; | ||
| 520 | |||
| 521 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
| 522 | if (!giu_base) | ||
| 523 | return -ENOMEM; | ||
| 524 | |||
| 525 | vr41xx_gpio_chip.dev = &pdev->dev; | ||
| 526 | |||
| 527 | retval = gpiochip_add(&vr41xx_gpio_chip); | ||
| 528 | |||
| 529 | giu_write(GIUINTENL, 0); | ||
| 530 | giu_write(GIUINTENH, 0); | ||
| 531 | |||
| 532 | trigger = giu_read(GIUINTTYPH) << 16; | ||
| 533 | trigger |= giu_read(GIUINTTYPL); | ||
| 534 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
| 535 | pin = GPIO_PIN_OF_IRQ(i); | ||
| 536 | if (pin < GIUINT_HIGH_OFFSET) | ||
| 537 | chip = &giuint_low_irq_chip; | ||
| 538 | else | ||
| 539 | chip = &giuint_high_irq_chip; | ||
| 540 | |||
| 541 | if (trigger & (1 << pin)) | ||
| 542 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
| 543 | else | ||
| 544 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
| 545 | |||
| 546 | } | ||
| 547 | |||
| 548 | irq = platform_get_irq(pdev, 0); | ||
| 549 | if (irq < 0 || irq >= nr_irqs) | ||
| 550 | return -EBUSY; | ||
| 551 | |||
| 552 | return cascade_irq(irq, giu_get_irq); | ||
| 553 | } | ||
| 554 | |||
| 555 | static int __devexit giu_remove(struct platform_device *pdev) | ||
| 556 | { | ||
| 557 | if (giu_base) { | ||
| 558 | iounmap(giu_base); | ||
| 559 | giu_base = NULL; | ||
| 560 | } | ||
| 561 | |||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | static struct platform_driver giu_device_driver = { | ||
| 566 | .probe = giu_probe, | ||
| 567 | .remove = __devexit_p(giu_remove), | ||
| 568 | .driver = { | ||
| 569 | .name = "GIU", | ||
| 570 | .owner = THIS_MODULE, | ||
| 571 | }, | ||
| 572 | }; | ||
| 573 | |||
| 574 | static int __init vr41xx_giu_init(void) | ||
| 575 | { | ||
| 576 | return platform_driver_register(&giu_device_driver); | ||
| 577 | } | ||
| 578 | |||
| 579 | static void __exit vr41xx_giu_exit(void) | ||
| 580 | { | ||
| 581 | platform_driver_unregister(&giu_device_driver); | ||
| 582 | } | ||
| 583 | |||
| 584 | module_init(vr41xx_giu_init); | ||
| 585 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c961fe415aef..39b393d38bb3 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -81,6 +81,7 @@ config DRM_I830 | |||
| 81 | 81 | ||
| 82 | config DRM_I915 | 82 | config DRM_I915 |
| 83 | tristate "i915 driver" | 83 | tristate "i915 driver" |
| 84 | depends on AGP_INTEL | ||
| 84 | select FB_CFB_FILLRECT | 85 | select FB_CFB_FILLRECT |
| 85 | select FB_CFB_COPYAREA | 86 | select FB_CFB_COPYAREA |
| 86 | select FB_CFB_IMAGEBLIT | 87 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4e89ab08b7b8..fe23f29f7cba 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -16,6 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
| 16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
| 17 | 17 | ||
| 18 | obj-$(CONFIG_DRM) += drm.o | 18 | obj-$(CONFIG_DRM) += drm.o |
| 19 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
| 19 | obj-$(CONFIG_DRM_TDFX) += tdfx/ | 20 | obj-$(CONFIG_DRM_TDFX) += tdfx/ |
| 20 | obj-$(CONFIG_DRM_R128) += r128/ | 21 | obj-$(CONFIG_DRM_R128) += r128/ |
| 21 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 22 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
| @@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915) += i915/ | |||
| 26 | obj-$(CONFIG_DRM_SIS) += sis/ | 27 | obj-$(CONFIG_DRM_SIS) += sis/ |
| 27 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ | 28 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ |
| 28 | obj-$(CONFIG_DRM_VIA) +=via/ | 29 | obj-$(CONFIG_DRM_VIA) +=via/ |
| 29 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a6f73f1e99d9..3da9cfa31848 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -1090,6 +1090,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
| 1090 | if (ret == false) | 1090 | if (ret == false) |
| 1091 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); | 1091 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
| 1092 | } | 1092 | } |
| 1093 | /* disable the unused connectors while restoring the modesetting */ | ||
| 1094 | drm_helper_disable_unused_functions(dev); | ||
| 1093 | return 0; | 1095 | return 0; |
| 1094 | } | 1096 | } |
| 1095 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 1097 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 2960b6d73456..9903f270e440 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
| @@ -101,6 +101,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count, | |||
| 101 | continue; | 101 | continue; |
| 102 | 102 | ||
| 103 | tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); | 103 | tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); |
| 104 | if (tmp == NULL) { | ||
| 105 | ret = -1; | ||
| 106 | goto fail; | ||
| 107 | } | ||
| 104 | ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO, | 108 | ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO, |
| 105 | root, tmp, &drm_debugfs_fops); | 109 | root, tmp, &drm_debugfs_fops); |
| 106 | if (!ent) { | 110 | if (!ent) { |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7d0835226f6e..80cc6d06d61b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -294,10 +294,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; | 294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; |
| 295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; | 295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; |
| 296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; | 296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; |
| 297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo; | 297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; |
| 298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo; | 298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; |
| 299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf); | 299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; |
| 300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; | 300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); |
| 301 | 301 | ||
| 302 | /* ignore tiny modes */ | 302 | /* ignore tiny modes */ |
| 303 | if (hactive < 64 || vactive < 64) | 303 | if (hactive < 64 || vactive < 64) |
| @@ -347,8 +347,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | 347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
| 348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | 348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
| 349 | 349 | ||
| 350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; | 350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; |
| 351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; | 351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; |
| 352 | 352 | ||
| 353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { | 353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { |
| 354 | mode->width_mm *= 10; | 354 | mode->width_mm *= 10; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 8104ecaea26f..ffe8f4394d50 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
| @@ -134,26 +134,29 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) | |||
| 134 | BUG_ON((size & (PAGE_SIZE - 1)) != 0); | 134 | BUG_ON((size & (PAGE_SIZE - 1)) != 0); |
| 135 | 135 | ||
| 136 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); | 136 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); |
| 137 | if (!obj) | ||
| 138 | goto free; | ||
| 137 | 139 | ||
| 138 | obj->dev = dev; | 140 | obj->dev = dev; |
| 139 | obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); | 141 | obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); |
| 140 | if (IS_ERR(obj->filp)) { | 142 | if (IS_ERR(obj->filp)) |
| 141 | kfree(obj); | 143 | goto free; |
| 142 | return NULL; | ||
| 143 | } | ||
| 144 | 144 | ||
| 145 | kref_init(&obj->refcount); | 145 | kref_init(&obj->refcount); |
| 146 | kref_init(&obj->handlecount); | 146 | kref_init(&obj->handlecount); |
| 147 | obj->size = size; | 147 | obj->size = size; |
| 148 | if (dev->driver->gem_init_object != NULL && | 148 | if (dev->driver->gem_init_object != NULL && |
| 149 | dev->driver->gem_init_object(obj) != 0) { | 149 | dev->driver->gem_init_object(obj) != 0) { |
| 150 | fput(obj->filp); | 150 | goto fput; |
| 151 | kfree(obj); | ||
| 152 | return NULL; | ||
| 153 | } | 151 | } |
| 154 | atomic_inc(&dev->object_count); | 152 | atomic_inc(&dev->object_count); |
| 155 | atomic_add(obj->size, &dev->object_memory); | 153 | atomic_add(obj->size, &dev->object_memory); |
| 156 | return obj; | 154 | return obj; |
| 155 | fput: | ||
| 156 | fput(obj->filp); | ||
| 157 | free: | ||
| 158 | kfree(obj); | ||
| 159 | return NULL; | ||
| 157 | } | 160 | } |
| 158 | EXPORT_SYMBOL(drm_gem_object_alloc); | 161 | EXPORT_SYMBOL(drm_gem_object_alloc); |
| 159 | 162 | ||
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 155a5bbce680..55bb8a82d612 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
| @@ -489,7 +489,7 @@ int drm_put_minor(struct drm_minor **minor_p) | |||
| 489 | */ | 489 | */ |
| 490 | void drm_put_dev(struct drm_device *dev) | 490 | void drm_put_dev(struct drm_device *dev) |
| 491 | { | 491 | { |
| 492 | struct drm_driver *driver = dev->driver; | 492 | struct drm_driver *driver; |
| 493 | struct drm_map_list *r_list, *list_temp; | 493 | struct drm_map_list *r_list, *list_temp; |
| 494 | 494 | ||
| 495 | DRM_DEBUG("\n"); | 495 | DRM_DEBUG("\n"); |
| @@ -498,6 +498,7 @@ void drm_put_dev(struct drm_device *dev) | |||
| 498 | DRM_ERROR("cleanup called no dev\n"); | 498 | DRM_ERROR("cleanup called no dev\n"); |
| 499 | return; | 499 | return; |
| 500 | } | 500 | } |
| 501 | driver = dev->driver; | ||
| 501 | 502 | ||
| 502 | drm_vblank_cleanup(dev); | 503 | drm_vblank_cleanup(dev); |
| 503 | 504 | ||
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 51c5a050aa73..30d6b99fb302 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
| 13 | intel_crt.o \ | 13 | intel_crt.o \ |
| 14 | intel_lvds.o \ | 14 | intel_lvds.o \ |
| 15 | intel_bios.o \ | 15 | intel_bios.o \ |
| 16 | intel_dp.o \ | ||
| 17 | intel_dp_i2c.o \ | ||
| 16 | intel_hdmi.o \ | 18 | intel_hdmi.o \ |
| 17 | intel_sdvo.o \ | 19 | intel_sdvo.o \ |
| 18 | intel_modes.o \ | 20 | intel_modes.o \ |
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index e747ac42fe3a..288fc50627e2 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h | |||
| @@ -37,7 +37,7 @@ struct intel_dvo_device { | |||
| 37 | /* GPIO register used for i2c bus to control this device */ | 37 | /* GPIO register used for i2c bus to control this device */ |
| 38 | u32 gpio; | 38 | u32 gpio; |
| 39 | int slave_addr; | 39 | int slave_addr; |
| 40 | struct intel_i2c_chan *i2c_bus; | 40 | struct i2c_adapter *i2c_bus; |
| 41 | 41 | ||
| 42 | const struct intel_dvo_dev_ops *dev_ops; | 42 | const struct intel_dvo_dev_ops *dev_ops; |
| 43 | void *dev_priv; | 43 | void *dev_priv; |
| @@ -52,7 +52,7 @@ struct intel_dvo_dev_ops { | |||
| 52 | * Returns NULL if the device does not exist. | 52 | * Returns NULL if the device does not exist. |
| 53 | */ | 53 | */ |
| 54 | bool (*init)(struct intel_dvo_device *dvo, | 54 | bool (*init)(struct intel_dvo_device *dvo, |
| 55 | struct intel_i2c_chan *i2cbus); | 55 | struct i2c_adapter *i2cbus); |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| 58 | * Called to allow the output a chance to create properties after the | 58 | * Called to allow the output a chance to create properties after the |
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 03d4b4973b02..621815b531db 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c | |||
| @@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); | |||
| 176 | 176 | ||
| 177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | 177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) |
| 178 | { | 178 | { |
| 179 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 179 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 180 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 180 | u8 out_buf[2]; | 181 | u8 out_buf[2]; |
| 181 | u8 in_buf[2]; | 182 | u8 in_buf[2]; |
| 182 | 183 | ||
| 183 | struct i2c_msg msgs[] = { | 184 | struct i2c_msg msgs[] = { |
| 184 | { | 185 | { |
| 185 | .addr = i2cbus->slave_addr, | 186 | .addr = dvo->slave_addr, |
| 186 | .flags = 0, | 187 | .flags = 0, |
| 187 | .len = 1, | 188 | .len = 1, |
| 188 | .buf = out_buf, | 189 | .buf = out_buf, |
| 189 | }, | 190 | }, |
| 190 | { | 191 | { |
| 191 | .addr = i2cbus->slave_addr, | 192 | .addr = dvo->slave_addr, |
| 192 | .flags = I2C_M_RD, | 193 | .flags = I2C_M_RD, |
| 193 | .len = 1, | 194 | .len = 1, |
| 194 | .buf = in_buf, | 195 | .buf = in_buf, |
| @@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | |||
| 208 | 209 | ||
| 209 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | 210 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) |
| 210 | { | 211 | { |
| 211 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 212 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 213 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 212 | uint8_t out_buf[2]; | 214 | uint8_t out_buf[2]; |
| 213 | struct i2c_msg msg = { | 215 | struct i2c_msg msg = { |
| 214 | .addr = i2cbus->slave_addr, | 216 | .addr = dvo->slave_addr, |
| 215 | .flags = 0, | 217 | .flags = 0, |
| 216 | .len = 2, | 218 | .len = 2, |
| 217 | .buf = out_buf, | 219 | .buf = out_buf, |
| @@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | |||
| 228 | 230 | ||
| 229 | /** Probes for a CH7017 on the given bus and slave address. */ | 231 | /** Probes for a CH7017 on the given bus and slave address. */ |
| 230 | static bool ch7017_init(struct intel_dvo_device *dvo, | 232 | static bool ch7017_init(struct intel_dvo_device *dvo, |
| 231 | struct intel_i2c_chan *i2cbus) | 233 | struct i2c_adapter *adapter) |
| 232 | { | 234 | { |
| 235 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 233 | struct ch7017_priv *priv; | 236 | struct ch7017_priv *priv; |
| 234 | uint8_t val; | 237 | uint8_t val; |
| 235 | 238 | ||
| @@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
| 237 | if (priv == NULL) | 240 | if (priv == NULL) |
| 238 | return false; | 241 | return false; |
| 239 | 242 | ||
| 240 | dvo->i2c_bus = i2cbus; | 243 | dvo->i2c_bus = adapter; |
| 241 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 242 | dvo->dev_priv = priv; | 244 | dvo->dev_priv = priv; |
| 243 | 245 | ||
| 244 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) | 246 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) |
| @@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
| 248 | val != CH7018_DEVICE_ID_VALUE && | 250 | val != CH7018_DEVICE_ID_VALUE && |
| 249 | val != CH7019_DEVICE_ID_VALUE) { | 251 | val != CH7019_DEVICE_ID_VALUE) { |
| 250 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", | 252 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", |
| 251 | val, i2cbus->adapter.name,i2cbus->slave_addr); | 253 | val, i2cbus->adapter.name,dvo->slave_addr); |
| 252 | goto fail; | 254 | goto fail; |
| 253 | } | 255 | } |
| 254 | 256 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index d2fd95dbd034..a9b896289680 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c | |||
| @@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid) | |||
| 123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 124 | { | 124 | { |
| 125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; | 125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; |
| 126 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 126 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 127 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 127 | u8 out_buf[2]; | 128 | u8 out_buf[2]; |
| 128 | u8 in_buf[2]; | 129 | u8 in_buf[2]; |
| 129 | 130 | ||
| 130 | struct i2c_msg msgs[] = { | 131 | struct i2c_msg msgs[] = { |
| 131 | { | 132 | { |
| 132 | .addr = i2cbus->slave_addr, | 133 | .addr = dvo->slave_addr, |
| 133 | .flags = 0, | 134 | .flags = 0, |
| 134 | .len = 1, | 135 | .len = 1, |
| 135 | .buf = out_buf, | 136 | .buf = out_buf, |
| 136 | }, | 137 | }, |
| 137 | { | 138 | { |
| 138 | .addr = i2cbus->slave_addr, | 139 | .addr = dvo->slave_addr, |
| 139 | .flags = I2C_M_RD, | 140 | .flags = I2C_M_RD, |
| 140 | .len = 1, | 141 | .len = 1, |
| 141 | .buf = in_buf, | 142 | .buf = in_buf, |
| @@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 152 | 153 | ||
| 153 | if (!ch7xxx->quiet) { | 154 | if (!ch7xxx->quiet) { |
| 154 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 155 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 155 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 156 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 156 | } | 157 | } |
| 157 | return false; | 158 | return false; |
| 158 | } | 159 | } |
| @@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 161 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 162 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 162 | { | 163 | { |
| 163 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; | 164 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; |
| 164 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 165 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 166 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 165 | uint8_t out_buf[2]; | 167 | uint8_t out_buf[2]; |
| 166 | struct i2c_msg msg = { | 168 | struct i2c_msg msg = { |
| 167 | .addr = i2cbus->slave_addr, | 169 | .addr = dvo->slave_addr, |
| 168 | .flags = 0, | 170 | .flags = 0, |
| 169 | .len = 2, | 171 | .len = 2, |
| 170 | .buf = out_buf, | 172 | .buf = out_buf, |
| @@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 178 | 180 | ||
| 179 | if (!ch7xxx->quiet) { | 181 | if (!ch7xxx->quiet) { |
| 180 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 182 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 181 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 183 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | return false; | 186 | return false; |
| 185 | } | 187 | } |
| 186 | 188 | ||
| 187 | static bool ch7xxx_init(struct intel_dvo_device *dvo, | 189 | static bool ch7xxx_init(struct intel_dvo_device *dvo, |
| 188 | struct intel_i2c_chan *i2cbus) | 190 | struct i2c_adapter *adapter) |
| 189 | { | 191 | { |
| 190 | /* this will detect the CH7xxx chip on the specified i2c bus */ | 192 | /* this will detect the CH7xxx chip on the specified i2c bus */ |
| 191 | struct ch7xxx_priv *ch7xxx; | 193 | struct ch7xxx_priv *ch7xxx; |
| @@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 196 | if (ch7xxx == NULL) | 198 | if (ch7xxx == NULL) |
| 197 | return false; | 199 | return false; |
| 198 | 200 | ||
| 199 | dvo->i2c_bus = i2cbus; | 201 | dvo->i2c_bus = adapter; |
| 200 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 201 | dvo->dev_priv = ch7xxx; | 202 | dvo->dev_priv = ch7xxx; |
| 202 | ch7xxx->quiet = true; | 203 | ch7xxx->quiet = true; |
| 203 | 204 | ||
| @@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 207 | name = ch7xxx_get_id(vendor); | 208 | name = ch7xxx_get_id(vendor); |
| 208 | if (!name) { | 209 | if (!name) { |
| 209 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 210 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
| 210 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 211 | vendor, adapter->name, dvo->slave_addr); |
| 211 | goto out; | 212 | goto out; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| @@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 217 | 218 | ||
| 218 | if (device != CH7xxx_DID) { | 219 | if (device != CH7xxx_DID) { |
| 219 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 220 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
| 220 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 221 | vendor, adapter->name, dvo->slave_addr); |
| 221 | goto out; | 222 | goto out; |
| 222 | } | 223 | } |
| 223 | 224 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 0c8d375e8e37..aa176f9921fe 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c | |||
| @@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo); | |||
| 169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | 169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) |
| 170 | { | 170 | { |
| 171 | struct ivch_priv *priv = dvo->dev_priv; | 171 | struct ivch_priv *priv = dvo->dev_priv; |
| 172 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 172 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 173 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 173 | u8 out_buf[1]; | 174 | u8 out_buf[1]; |
| 174 | u8 in_buf[2]; | 175 | u8 in_buf[2]; |
| 175 | 176 | ||
| 176 | struct i2c_msg msgs[] = { | 177 | struct i2c_msg msgs[] = { |
| 177 | { | 178 | { |
| 178 | .addr = i2cbus->slave_addr, | 179 | .addr = dvo->slave_addr, |
| 179 | .flags = I2C_M_RD, | 180 | .flags = I2C_M_RD, |
| 180 | .len = 0, | 181 | .len = 0, |
| 181 | }, | 182 | }, |
| @@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 186 | .buf = out_buf, | 187 | .buf = out_buf, |
| 187 | }, | 188 | }, |
| 188 | { | 189 | { |
| 189 | .addr = i2cbus->slave_addr, | 190 | .addr = dvo->slave_addr, |
| 190 | .flags = I2C_M_RD | I2C_M_NOSTART, | 191 | .flags = I2C_M_RD | I2C_M_NOSTART, |
| 191 | .len = 2, | 192 | .len = 2, |
| 192 | .buf = in_buf, | 193 | .buf = in_buf, |
| @@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 202 | 203 | ||
| 203 | if (!priv->quiet) { | 204 | if (!priv->quiet) { |
| 204 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 205 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 205 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 206 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 206 | } | 207 | } |
| 207 | return false; | 208 | return false; |
| 208 | } | 209 | } |
| @@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 211 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | 212 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) |
| 212 | { | 213 | { |
| 213 | struct ivch_priv *priv = dvo->dev_priv; | 214 | struct ivch_priv *priv = dvo->dev_priv; |
| 214 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 215 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 216 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 215 | u8 out_buf[3]; | 217 | u8 out_buf[3]; |
| 216 | struct i2c_msg msg = { | 218 | struct i2c_msg msg = { |
| 217 | .addr = i2cbus->slave_addr, | 219 | .addr = dvo->slave_addr, |
| 218 | .flags = 0, | 220 | .flags = 0, |
| 219 | .len = 3, | 221 | .len = 3, |
| 220 | .buf = out_buf, | 222 | .buf = out_buf, |
| @@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
| 229 | 231 | ||
| 230 | if (!priv->quiet) { | 232 | if (!priv->quiet) { |
| 231 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 233 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 232 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 234 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 233 | } | 235 | } |
| 234 | 236 | ||
| 235 | return false; | 237 | return false; |
| @@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
| 237 | 239 | ||
| 238 | /** Probes the given bus and slave address for an ivch */ | 240 | /** Probes the given bus and slave address for an ivch */ |
| 239 | static bool ivch_init(struct intel_dvo_device *dvo, | 241 | static bool ivch_init(struct intel_dvo_device *dvo, |
| 240 | struct intel_i2c_chan *i2cbus) | 242 | struct i2c_adapter *adapter) |
| 241 | { | 243 | { |
| 242 | struct ivch_priv *priv; | 244 | struct ivch_priv *priv; |
| 243 | uint16_t temp; | 245 | uint16_t temp; |
| @@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, | |||
| 246 | if (priv == NULL) | 248 | if (priv == NULL) |
| 247 | return false; | 249 | return false; |
| 248 | 250 | ||
| 249 | dvo->i2c_bus = i2cbus; | 251 | dvo->i2c_bus = adapter; |
| 250 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 251 | dvo->dev_priv = priv; | 252 | dvo->dev_priv = priv; |
| 252 | priv->quiet = true; | 253 | priv->quiet = true; |
| 253 | 254 | ||
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 033a4bb070b2..e1c1f7341e5c 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c | |||
| @@ -76,19 +76,20 @@ struct sil164_priv { | |||
| 76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 77 | { | 77 | { |
| 78 | struct sil164_priv *sil = dvo->dev_priv; | 78 | struct sil164_priv *sil = dvo->dev_priv; |
| 79 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 79 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 80 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 80 | u8 out_buf[2]; | 81 | u8 out_buf[2]; |
| 81 | u8 in_buf[2]; | 82 | u8 in_buf[2]; |
| 82 | 83 | ||
| 83 | struct i2c_msg msgs[] = { | 84 | struct i2c_msg msgs[] = { |
| 84 | { | 85 | { |
| 85 | .addr = i2cbus->slave_addr, | 86 | .addr = dvo->slave_addr, |
| 86 | .flags = 0, | 87 | .flags = 0, |
| 87 | .len = 1, | 88 | .len = 1, |
| 88 | .buf = out_buf, | 89 | .buf = out_buf, |
| 89 | }, | 90 | }, |
| 90 | { | 91 | { |
| 91 | .addr = i2cbus->slave_addr, | 92 | .addr = dvo->slave_addr, |
| 92 | .flags = I2C_M_RD, | 93 | .flags = I2C_M_RD, |
| 93 | .len = 1, | 94 | .len = 1, |
| 94 | .buf = in_buf, | 95 | .buf = in_buf, |
| @@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 105 | 106 | ||
| 106 | if (!sil->quiet) { | 107 | if (!sil->quiet) { |
| 107 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 108 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 108 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 109 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 109 | } | 110 | } |
| 110 | return false; | 111 | return false; |
| 111 | } | 112 | } |
| @@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 113 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 114 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 114 | { | 115 | { |
| 115 | struct sil164_priv *sil= dvo->dev_priv; | 116 | struct sil164_priv *sil= dvo->dev_priv; |
| 116 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 117 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 118 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 117 | uint8_t out_buf[2]; | 119 | uint8_t out_buf[2]; |
| 118 | struct i2c_msg msg = { | 120 | struct i2c_msg msg = { |
| 119 | .addr = i2cbus->slave_addr, | 121 | .addr = dvo->slave_addr, |
| 120 | .flags = 0, | 122 | .flags = 0, |
| 121 | .len = 2, | 123 | .len = 2, |
| 122 | .buf = out_buf, | 124 | .buf = out_buf, |
| @@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 130 | 132 | ||
| 131 | if (!sil->quiet) { | 133 | if (!sil->quiet) { |
| 132 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 134 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 135 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | return false; | 138 | return false; |
| @@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 138 | 140 | ||
| 139 | /* Silicon Image 164 driver for chip on i2c bus */ | 141 | /* Silicon Image 164 driver for chip on i2c bus */ |
| 140 | static bool sil164_init(struct intel_dvo_device *dvo, | 142 | static bool sil164_init(struct intel_dvo_device *dvo, |
| 141 | struct intel_i2c_chan *i2cbus) | 143 | struct i2c_adapter *adapter) |
| 142 | { | 144 | { |
| 143 | /* this will detect the SIL164 chip on the specified i2c bus */ | 145 | /* this will detect the SIL164 chip on the specified i2c bus */ |
| 144 | struct sil164_priv *sil; | 146 | struct sil164_priv *sil; |
| @@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 148 | if (sil == NULL) | 150 | if (sil == NULL) |
| 149 | return false; | 151 | return false; |
| 150 | 152 | ||
| 151 | dvo->i2c_bus = i2cbus; | 153 | dvo->i2c_bus = adapter; |
| 152 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 153 | dvo->dev_priv = sil; | 154 | dvo->dev_priv = sil; |
| 154 | sil->quiet = true; | 155 | sil->quiet = true; |
| 155 | 156 | ||
| @@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 158 | 159 | ||
| 159 | if (ch != (SIL164_VID & 0xff)) { | 160 | if (ch != (SIL164_VID & 0xff)) { |
| 160 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 161 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
| 161 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 162 | ch, adapter->name, dvo->slave_addr); |
| 162 | goto out; | 163 | goto out; |
| 163 | } | 164 | } |
| 164 | 165 | ||
| @@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 167 | 168 | ||
| 168 | if (ch != (SIL164_DID & 0xff)) { | 169 | if (ch != (SIL164_DID & 0xff)) { |
| 169 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 170 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
| 170 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 171 | ch, adapter->name, dvo->slave_addr); |
| 171 | goto out; | 172 | goto out; |
| 172 | } | 173 | } |
| 173 | sil->quiet = false; | 174 | sil->quiet = false; |
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 207fda806ebf..9ecc907384ec 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c | |||
| @@ -101,19 +101,20 @@ struct tfp410_priv { | |||
| 101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 102 | { | 102 | { |
| 103 | struct tfp410_priv *tfp = dvo->dev_priv; | 103 | struct tfp410_priv *tfp = dvo->dev_priv; |
| 104 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 104 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 105 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 105 | u8 out_buf[2]; | 106 | u8 out_buf[2]; |
| 106 | u8 in_buf[2]; | 107 | u8 in_buf[2]; |
| 107 | 108 | ||
| 108 | struct i2c_msg msgs[] = { | 109 | struct i2c_msg msgs[] = { |
| 109 | { | 110 | { |
| 110 | .addr = i2cbus->slave_addr, | 111 | .addr = dvo->slave_addr, |
| 111 | .flags = 0, | 112 | .flags = 0, |
| 112 | .len = 1, | 113 | .len = 1, |
| 113 | .buf = out_buf, | 114 | .buf = out_buf, |
| 114 | }, | 115 | }, |
| 115 | { | 116 | { |
| 116 | .addr = i2cbus->slave_addr, | 117 | .addr = dvo->slave_addr, |
| 117 | .flags = I2C_M_RD, | 118 | .flags = I2C_M_RD, |
| 118 | .len = 1, | 119 | .len = 1, |
| 119 | .buf = in_buf, | 120 | .buf = in_buf, |
| @@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 130 | 131 | ||
| 131 | if (!tfp->quiet) { | 132 | if (!tfp->quiet) { |
| 132 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 133 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 134 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 134 | } | 135 | } |
| 135 | return false; | 136 | return false; |
| 136 | } | 137 | } |
| @@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 138 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 139 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 139 | { | 140 | { |
| 140 | struct tfp410_priv *tfp = dvo->dev_priv; | 141 | struct tfp410_priv *tfp = dvo->dev_priv; |
| 141 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 142 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 143 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 142 | uint8_t out_buf[2]; | 144 | uint8_t out_buf[2]; |
| 143 | struct i2c_msg msg = { | 145 | struct i2c_msg msg = { |
| 144 | .addr = i2cbus->slave_addr, | 146 | .addr = dvo->slave_addr, |
| 145 | .flags = 0, | 147 | .flags = 0, |
| 146 | .len = 2, | 148 | .len = 2, |
| 147 | .buf = out_buf, | 149 | .buf = out_buf, |
| @@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 155 | 157 | ||
| 156 | if (!tfp->quiet) { | 158 | if (!tfp->quiet) { |
| 157 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 159 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 158 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 160 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | return false; | 163 | return false; |
| @@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr) | |||
| 174 | 176 | ||
| 175 | /* Ti TFP410 driver for chip on i2c bus */ | 177 | /* Ti TFP410 driver for chip on i2c bus */ |
| 176 | static bool tfp410_init(struct intel_dvo_device *dvo, | 178 | static bool tfp410_init(struct intel_dvo_device *dvo, |
| 177 | struct intel_i2c_chan *i2cbus) | 179 | struct i2c_adapter *adapter) |
| 178 | { | 180 | { |
| 179 | /* this will detect the tfp410 chip on the specified i2c bus */ | 181 | /* this will detect the tfp410 chip on the specified i2c bus */ |
| 180 | struct tfp410_priv *tfp; | 182 | struct tfp410_priv *tfp; |
| @@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo, | |||
| 184 | if (tfp == NULL) | 186 | if (tfp == NULL) |
| 185 | return false; | 187 | return false; |
| 186 | 188 | ||
| 187 | dvo->i2c_bus = i2cbus; | 189 | dvo->i2c_bus = adapter; |
| 188 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 189 | dvo->dev_priv = tfp; | 190 | dvo->dev_priv = tfp; |
| 190 | tfp->quiet = true; | 191 | tfp->quiet = true; |
| 191 | 192 | ||
| 192 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { | 193 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { |
| 193 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", | 194 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", |
| 194 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 195 | id, adapter->name, dvo->slave_addr); |
| 195 | goto out; | 196 | goto out; |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { | 199 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { |
| 199 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", | 200 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", |
| 200 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 201 | id, adapter->name, dvo->slave_addr); |
| 201 | goto out; | 202 | goto out; |
| 202 | } | 203 | } |
| 203 | tfp->quiet = false; | 204 | tfp->quiet = false; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f112c769d533..8c4783180bf6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -846,7 +846,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 846 | return 0; | 846 | return 0; |
| 847 | } | 847 | } |
| 848 | 848 | ||
| 849 | printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); | 849 | DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr); |
| 850 | 850 | ||
| 851 | dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); | 851 | dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); |
| 852 | 852 | ||
| @@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 885 | * some RAM for the framebuffer at early boot. This code figures out | 885 | * some RAM for the framebuffer at early boot. This code figures out |
| 886 | * how much was set aside so we can use it for our own purposes. | 886 | * how much was set aside so we can use it for our own purposes. |
| 887 | */ | 887 | */ |
| 888 | static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | 888 | static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, |
| 889 | unsigned long *preallocated_size) | 889 | uint32_t *preallocated_size) |
| 890 | { | 890 | { |
| 891 | struct pci_dev *bridge_dev; | 891 | struct pci_dev *bridge_dev; |
| 892 | u16 tmp = 0; | 892 | u16 tmp = 0; |
| @@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
| 984 | return 0; | 984 | return 0; |
| 985 | } | 985 | } |
| 986 | 986 | ||
| 987 | static int i915_load_modeset_init(struct drm_device *dev) | 987 | static int i915_load_modeset_init(struct drm_device *dev, |
| 988 | unsigned long prealloc_size, | ||
| 989 | unsigned long agp_size) | ||
| 988 | { | 990 | { |
| 989 | struct drm_i915_private *dev_priv = dev->dev_private; | 991 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 990 | unsigned long agp_size, prealloc_size; | ||
| 991 | int fb_bar = IS_I9XX(dev) ? 2 : 0; | 992 | int fb_bar = IS_I9XX(dev) ? 2 : 0; |
| 992 | int ret = 0; | 993 | int ret = 0; |
| 993 | 994 | ||
| @@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 1002 | if (IS_I965G(dev) || IS_G33(dev)) | 1003 | if (IS_I965G(dev) || IS_G33(dev)) |
| 1003 | dev_priv->cursor_needs_physical = false; | 1004 | dev_priv->cursor_needs_physical = false; |
| 1004 | 1005 | ||
| 1005 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); | ||
| 1006 | if (ret) | ||
| 1007 | goto out; | ||
| 1008 | |||
| 1009 | /* Basic memrange allocator for stolen space (aka vram) */ | 1006 | /* Basic memrange allocator for stolen space (aka vram) */ |
| 1010 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); | 1007 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); |
| 1011 | 1008 | ||
| @@ -1082,6 +1079,44 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) | |||
| 1082 | master->driver_priv = NULL; | 1079 | master->driver_priv = NULL; |
| 1083 | } | 1080 | } |
| 1084 | 1081 | ||
| 1082 | static void i915_get_mem_freq(struct drm_device *dev) | ||
| 1083 | { | ||
| 1084 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 1085 | u32 tmp; | ||
| 1086 | |||
| 1087 | if (!IS_IGD(dev)) | ||
| 1088 | return; | ||
| 1089 | |||
| 1090 | tmp = I915_READ(CLKCFG); | ||
| 1091 | |||
| 1092 | switch (tmp & CLKCFG_FSB_MASK) { | ||
| 1093 | case CLKCFG_FSB_533: | ||
| 1094 | dev_priv->fsb_freq = 533; /* 133*4 */ | ||
| 1095 | break; | ||
| 1096 | case CLKCFG_FSB_800: | ||
| 1097 | dev_priv->fsb_freq = 800; /* 200*4 */ | ||
| 1098 | break; | ||
| 1099 | case CLKCFG_FSB_667: | ||
| 1100 | dev_priv->fsb_freq = 667; /* 167*4 */ | ||
| 1101 | break; | ||
| 1102 | case CLKCFG_FSB_400: | ||
| 1103 | dev_priv->fsb_freq = 400; /* 100*4 */ | ||
| 1104 | break; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | switch (tmp & CLKCFG_MEM_MASK) { | ||
| 1108 | case CLKCFG_MEM_533: | ||
| 1109 | dev_priv->mem_freq = 533; | ||
| 1110 | break; | ||
| 1111 | case CLKCFG_MEM_667: | ||
| 1112 | dev_priv->mem_freq = 667; | ||
| 1113 | break; | ||
| 1114 | case CLKCFG_MEM_800: | ||
| 1115 | dev_priv->mem_freq = 800; | ||
| 1116 | break; | ||
| 1117 | } | ||
| 1118 | } | ||
| 1119 | |||
| 1085 | /** | 1120 | /** |
| 1086 | * i915_driver_load - setup chip and create an initial config | 1121 | * i915_driver_load - setup chip and create an initial config |
| 1087 | * @dev: DRM device | 1122 | * @dev: DRM device |
| @@ -1098,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1098 | struct drm_i915_private *dev_priv = dev->dev_private; | 1133 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1099 | resource_size_t base, size; | 1134 | resource_size_t base, size; |
| 1100 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 1135 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; |
| 1136 | uint32_t agp_size, prealloc_size; | ||
| 1101 | 1137 | ||
| 1102 | /* i915 has 4 more counters */ | 1138 | /* i915 has 4 more counters */ |
| 1103 | dev->counters += 4; | 1139 | dev->counters += 4; |
| @@ -1146,9 +1182,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1146 | "performance may suffer.\n"); | 1182 | "performance may suffer.\n"); |
| 1147 | } | 1183 | } |
| 1148 | 1184 | ||
| 1185 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); | ||
| 1186 | if (ret) | ||
| 1187 | goto out_iomapfree; | ||
| 1188 | |||
| 1149 | /* enable GEM by default */ | 1189 | /* enable GEM by default */ |
| 1150 | dev_priv->has_gem = 1; | 1190 | dev_priv->has_gem = 1; |
| 1151 | 1191 | ||
| 1192 | if (prealloc_size > agp_size * 3 / 4) { | ||
| 1193 | DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " | ||
| 1194 | "memory stolen.\n", | ||
| 1195 | prealloc_size / 1024, agp_size / 1024); | ||
| 1196 | DRM_ERROR("Disabling GEM. (try reducing stolen memory or " | ||
| 1197 | "updating the BIOS to fix).\n"); | ||
| 1198 | dev_priv->has_gem = 0; | ||
| 1199 | } | ||
| 1200 | |||
| 1152 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 1201 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| 1153 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 1202 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
| 1154 | if (IS_G4X(dev) || IS_IGDNG(dev)) { | 1203 | if (IS_G4X(dev) || IS_IGDNG(dev)) { |
| @@ -1165,6 +1214,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1165 | goto out_iomapfree; | 1214 | goto out_iomapfree; |
| 1166 | } | 1215 | } |
| 1167 | 1216 | ||
| 1217 | i915_get_mem_freq(dev); | ||
| 1218 | |||
| 1168 | /* On the 945G/GM, the chipset reports the MSI capability on the | 1219 | /* On the 945G/GM, the chipset reports the MSI capability on the |
| 1169 | * integrated graphics even though the support isn't actually there | 1220 | * integrated graphics even though the support isn't actually there |
| 1170 | * according to the published specs. It doesn't appear to function | 1221 | * according to the published specs. It doesn't appear to function |
| @@ -1180,6 +1231,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1180 | pci_enable_msi(dev->pdev); | 1231 | pci_enable_msi(dev->pdev); |
| 1181 | 1232 | ||
| 1182 | spin_lock_init(&dev_priv->user_irq_lock); | 1233 | spin_lock_init(&dev_priv->user_irq_lock); |
| 1234 | spin_lock_init(&dev_priv->error_lock); | ||
| 1183 | dev_priv->user_irq_refcount = 0; | 1235 | dev_priv->user_irq_refcount = 0; |
| 1184 | 1236 | ||
| 1185 | ret = drm_vblank_init(dev, I915_NUM_PIPE); | 1237 | ret = drm_vblank_init(dev, I915_NUM_PIPE); |
| @@ -1190,7 +1242,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1190 | } | 1242 | } |
| 1191 | 1243 | ||
| 1192 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1244 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1193 | ret = i915_load_modeset_init(dev); | 1245 | ret = i915_load_modeset_init(dev, prealloc_size, agp_size); |
| 1194 | if (ret < 0) { | 1246 | if (ret < 0) { |
| 1195 | DRM_ERROR("failed to init modeset\n"); | 1247 | DRM_ERROR("failed to init modeset\n"); |
| 1196 | goto out_rmmap; | 1248 | goto out_rmmap; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 98560e1e899a..fc4b68aa2d05 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include "drm_pciids.h" | 36 | #include "drm_pciids.h" |
| 37 | #include <linux/console.h> | 37 | #include <linux/console.h> |
| 38 | #include "drm_crtc_helper.h" | ||
| 38 | 39 | ||
| 39 | static unsigned int i915_modeset = -1; | 40 | static unsigned int i915_modeset = -1; |
| 40 | module_param_named(modeset, i915_modeset, int, 0400); | 41 | module_param_named(modeset, i915_modeset, int, 0400); |
| @@ -57,8 +58,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 57 | struct drm_i915_private *dev_priv = dev->dev_private; | 58 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 58 | 59 | ||
| 59 | if (!dev || !dev_priv) { | 60 | if (!dev || !dev_priv) { |
| 60 | printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv); | 61 | DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv); |
| 61 | printk(KERN_ERR "DRM not initialized, aborting suspend.\n"); | 62 | DRM_ERROR("DRM not initialized, aborting suspend.\n"); |
| 62 | return -ENODEV; | 63 | return -ENODEV; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| @@ -67,8 +68,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 67 | 68 | ||
| 68 | pci_save_state(dev->pdev); | 69 | pci_save_state(dev->pdev); |
| 69 | 70 | ||
| 70 | i915_save_state(dev); | ||
| 71 | |||
| 72 | /* If KMS is active, we do the leavevt stuff here */ | 71 | /* If KMS is active, we do the leavevt stuff here */ |
| 73 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 72 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 74 | if (i915_gem_idle(dev)) | 73 | if (i915_gem_idle(dev)) |
| @@ -77,6 +76,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 77 | drm_irq_uninstall(dev); | 76 | drm_irq_uninstall(dev); |
| 78 | } | 77 | } |
| 79 | 78 | ||
| 79 | i915_save_state(dev); | ||
| 80 | |||
| 80 | intel_opregion_free(dev, 1); | 81 | intel_opregion_free(dev, 1); |
| 81 | 82 | ||
| 82 | if (state.event == PM_EVENT_SUSPEND) { | 83 | if (state.event == PM_EVENT_SUSPEND) { |
| @@ -115,6 +116,10 @@ static int i915_resume(struct drm_device *dev) | |||
| 115 | 116 | ||
| 116 | drm_irq_install(dev); | 117 | drm_irq_install(dev); |
| 117 | } | 118 | } |
| 119 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 120 | /* Resume the modeset for every activated CRTC */ | ||
| 121 | drm_helper_resume_force_mode(dev); | ||
| 122 | } | ||
| 118 | 123 | ||
| 119 | return ret; | 124 | return ret; |
| 120 | } | 125 | } |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a84f04e8439..d08752875885 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -133,6 +133,22 @@ struct sdvo_device_mapping { | |||
| 133 | u8 initialized; | 133 | u8 initialized; |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | struct drm_i915_error_state { | ||
| 137 | u32 eir; | ||
| 138 | u32 pgtbl_er; | ||
| 139 | u32 pipeastat; | ||
| 140 | u32 pipebstat; | ||
| 141 | u32 ipeir; | ||
| 142 | u32 ipehr; | ||
| 143 | u32 instdone; | ||
| 144 | u32 acthd; | ||
| 145 | u32 instpm; | ||
| 146 | u32 instps; | ||
| 147 | u32 instdone1; | ||
| 148 | u32 seqno; | ||
| 149 | struct timeval time; | ||
| 150 | }; | ||
| 151 | |||
| 136 | typedef struct drm_i915_private { | 152 | typedef struct drm_i915_private { |
| 137 | struct drm_device *dev; | 153 | struct drm_device *dev; |
| 138 | 154 | ||
| @@ -209,6 +225,11 @@ typedef struct drm_i915_private { | |||
| 209 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ | 225 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ |
| 210 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ | 226 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ |
| 211 | 227 | ||
| 228 | unsigned int fsb_freq, mem_freq; | ||
| 229 | |||
| 230 | spinlock_t error_lock; | ||
| 231 | struct drm_i915_error_state *first_error; | ||
| 232 | |||
| 212 | /* Register state */ | 233 | /* Register state */ |
| 213 | u8 saveLBB; | 234 | u8 saveLBB; |
| 214 | u32 saveDSPACNTR; | 235 | u32 saveDSPACNTR; |
| @@ -306,6 +327,17 @@ typedef struct drm_i915_private { | |||
| 306 | u32 saveCURBPOS; | 327 | u32 saveCURBPOS; |
| 307 | u32 saveCURBBASE; | 328 | u32 saveCURBBASE; |
| 308 | u32 saveCURSIZE; | 329 | u32 saveCURSIZE; |
| 330 | u32 saveDP_B; | ||
| 331 | u32 saveDP_C; | ||
| 332 | u32 saveDP_D; | ||
| 333 | u32 savePIPEA_GMCH_DATA_M; | ||
| 334 | u32 savePIPEB_GMCH_DATA_M; | ||
| 335 | u32 savePIPEA_GMCH_DATA_N; | ||
| 336 | u32 savePIPEB_GMCH_DATA_N; | ||
| 337 | u32 savePIPEA_DP_LINK_M; | ||
| 338 | u32 savePIPEB_DP_LINK_M; | ||
| 339 | u32 savePIPEA_DP_LINK_N; | ||
| 340 | u32 savePIPEB_DP_LINK_N; | ||
| 309 | 341 | ||
| 310 | struct { | 342 | struct { |
| 311 | struct drm_mm gtt_space; | 343 | struct drm_mm gtt_space; |
| @@ -457,9 +489,6 @@ struct drm_i915_gem_object { | |||
| 457 | */ | 489 | */ |
| 458 | int fence_reg; | 490 | int fence_reg; |
| 459 | 491 | ||
| 460 | /** Boolean whether this object has a valid gtt offset. */ | ||
| 461 | int gtt_bound; | ||
| 462 | |||
| 463 | /** How many users have pinned this object in GTT space */ | 492 | /** How many users have pinned this object in GTT space */ |
| 464 | int pin_count; | 493 | int pin_count; |
| 465 | 494 | ||
| @@ -644,6 +673,7 @@ void i915_gem_free_object(struct drm_gem_object *obj); | |||
| 644 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); | 673 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); |
| 645 | void i915_gem_object_unpin(struct drm_gem_object *obj); | 674 | void i915_gem_object_unpin(struct drm_gem_object *obj); |
| 646 | int i915_gem_object_unbind(struct drm_gem_object *obj); | 675 | int i915_gem_object_unbind(struct drm_gem_object *obj); |
| 676 | void i915_gem_release_mmap(struct drm_gem_object *obj); | ||
| 647 | void i915_gem_lastclose(struct drm_device *dev); | 677 | void i915_gem_lastclose(struct drm_device *dev); |
| 648 | uint32_t i915_get_gem_seqno(struct drm_device *dev); | 678 | uint32_t i915_get_gem_seqno(struct drm_device *dev); |
| 649 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); | 679 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); |
| @@ -857,7 +887,10 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
| 857 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ | 887 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ |
| 858 | IS_I915GM(dev))) | 888 | IS_I915GM(dev))) |
| 859 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | 889 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) |
| 890 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | ||
| 860 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) | 891 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) |
| 892 | /* dsparb controlled by hw only */ | ||
| 893 | #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | ||
| 861 | 894 | ||
| 862 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 895 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
| 863 | 896 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fd2b8bdffe3f..5bf420378b6d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1006,7 +1006,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 1006 | 1006 | ||
| 1007 | mutex_lock(&dev->struct_mutex); | 1007 | mutex_lock(&dev->struct_mutex); |
| 1008 | #if WATCH_BUF | 1008 | #if WATCH_BUF |
| 1009 | DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n", | 1009 | DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", |
| 1010 | obj, obj->size, read_domains, write_domain); | 1010 | obj, obj->size, read_domains, write_domain); |
| 1011 | #endif | 1011 | #endif |
| 1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { | 1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { |
| @@ -1050,7 +1050,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
| 1050 | } | 1050 | } |
| 1051 | 1051 | ||
| 1052 | #if WATCH_BUF | 1052 | #if WATCH_BUF |
| 1053 | DRM_INFO("%s: sw_finish %d (%p %d)\n", | 1053 | DRM_INFO("%s: sw_finish %d (%p %zd)\n", |
| 1054 | __func__, args->handle, obj, obj->size); | 1054 | __func__, args->handle, obj, obj->size); |
| 1055 | #endif | 1055 | #endif |
| 1056 | obj_priv = obj->driver_private; | 1056 | obj_priv = obj->driver_private; |
| @@ -1252,6 +1252,31 @@ out_free_list: | |||
| 1252 | return ret; | 1252 | return ret; |
| 1253 | } | 1253 | } |
| 1254 | 1254 | ||
| 1255 | /** | ||
| 1256 | * i915_gem_release_mmap - remove physical page mappings | ||
| 1257 | * @obj: obj in question | ||
| 1258 | * | ||
| 1259 | * Preserve the reservation of the mmaping with the DRM core code, but | ||
| 1260 | * relinquish ownership of the pages back to the system. | ||
| 1261 | * | ||
| 1262 | * It is vital that we remove the page mapping if we have mapped a tiled | ||
| 1263 | * object through the GTT and then lose the fence register due to | ||
| 1264 | * resource pressure. Similarly if the object has been moved out of the | ||
| 1265 | * aperture, than pages mapped into userspace must be revoked. Removing the | ||
| 1266 | * mapping will then trigger a page fault on the next user access, allowing | ||
| 1267 | * fixup by i915_gem_fault(). | ||
| 1268 | */ | ||
| 1269 | void | ||
| 1270 | i915_gem_release_mmap(struct drm_gem_object *obj) | ||
| 1271 | { | ||
| 1272 | struct drm_device *dev = obj->dev; | ||
| 1273 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 1274 | |||
| 1275 | if (dev->dev_mapping) | ||
| 1276 | unmap_mapping_range(dev->dev_mapping, | ||
| 1277 | obj_priv->mmap_offset, obj->size, 1); | ||
| 1278 | } | ||
| 1279 | |||
| 1255 | static void | 1280 | static void |
| 1256 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | 1281 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) |
| 1257 | { | 1282 | { |
| @@ -1861,7 +1886,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 1861 | { | 1886 | { |
| 1862 | struct drm_device *dev = obj->dev; | 1887 | struct drm_device *dev = obj->dev; |
| 1863 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1888 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1864 | loff_t offset; | ||
| 1865 | int ret = 0; | 1889 | int ret = 0; |
| 1866 | 1890 | ||
| 1867 | #if WATCH_BUF | 1891 | #if WATCH_BUF |
| @@ -1898,9 +1922,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 1898 | BUG_ON(obj_priv->active); | 1922 | BUG_ON(obj_priv->active); |
| 1899 | 1923 | ||
| 1900 | /* blow away mappings if mapped through GTT */ | 1924 | /* blow away mappings if mapped through GTT */ |
| 1901 | offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; | 1925 | i915_gem_release_mmap(obj); |
| 1902 | if (dev->dev_mapping) | ||
| 1903 | unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); | ||
| 1904 | 1926 | ||
| 1905 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 1927 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
| 1906 | i915_gem_clear_fence_reg(obj); | 1928 | i915_gem_clear_fence_reg(obj); |
| @@ -2222,7 +2244,6 @@ try_again: | |||
| 2222 | /* None available, try to steal one or wait for a user to finish */ | 2244 | /* None available, try to steal one or wait for a user to finish */ |
| 2223 | if (i == dev_priv->num_fence_regs) { | 2245 | if (i == dev_priv->num_fence_regs) { |
| 2224 | uint32_t seqno = dev_priv->mm.next_gem_seqno; | 2246 | uint32_t seqno = dev_priv->mm.next_gem_seqno; |
| 2225 | loff_t offset; | ||
| 2226 | 2247 | ||
| 2227 | if (avail == 0) | 2248 | if (avail == 0) |
| 2228 | return -ENOSPC; | 2249 | return -ENOSPC; |
| @@ -2274,10 +2295,7 @@ try_again: | |||
| 2274 | * Zap this virtual mapping so we can set up a fence again | 2295 | * Zap this virtual mapping so we can set up a fence again |
| 2275 | * for this object next time we need it. | 2296 | * for this object next time we need it. |
| 2276 | */ | 2297 | */ |
| 2277 | offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; | 2298 | i915_gem_release_mmap(reg->obj); |
| 2278 | if (dev->dev_mapping) | ||
| 2279 | unmap_mapping_range(dev->dev_mapping, offset, | ||
| 2280 | reg->obj->size, 1); | ||
| 2281 | old_obj_priv->fence_reg = I915_FENCE_REG_NONE; | 2299 | old_obj_priv->fence_reg = I915_FENCE_REG_NONE; |
| 2282 | } | 2300 | } |
| 2283 | 2301 | ||
| @@ -2423,7 +2441,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 2423 | } | 2441 | } |
| 2424 | 2442 | ||
| 2425 | #if WATCH_BUF | 2443 | #if WATCH_BUF |
| 2426 | DRM_INFO("Binding object of size %d at 0x%08x\n", | 2444 | DRM_INFO("Binding object of size %zd at 0x%08x\n", |
| 2427 | obj->size, obj_priv->gtt_offset); | 2445 | obj->size, obj_priv->gtt_offset); |
| 2428 | #endif | 2446 | #endif |
| 2429 | ret = i915_gem_object_get_pages(obj); | 2447 | ret = i915_gem_object_get_pages(obj); |
| @@ -4227,6 +4245,7 @@ i915_gem_lastclose(struct drm_device *dev) | |||
| 4227 | void | 4245 | void |
| 4228 | i915_gem_load(struct drm_device *dev) | 4246 | i915_gem_load(struct drm_device *dev) |
| 4229 | { | 4247 | { |
| 4248 | int i; | ||
| 4230 | drm_i915_private_t *dev_priv = dev->dev_private; | 4249 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 4231 | 4250 | ||
| 4232 | spin_lock_init(&dev_priv->mm.active_list_lock); | 4251 | spin_lock_init(&dev_priv->mm.active_list_lock); |
| @@ -4246,6 +4265,18 @@ i915_gem_load(struct drm_device *dev) | |||
| 4246 | else | 4265 | else |
| 4247 | dev_priv->num_fence_regs = 8; | 4266 | dev_priv->num_fence_regs = 8; |
| 4248 | 4267 | ||
| 4268 | /* Initialize fence registers to zero */ | ||
| 4269 | if (IS_I965G(dev)) { | ||
| 4270 | for (i = 0; i < 16; i++) | ||
| 4271 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); | ||
| 4272 | } else { | ||
| 4273 | for (i = 0; i < 8; i++) | ||
| 4274 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
| 4275 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
| 4276 | for (i = 0; i < 8; i++) | ||
| 4277 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); | ||
| 4278 | } | ||
| 4279 | |||
| 4249 | i915_gem_detect_bit_6_swizzle(dev); | 4280 | i915_gem_detect_bit_6_swizzle(dev); |
| 4250 | } | 4281 | } |
| 4251 | 4282 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 8d0b943e2c5a..e602614bd3f8 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
| @@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, | |||
| 87 | chunk_len = page_len - chunk; | 87 | chunk_len = page_len - chunk; |
| 88 | if (chunk_len > 128) | 88 | if (chunk_len > 128) |
| 89 | chunk_len = 128; | 89 | chunk_len = 128; |
| 90 | i915_gem_dump_page(obj_priv->page_list[page], | 90 | i915_gem_dump_page(obj_priv->pages[page], |
| 91 | chunk, chunk + chunk_len, | 91 | chunk, chunk + chunk_len, |
| 92 | obj_priv->gtt_offset + | 92 | obj_priv->gtt_offset + |
| 93 | page * PAGE_SIZE, | 93 | page * PAGE_SIZE, |
| @@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
| 143 | uint32_t *backing_map = NULL; | 143 | uint32_t *backing_map = NULL; |
| 144 | int bad_count = 0; | 144 | int bad_count = 0; |
| 145 | 145 | ||
| 146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n", | 146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n", |
| 147 | __func__, obj, obj_priv->gtt_offset, handle, | 147 | __func__, obj, obj_priv->gtt_offset, handle, |
| 148 | obj->size / 1024); | 148 | obj->size / 1024); |
| 149 | 149 | ||
| @@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
| 157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { | 157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { |
| 158 | int i; | 158 | int i; |
| 159 | 159 | ||
| 160 | backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0); | 160 | backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0); |
| 161 | 161 | ||
| 162 | if (backing_map == NULL) { | 162 | if (backing_map == NULL) { |
| 163 | DRM_ERROR("failed to map backing page\n"); | 163 | DRM_ERROR("failed to map backing page\n"); |
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index 28146e405e87..9a44bfcb8139 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c | |||
| @@ -75,11 +75,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 75 | case ACTIVE_LIST: | 75 | case ACTIVE_LIST: |
| 76 | seq_printf(m, "Active:\n"); | 76 | seq_printf(m, "Active:\n"); |
| 77 | lock = &dev_priv->mm.active_list_lock; | 77 | lock = &dev_priv->mm.active_list_lock; |
| 78 | spin_lock(lock); | ||
| 79 | head = &dev_priv->mm.active_list; | 78 | head = &dev_priv->mm.active_list; |
| 80 | break; | 79 | break; |
| 81 | case INACTIVE_LIST: | 80 | case INACTIVE_LIST: |
| 82 | seq_printf(m, "Inctive:\n"); | 81 | seq_printf(m, "Inactive:\n"); |
| 83 | head = &dev_priv->mm.inactive_list; | 82 | head = &dev_priv->mm.inactive_list; |
| 84 | break; | 83 | break; |
| 85 | case FLUSHING_LIST: | 84 | case FLUSHING_LIST: |
| @@ -91,6 +90,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 91 | return 0; | 90 | return 0; |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 93 | if (lock) | ||
| 94 | spin_lock(lock); | ||
| 94 | list_for_each_entry(obj_priv, head, list) | 95 | list_for_each_entry(obj_priv, head, list) |
| 95 | { | 96 | { |
| 96 | struct drm_gem_object *obj = obj_priv->obj; | 97 | struct drm_gem_object *obj = obj_priv->obj; |
| @@ -104,7 +105,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 104 | if (obj->name) | 105 | if (obj->name) |
| 105 | seq_printf(m, " (name: %d)", obj->name); | 106 | seq_printf(m, " (name: %d)", obj->name); |
| 106 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 107 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
| 107 | seq_printf(m, " (fence: %d)\n", obj_priv->fence_reg); | 108 | seq_printf(m, " (fence: %d)", obj_priv->fence_reg); |
| 109 | if (obj_priv->gtt_space != NULL) | ||
| 110 | seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset); | ||
| 111 | |||
| 108 | seq_printf(m, "\n"); | 112 | seq_printf(m, "\n"); |
| 109 | } | 113 | } |
| 110 | 114 | ||
| @@ -323,6 +327,39 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) | |||
| 323 | return 0; | 327 | return 0; |
| 324 | } | 328 | } |
| 325 | 329 | ||
| 330 | static int i915_error_state(struct seq_file *m, void *unused) | ||
| 331 | { | ||
| 332 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 333 | struct drm_device *dev = node->minor->dev; | ||
| 334 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 335 | struct drm_i915_error_state *error; | ||
| 336 | unsigned long flags; | ||
| 337 | |||
| 338 | spin_lock_irqsave(&dev_priv->error_lock, flags); | ||
| 339 | if (!dev_priv->first_error) { | ||
| 340 | seq_printf(m, "no error state collected\n"); | ||
| 341 | goto out; | ||
| 342 | } | ||
| 343 | |||
| 344 | error = dev_priv->first_error; | ||
| 345 | |||
| 346 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | ||
| 347 | seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er); | ||
| 348 | seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); | ||
| 349 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir); | ||
| 350 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); | ||
| 351 | seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); | ||
| 352 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); | ||
| 353 | if (IS_I965G(dev)) { | ||
| 354 | seq_printf(m, " INSTPS: 0x%08x\n", error->instps); | ||
| 355 | seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); | ||
| 356 | } | ||
| 357 | |||
| 358 | out: | ||
| 359 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | ||
| 360 | |||
| 361 | return 0; | ||
| 362 | } | ||
| 326 | 363 | ||
| 327 | static struct drm_info_list i915_gem_debugfs_list[] = { | 364 | static struct drm_info_list i915_gem_debugfs_list[] = { |
| 328 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, | 365 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, |
| @@ -336,6 +373,7 @@ static struct drm_info_list i915_gem_debugfs_list[] = { | |||
| 336 | {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, | 373 | {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, |
| 337 | {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, | 374 | {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, |
| 338 | {"i915_batchbuffers", i915_batchbuffer_info, 0}, | 375 | {"i915_batchbuffers", i915_batchbuffer_info, 0}, |
| 376 | {"i915_error_state", i915_error_state, 0}, | ||
| 339 | }; | 377 | }; |
| 340 | #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) | 378 | #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) |
| 341 | 379 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 5c1ceec49f5b..a2d527b22ec4 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev) | |||
| 114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; | 114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; |
| 115 | 115 | ||
| 116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ | 116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ |
| 117 | #ifdef CONFIG_PNP | ||
| 117 | if (mchbar_addr && | 118 | if (mchbar_addr && |
| 118 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { | 119 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { |
| 119 | ret = 0; | 120 | ret = 0; |
| 120 | goto out_put; | 121 | goto out_put; |
| 121 | } | 122 | } |
| 123 | #endif | ||
| 122 | 124 | ||
| 123 | /* Get some space for it */ | 125 | /* Get some space for it */ |
| 124 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, | 126 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, |
| @@ -519,6 +521,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 519 | goto err; | 521 | goto err; |
| 520 | } | 522 | } |
| 521 | 523 | ||
| 524 | /* If we've changed tiling, GTT-mappings of the object | ||
| 525 | * need to re-fault to ensure that the correct fence register | ||
| 526 | * setup is in place. | ||
| 527 | */ | ||
| 528 | i915_gem_release_mmap(obj); | ||
| 529 | |||
| 522 | obj_priv->tiling_mode = args->tiling_mode; | 530 | obj_priv->tiling_mode = args->tiling_mode; |
| 523 | obj_priv->stride = args->stride; | 531 | obj_priv->stride = args->stride; |
| 524 | } | 532 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b86b7b7130c6..7ba23a69a0c0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | * | 26 | * |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | #include <linux/sysrq.h> | ||
| 29 | #include "drmP.h" | 30 | #include "drmP.h" |
| 30 | #include "drm.h" | 31 | #include "drm.h" |
| 31 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
| @@ -41,9 +42,10 @@ | |||
| 41 | * we leave them always unmasked in IMR and then control enabling them through | 42 | * we leave them always unmasked in IMR and then control enabling them through |
| 42 | * PIPESTAT alone. | 43 | * PIPESTAT alone. |
| 43 | */ | 44 | */ |
| 44 | #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ | 45 | #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ |
| 45 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ | 46 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ |
| 46 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) | 47 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ |
| 48 | I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | ||
| 47 | 49 | ||
| 48 | /** Interrupts that we mask and unmask at runtime. */ | 50 | /** Interrupts that we mask and unmask at runtime. */ |
| 49 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) | 51 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) |
| @@ -232,7 +234,17 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
| 232 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | 234 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, |
| 233 | hotplug_work); | 235 | hotplug_work); |
| 234 | struct drm_device *dev = dev_priv->dev; | 236 | struct drm_device *dev = dev_priv->dev; |
| 235 | 237 | struct drm_mode_config *mode_config = &dev->mode_config; | |
| 238 | struct drm_connector *connector; | ||
| 239 | |||
| 240 | if (mode_config->num_connector) { | ||
| 241 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 242 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 243 | |||
| 244 | if (intel_output->hot_plug) | ||
| 245 | (*intel_output->hot_plug) (intel_output); | ||
| 246 | } | ||
| 247 | } | ||
| 236 | /* Just fire off a uevent and let userspace tell us what to do */ | 248 | /* Just fire off a uevent and let userspace tell us what to do */ |
| 237 | drm_sysfs_hotplug_event(dev); | 249 | drm_sysfs_hotplug_event(dev); |
| 238 | } | 250 | } |
| @@ -278,6 +290,47 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) | |||
| 278 | return ret; | 290 | return ret; |
| 279 | } | 291 | } |
| 280 | 292 | ||
| 293 | static void i915_capture_error_state(struct drm_device *dev) | ||
| 294 | { | ||
| 295 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 296 | struct drm_i915_error_state *error; | ||
| 297 | unsigned long flags; | ||
| 298 | |||
| 299 | spin_lock_irqsave(&dev_priv->error_lock, flags); | ||
| 300 | if (dev_priv->first_error) | ||
| 301 | goto out; | ||
| 302 | |||
| 303 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | ||
| 304 | if (!error) { | ||
| 305 | DRM_DEBUG("out ot memory, not capturing error state\n"); | ||
| 306 | goto out; | ||
| 307 | } | ||
| 308 | |||
| 309 | error->eir = I915_READ(EIR); | ||
| 310 | error->pgtbl_er = I915_READ(PGTBL_ER); | ||
| 311 | error->pipeastat = I915_READ(PIPEASTAT); | ||
| 312 | error->pipebstat = I915_READ(PIPEBSTAT); | ||
| 313 | error->instpm = I915_READ(INSTPM); | ||
| 314 | if (!IS_I965G(dev)) { | ||
| 315 | error->ipeir = I915_READ(IPEIR); | ||
| 316 | error->ipehr = I915_READ(IPEHR); | ||
| 317 | error->instdone = I915_READ(INSTDONE); | ||
| 318 | error->acthd = I915_READ(ACTHD); | ||
| 319 | } else { | ||
| 320 | error->ipeir = I915_READ(IPEIR_I965); | ||
| 321 | error->ipehr = I915_READ(IPEHR_I965); | ||
| 322 | error->instdone = I915_READ(INSTDONE_I965); | ||
| 323 | error->instps = I915_READ(INSTPS); | ||
| 324 | error->instdone1 = I915_READ(INSTDONE1); | ||
| 325 | error->acthd = I915_READ(ACTHD_I965); | ||
| 326 | } | ||
| 327 | |||
| 328 | dev_priv->first_error = error; | ||
| 329 | |||
| 330 | out: | ||
| 331 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | ||
| 332 | } | ||
| 333 | |||
| 281 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 334 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
| 282 | { | 335 | { |
| 283 | struct drm_device *dev = (struct drm_device *) arg; | 336 | struct drm_device *dev = (struct drm_device *) arg; |
| @@ -323,11 +376,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 323 | * Clear the PIPE(A|B)STAT regs before the IIR | 376 | * Clear the PIPE(A|B)STAT regs before the IIR |
| 324 | */ | 377 | */ |
| 325 | if (pipea_stats & 0x8000ffff) { | 378 | if (pipea_stats & 0x8000ffff) { |
| 379 | if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) | ||
| 380 | DRM_DEBUG("pipe a underrun\n"); | ||
| 326 | I915_WRITE(PIPEASTAT, pipea_stats); | 381 | I915_WRITE(PIPEASTAT, pipea_stats); |
| 327 | irq_received = 1; | 382 | irq_received = 1; |
| 328 | } | 383 | } |
| 329 | 384 | ||
| 330 | if (pipeb_stats & 0x8000ffff) { | 385 | if (pipeb_stats & 0x8000ffff) { |
| 386 | if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) | ||
| 387 | DRM_DEBUG("pipe b underrun\n"); | ||
| 331 | I915_WRITE(PIPEBSTAT, pipeb_stats); | 388 | I915_WRITE(PIPEBSTAT, pipeb_stats); |
| 332 | irq_received = 1; | 389 | irq_received = 1; |
| 333 | } | 390 | } |
| @@ -352,6 +409,80 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 352 | I915_READ(PORT_HOTPLUG_STAT); | 409 | I915_READ(PORT_HOTPLUG_STAT); |
| 353 | } | 410 | } |
| 354 | 411 | ||
| 412 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) { | ||
| 413 | u32 eir = I915_READ(EIR); | ||
| 414 | |||
| 415 | i915_capture_error_state(dev); | ||
| 416 | |||
| 417 | printk(KERN_ERR "render error detected, EIR: 0x%08x\n", | ||
| 418 | eir); | ||
| 419 | if (eir & I915_ERROR_PAGE_TABLE) { | ||
| 420 | u32 pgtbl_err = I915_READ(PGTBL_ER); | ||
| 421 | printk(KERN_ERR "page table error\n"); | ||
| 422 | printk(KERN_ERR " PGTBL_ER: 0x%08x\n", | ||
| 423 | pgtbl_err); | ||
| 424 | I915_WRITE(PGTBL_ER, pgtbl_err); | ||
| 425 | (void)I915_READ(PGTBL_ER); | ||
| 426 | } | ||
| 427 | if (eir & I915_ERROR_MEMORY_REFRESH) { | ||
| 428 | printk(KERN_ERR "memory refresh error\n"); | ||
| 429 | printk(KERN_ERR "PIPEASTAT: 0x%08x\n", | ||
| 430 | pipea_stats); | ||
| 431 | printk(KERN_ERR "PIPEBSTAT: 0x%08x\n", | ||
| 432 | pipeb_stats); | ||
| 433 | /* pipestat has already been acked */ | ||
| 434 | } | ||
| 435 | if (eir & I915_ERROR_INSTRUCTION) { | ||
| 436 | printk(KERN_ERR "instruction error\n"); | ||
| 437 | printk(KERN_ERR " INSTPM: 0x%08x\n", | ||
| 438 | I915_READ(INSTPM)); | ||
| 439 | if (!IS_I965G(dev)) { | ||
| 440 | u32 ipeir = I915_READ(IPEIR); | ||
| 441 | |||
| 442 | printk(KERN_ERR " IPEIR: 0x%08x\n", | ||
| 443 | I915_READ(IPEIR)); | ||
| 444 | printk(KERN_ERR " IPEHR: 0x%08x\n", | ||
| 445 | I915_READ(IPEHR)); | ||
| 446 | printk(KERN_ERR " INSTDONE: 0x%08x\n", | ||
| 447 | I915_READ(INSTDONE)); | ||
| 448 | printk(KERN_ERR " ACTHD: 0x%08x\n", | ||
| 449 | I915_READ(ACTHD)); | ||
| 450 | I915_WRITE(IPEIR, ipeir); | ||
| 451 | (void)I915_READ(IPEIR); | ||
| 452 | } else { | ||
| 453 | u32 ipeir = I915_READ(IPEIR_I965); | ||
| 454 | |||
| 455 | printk(KERN_ERR " IPEIR: 0x%08x\n", | ||
| 456 | I915_READ(IPEIR_I965)); | ||
| 457 | printk(KERN_ERR " IPEHR: 0x%08x\n", | ||
| 458 | I915_READ(IPEHR_I965)); | ||
| 459 | printk(KERN_ERR " INSTDONE: 0x%08x\n", | ||
| 460 | I915_READ(INSTDONE_I965)); | ||
| 461 | printk(KERN_ERR " INSTPS: 0x%08x\n", | ||
| 462 | I915_READ(INSTPS)); | ||
| 463 | printk(KERN_ERR " INSTDONE1: 0x%08x\n", | ||
| 464 | I915_READ(INSTDONE1)); | ||
| 465 | printk(KERN_ERR " ACTHD: 0x%08x\n", | ||
| 466 | I915_READ(ACTHD_I965)); | ||
| 467 | I915_WRITE(IPEIR_I965, ipeir); | ||
| 468 | (void)I915_READ(IPEIR_I965); | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | I915_WRITE(EIR, eir); | ||
| 473 | (void)I915_READ(EIR); | ||
| 474 | eir = I915_READ(EIR); | ||
| 475 | if (eir) { | ||
| 476 | /* | ||
| 477 | * some errors might have become stuck, | ||
| 478 | * mask them. | ||
| 479 | */ | ||
| 480 | DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir); | ||
| 481 | I915_WRITE(EMR, I915_READ(EMR) | eir); | ||
| 482 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 355 | I915_WRITE(IIR, iir); | 486 | I915_WRITE(IIR, iir); |
| 356 | new_iir = I915_READ(IIR); /* Flush posted writes */ | 487 | new_iir = I915_READ(IIR); /* Flush posted writes */ |
| 357 | 488 | ||
| @@ -722,6 +853,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 722 | { | 853 | { |
| 723 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 854 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 724 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; | 855 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; |
| 856 | u32 error_mask; | ||
| 725 | 857 | ||
| 726 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); | 858 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); |
| 727 | 859 | ||
| @@ -758,6 +890,21 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 758 | i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); | 890 | i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); |
| 759 | } | 891 | } |
| 760 | 892 | ||
| 893 | /* | ||
| 894 | * Enable some error detection, note the instruction error mask | ||
| 895 | * bit is reserved, so we leave it masked. | ||
| 896 | */ | ||
| 897 | if (IS_G4X(dev)) { | ||
| 898 | error_mask = ~(GM45_ERROR_PAGE_TABLE | | ||
| 899 | GM45_ERROR_MEM_PRIV | | ||
| 900 | GM45_ERROR_CP_PRIV | | ||
| 901 | I915_ERROR_MEMORY_REFRESH); | ||
| 902 | } else { | ||
| 903 | error_mask = ~(I915_ERROR_PAGE_TABLE | | ||
| 904 | I915_ERROR_MEMORY_REFRESH); | ||
| 905 | } | ||
| 906 | I915_WRITE(EMR, error_mask); | ||
| 907 | |||
| 761 | /* Disable pipe interrupt enables, clear pending pipe status */ | 908 | /* Disable pipe interrupt enables, clear pending pipe status */ |
| 762 | I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); | 909 | I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); |
| 763 | I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); | 910 | I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); |
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index dc425e74a268..e4b4e8898e39 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c | |||
| @@ -419,7 +419,7 @@ void intel_opregion_free(struct drm_device *dev, int suspend) | |||
| 419 | return; | 419 | return; |
| 420 | 420 | ||
| 421 | if (!suspend) | 421 | if (!suspend) |
| 422 | acpi_video_exit(); | 422 | acpi_video_unregister(); |
| 423 | 423 | ||
| 424 | opregion->acpi->drdy = 0; | 424 | opregion->acpi->drdy = 0; |
| 425 | 425 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f6237a0b1133..6c0858484094 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -206,6 +206,7 @@ | |||
| 206 | /* | 206 | /* |
| 207 | * Instruction and interrupt control regs | 207 | * Instruction and interrupt control regs |
| 208 | */ | 208 | */ |
| 209 | #define PGTBL_ER 0x02024 | ||
| 209 | #define PRB0_TAIL 0x02030 | 210 | #define PRB0_TAIL 0x02030 |
| 210 | #define PRB0_HEAD 0x02034 | 211 | #define PRB0_HEAD 0x02034 |
| 211 | #define PRB0_START 0x02038 | 212 | #define PRB0_START 0x02038 |
| @@ -226,11 +227,18 @@ | |||
| 226 | #define PRB1_HEAD 0x02044 /* 915+ only */ | 227 | #define PRB1_HEAD 0x02044 /* 915+ only */ |
| 227 | #define PRB1_START 0x02048 /* 915+ only */ | 228 | #define PRB1_START 0x02048 /* 915+ only */ |
| 228 | #define PRB1_CTL 0x0204c /* 915+ only */ | 229 | #define PRB1_CTL 0x0204c /* 915+ only */ |
| 230 | #define IPEIR_I965 0x02064 | ||
| 231 | #define IPEHR_I965 0x02068 | ||
| 232 | #define INSTDONE_I965 0x0206c | ||
| 233 | #define INSTPS 0x02070 /* 965+ only */ | ||
| 234 | #define INSTDONE1 0x0207c /* 965+ only */ | ||
| 229 | #define ACTHD_I965 0x02074 | 235 | #define ACTHD_I965 0x02074 |
| 230 | #define HWS_PGA 0x02080 | 236 | #define HWS_PGA 0x02080 |
| 231 | #define HWS_ADDRESS_MASK 0xfffff000 | 237 | #define HWS_ADDRESS_MASK 0xfffff000 |
| 232 | #define HWS_START_ADDRESS_SHIFT 4 | 238 | #define HWS_START_ADDRESS_SHIFT 4 |
| 233 | #define IPEIR 0x02088 | 239 | #define IPEIR 0x02088 |
| 240 | #define IPEHR 0x0208c | ||
| 241 | #define INSTDONE 0x02090 | ||
| 234 | #define NOPID 0x02094 | 242 | #define NOPID 0x02094 |
| 235 | #define HWSTAM 0x02098 | 243 | #define HWSTAM 0x02098 |
| 236 | #define SCPD0 0x0209c /* 915+ only */ | 244 | #define SCPD0 0x0209c /* 915+ only */ |
| @@ -258,10 +266,22 @@ | |||
| 258 | #define EIR 0x020b0 | 266 | #define EIR 0x020b0 |
| 259 | #define EMR 0x020b4 | 267 | #define EMR 0x020b4 |
| 260 | #define ESR 0x020b8 | 268 | #define ESR 0x020b8 |
| 269 | #define GM45_ERROR_PAGE_TABLE (1<<5) | ||
| 270 | #define GM45_ERROR_MEM_PRIV (1<<4) | ||
| 271 | #define I915_ERROR_PAGE_TABLE (1<<4) | ||
| 272 | #define GM45_ERROR_CP_PRIV (1<<3) | ||
| 273 | #define I915_ERROR_MEMORY_REFRESH (1<<1) | ||
| 274 | #define I915_ERROR_INSTRUCTION (1<<0) | ||
| 261 | #define INSTPM 0x020c0 | 275 | #define INSTPM 0x020c0 |
| 262 | #define ACTHD 0x020c8 | 276 | #define ACTHD 0x020c8 |
| 263 | #define FW_BLC 0x020d8 | 277 | #define FW_BLC 0x020d8 |
| 278 | #define FW_BLC2 0x020dc | ||
| 264 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ | 279 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ |
| 280 | #define FW_BLC_SELF_EN (1<<15) | ||
| 281 | #define MM_BURST_LENGTH 0x00700000 | ||
| 282 | #define MM_FIFO_WATERMARK 0x0001F000 | ||
| 283 | #define LM_BURST_LENGTH 0x00000700 | ||
| 284 | #define LM_FIFO_WATERMARK 0x0000001F | ||
| 265 | #define MI_ARB_STATE 0x020e4 /* 915+ only */ | 285 | #define MI_ARB_STATE 0x020e4 /* 915+ only */ |
| 266 | #define CACHE_MODE_0 0x02120 /* 915+ only */ | 286 | #define CACHE_MODE_0 0x02120 /* 915+ only */ |
| 267 | #define CM0_MASK_SHIFT 16 | 287 | #define CM0_MASK_SHIFT 16 |
| @@ -569,6 +589,23 @@ | |||
| 569 | #define C0DRB3 0x10206 | 589 | #define C0DRB3 0x10206 |
| 570 | #define C1DRB3 0x10606 | 590 | #define C1DRB3 0x10606 |
| 571 | 591 | ||
| 592 | /* Clocking configuration register */ | ||
| 593 | #define CLKCFG 0x10c00 | ||
| 594 | #define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ | ||
| 595 | #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ | ||
| 596 | #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ | ||
| 597 | #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ | ||
| 598 | #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ | ||
| 599 | #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ | ||
| 600 | /* Note, below two are guess */ | ||
| 601 | #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ | ||
| 602 | #define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ | ||
| 603 | #define CLKCFG_FSB_MASK (7 << 0) | ||
| 604 | #define CLKCFG_MEM_533 (1 << 4) | ||
| 605 | #define CLKCFG_MEM_667 (2 << 4) | ||
| 606 | #define CLKCFG_MEM_800 (3 << 4) | ||
| 607 | #define CLKCFG_MEM_MASK (7 << 4) | ||
| 608 | |||
| 572 | /** GM965 GM45 render standby register */ | 609 | /** GM965 GM45 render standby register */ |
| 573 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 610 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
| 574 | 611 | ||
| @@ -834,9 +871,25 @@ | |||
| 834 | #define HORIZ_INTERP_MASK (3 << 6) | 871 | #define HORIZ_INTERP_MASK (3 << 6) |
| 835 | #define HORIZ_AUTO_SCALE (1 << 5) | 872 | #define HORIZ_AUTO_SCALE (1 << 5) |
| 836 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) | 873 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) |
| 874 | #define PFIT_FILTER_FUZZY (0 << 24) | ||
| 875 | #define PFIT_SCALING_AUTO (0 << 26) | ||
| 876 | #define PFIT_SCALING_PROGRAMMED (1 << 26) | ||
| 877 | #define PFIT_SCALING_PILLAR (2 << 26) | ||
| 878 | #define PFIT_SCALING_LETTER (3 << 26) | ||
| 837 | #define PFIT_PGM_RATIOS 0x61234 | 879 | #define PFIT_PGM_RATIOS 0x61234 |
| 838 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | 880 | #define PFIT_VERT_SCALE_MASK 0xfff00000 |
| 839 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | 881 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 |
| 882 | /* Pre-965 */ | ||
| 883 | #define PFIT_VERT_SCALE_SHIFT 20 | ||
| 884 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | ||
| 885 | #define PFIT_HORIZ_SCALE_SHIFT 4 | ||
| 886 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | ||
| 887 | /* 965+ */ | ||
| 888 | #define PFIT_VERT_SCALE_SHIFT_965 16 | ||
| 889 | #define PFIT_VERT_SCALE_MASK_965 0x1fff0000 | ||
| 890 | #define PFIT_HORIZ_SCALE_SHIFT_965 0 | ||
| 891 | #define PFIT_HORIZ_SCALE_MASK_965 0x00001fff | ||
| 892 | |||
| 840 | #define PFIT_AUTO_RATIOS 0x61238 | 893 | #define PFIT_AUTO_RATIOS 0x61238 |
| 841 | 894 | ||
| 842 | /* Backlight control */ | 895 | /* Backlight control */ |
| @@ -1552,6 +1605,34 @@ | |||
| 1552 | #define DSPARB_CSTART_SHIFT 7 | 1605 | #define DSPARB_CSTART_SHIFT 7 |
| 1553 | #define DSPARB_BSTART_MASK (0x7f) | 1606 | #define DSPARB_BSTART_MASK (0x7f) |
| 1554 | #define DSPARB_BSTART_SHIFT 0 | 1607 | #define DSPARB_BSTART_SHIFT 0 |
| 1608 | #define DSPARB_BEND_SHIFT 9 /* on 855 */ | ||
| 1609 | #define DSPARB_AEND_SHIFT 0 | ||
| 1610 | |||
| 1611 | #define DSPFW1 0x70034 | ||
| 1612 | #define DSPFW2 0x70038 | ||
| 1613 | #define DSPFW3 0x7003c | ||
| 1614 | #define IGD_SELF_REFRESH_EN (1<<30) | ||
| 1615 | |||
| 1616 | /* FIFO watermark sizes etc */ | ||
| 1617 | #define I915_FIFO_LINE_SIZE 64 | ||
| 1618 | #define I830_FIFO_LINE_SIZE 32 | ||
| 1619 | #define I945_FIFO_SIZE 127 /* 945 & 965 */ | ||
| 1620 | #define I915_FIFO_SIZE 95 | ||
| 1621 | #define I855GM_FIFO_SIZE 255 | ||
| 1622 | #define I830_FIFO_SIZE 95 | ||
| 1623 | #define I915_MAX_WM 0x3f | ||
| 1624 | |||
| 1625 | #define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ | ||
| 1626 | #define IGD_FIFO_LINE_SIZE 64 | ||
| 1627 | #define IGD_MAX_WM 0x1ff | ||
| 1628 | #define IGD_DFT_WM 0x3f | ||
| 1629 | #define IGD_DFT_HPLLOFF_WM 0 | ||
| 1630 | #define IGD_GUARD_WM 10 | ||
| 1631 | #define IGD_CURSOR_FIFO 64 | ||
| 1632 | #define IGD_CURSOR_MAX_WM 0x3f | ||
| 1633 | #define IGD_CURSOR_DFT_WM 0 | ||
| 1634 | #define IGD_CURSOR_GUARD_WM 5 | ||
| 1635 | |||
| 1555 | /* | 1636 | /* |
| 1556 | * The two pipe frame counter registers are not synchronized, so | 1637 | * The two pipe frame counter registers are not synchronized, so |
| 1557 | * reading a stable value is somewhat tricky. The following code | 1638 | * reading a stable value is somewhat tricky. The following code |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a98e2831ed31..9e1d16e5c3ea 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -222,23 +222,12 @@ static void i915_restore_vga(struct drm_device *dev) | |||
| 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); | 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | int i915_save_state(struct drm_device *dev) | 225 | static void i915_save_modeset_reg(struct drm_device *dev) |
| 226 | { | 226 | { |
| 227 | struct drm_i915_private *dev_priv = dev->dev_private; | 227 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 228 | int i; | ||
| 229 | |||
| 230 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | ||
| 231 | |||
| 232 | /* Render Standby */ | ||
| 233 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 234 | dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); | ||
| 235 | |||
| 236 | /* Hardware status page */ | ||
| 237 | dev_priv->saveHWS = I915_READ(HWS_PGA); | ||
| 238 | |||
| 239 | /* Display arbitration control */ | ||
| 240 | dev_priv->saveDSPARB = I915_READ(DSPARB); | ||
| 241 | 228 | ||
| 229 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 230 | return; | ||
| 242 | /* Pipe & plane A info */ | 231 | /* Pipe & plane A info */ |
| 243 | dev_priv->savePIPEACONF = I915_READ(PIPEACONF); | 232 | dev_priv->savePIPEACONF = I915_READ(PIPEACONF); |
| 244 | dev_priv->savePIPEASRC = I915_READ(PIPEASRC); | 233 | dev_priv->savePIPEASRC = I915_READ(PIPEASRC); |
| @@ -294,7 +283,122 @@ int i915_save_state(struct drm_device *dev) | |||
| 294 | } | 283 | } |
| 295 | i915_save_palette(dev, PIPE_B); | 284 | i915_save_palette(dev, PIPE_B); |
| 296 | dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); | 285 | dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); |
| 286 | return; | ||
| 287 | } | ||
| 288 | static void i915_restore_modeset_reg(struct drm_device *dev) | ||
| 289 | { | ||
| 290 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 291 | |||
| 292 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 293 | return; | ||
| 294 | |||
| 295 | /* Pipe & plane A info */ | ||
| 296 | /* Prime the clock */ | ||
| 297 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | ||
| 298 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & | ||
| 299 | ~DPLL_VCO_ENABLE); | ||
| 300 | DRM_UDELAY(150); | ||
| 301 | } | ||
| 302 | I915_WRITE(FPA0, dev_priv->saveFPA0); | ||
| 303 | I915_WRITE(FPA1, dev_priv->saveFPA1); | ||
| 304 | /* Actually enable it */ | ||
| 305 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); | ||
| 306 | DRM_UDELAY(150); | ||
| 307 | if (IS_I965G(dev)) | ||
| 308 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | ||
| 309 | DRM_UDELAY(150); | ||
| 310 | |||
| 311 | /* Restore mode */ | ||
| 312 | I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); | ||
| 313 | I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); | ||
| 314 | I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); | ||
| 315 | I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); | ||
| 316 | I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); | ||
| 317 | I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); | ||
| 318 | I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); | ||
| 319 | |||
| 320 | /* Restore plane info */ | ||
| 321 | I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); | ||
| 322 | I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); | ||
| 323 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | ||
| 324 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | ||
| 325 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | ||
| 326 | if (IS_I965G(dev)) { | ||
| 327 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | ||
| 328 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | ||
| 329 | } | ||
| 330 | |||
| 331 | I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); | ||
| 332 | |||
| 333 | i915_restore_palette(dev, PIPE_A); | ||
| 334 | /* Enable the plane */ | ||
| 335 | I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); | ||
| 336 | I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); | ||
| 337 | |||
| 338 | /* Pipe & plane B info */ | ||
| 339 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { | ||
| 340 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & | ||
| 341 | ~DPLL_VCO_ENABLE); | ||
| 342 | DRM_UDELAY(150); | ||
| 343 | } | ||
| 344 | I915_WRITE(FPB0, dev_priv->saveFPB0); | ||
| 345 | I915_WRITE(FPB1, dev_priv->saveFPB1); | ||
| 346 | /* Actually enable it */ | ||
| 347 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); | ||
| 348 | DRM_UDELAY(150); | ||
| 349 | if (IS_I965G(dev)) | ||
| 350 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | ||
| 351 | DRM_UDELAY(150); | ||
| 352 | |||
| 353 | /* Restore mode */ | ||
| 354 | I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); | ||
| 355 | I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); | ||
| 356 | I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); | ||
| 357 | I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); | ||
| 358 | I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); | ||
| 359 | I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); | ||
| 360 | I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); | ||
| 361 | |||
| 362 | /* Restore plane info */ | ||
| 363 | I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); | ||
| 364 | I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); | ||
| 365 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | ||
| 366 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | ||
| 367 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | ||
| 368 | if (IS_I965G(dev)) { | ||
| 369 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | ||
| 370 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | ||
| 371 | } | ||
| 372 | |||
| 373 | I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); | ||
| 374 | |||
| 375 | i915_restore_palette(dev, PIPE_B); | ||
| 376 | /* Enable the plane */ | ||
| 377 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | ||
| 378 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | ||
| 297 | 379 | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | int i915_save_state(struct drm_device *dev) | ||
| 383 | { | ||
| 384 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 385 | int i; | ||
| 386 | |||
| 387 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | ||
| 388 | |||
| 389 | /* Render Standby */ | ||
| 390 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 391 | dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); | ||
| 392 | |||
| 393 | /* Hardware status page */ | ||
| 394 | dev_priv->saveHWS = I915_READ(HWS_PGA); | ||
| 395 | |||
| 396 | /* Display arbitration control */ | ||
| 397 | dev_priv->saveDSPARB = I915_READ(DSPARB); | ||
| 398 | |||
| 399 | /* This is only meaningful in non-KMS mode */ | ||
| 400 | /* Don't save them in KMS mode */ | ||
| 401 | i915_save_modeset_reg(dev); | ||
| 298 | /* Cursor state */ | 402 | /* Cursor state */ |
| 299 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | 403 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); |
| 300 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | 404 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); |
| @@ -322,6 +426,20 @@ int i915_save_state(struct drm_device *dev) | |||
| 322 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); | 426 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); |
| 323 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); | 427 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); |
| 324 | 428 | ||
| 429 | /* Display Port state */ | ||
| 430 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
| 431 | dev_priv->saveDP_B = I915_READ(DP_B); | ||
| 432 | dev_priv->saveDP_C = I915_READ(DP_C); | ||
| 433 | dev_priv->saveDP_D = I915_READ(DP_D); | ||
| 434 | dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M); | ||
| 435 | dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M); | ||
| 436 | dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N); | ||
| 437 | dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N); | ||
| 438 | dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M); | ||
| 439 | dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M); | ||
| 440 | dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N); | ||
| 441 | dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N); | ||
| 442 | } | ||
| 325 | /* FIXME: save TV & SDVO state */ | 443 | /* FIXME: save TV & SDVO state */ |
| 326 | 444 | ||
| 327 | /* FBC state */ | 445 | /* FBC state */ |
| @@ -404,92 +522,21 @@ int i915_restore_state(struct drm_device *dev) | |||
| 404 | for (i = 0; i < 8; i++) | 522 | for (i = 0; i < 8; i++) |
| 405 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); | 523 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); |
| 406 | } | 524 | } |
| 407 | 525 | ||
| 408 | /* Pipe & plane A info */ | 526 | /* Display port ratios (must be done before clock is set) */ |
| 409 | /* Prime the clock */ | 527 | if (SUPPORTS_INTEGRATED_DP(dev)) { |
| 410 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | 528 | I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); |
| 411 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & | 529 | I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); |
| 412 | ~DPLL_VCO_ENABLE); | 530 | I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); |
| 413 | DRM_UDELAY(150); | 531 | I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); |
| 532 | I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); | ||
| 533 | I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); | ||
| 534 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); | ||
| 535 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); | ||
| 414 | } | 536 | } |
| 415 | I915_WRITE(FPA0, dev_priv->saveFPA0); | 537 | /* This is only meaningful in non-KMS mode */ |
| 416 | I915_WRITE(FPA1, dev_priv->saveFPA1); | 538 | /* Don't restore them in KMS mode */ |
| 417 | /* Actually enable it */ | 539 | i915_restore_modeset_reg(dev); |
| 418 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); | ||
| 419 | DRM_UDELAY(150); | ||
| 420 | if (IS_I965G(dev)) | ||
| 421 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | ||
| 422 | DRM_UDELAY(150); | ||
| 423 | |||
| 424 | /* Restore mode */ | ||
| 425 | I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); | ||
| 426 | I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); | ||
| 427 | I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); | ||
| 428 | I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); | ||
| 429 | I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); | ||
| 430 | I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); | ||
| 431 | I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); | ||
| 432 | |||
| 433 | /* Restore plane info */ | ||
| 434 | I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); | ||
| 435 | I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); | ||
| 436 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | ||
| 437 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | ||
| 438 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | ||
| 439 | if (IS_I965G(dev)) { | ||
| 440 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | ||
| 441 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | ||
| 442 | } | ||
| 443 | |||
| 444 | I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); | ||
| 445 | |||
| 446 | i915_restore_palette(dev, PIPE_A); | ||
| 447 | /* Enable the plane */ | ||
| 448 | I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); | ||
| 449 | I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); | ||
| 450 | |||
| 451 | /* Pipe & plane B info */ | ||
| 452 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { | ||
| 453 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & | ||
| 454 | ~DPLL_VCO_ENABLE); | ||
| 455 | DRM_UDELAY(150); | ||
| 456 | } | ||
| 457 | I915_WRITE(FPB0, dev_priv->saveFPB0); | ||
| 458 | I915_WRITE(FPB1, dev_priv->saveFPB1); | ||
| 459 | /* Actually enable it */ | ||
| 460 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); | ||
| 461 | DRM_UDELAY(150); | ||
| 462 | if (IS_I965G(dev)) | ||
| 463 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | ||
| 464 | DRM_UDELAY(150); | ||
| 465 | |||
| 466 | /* Restore mode */ | ||
| 467 | I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); | ||
| 468 | I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); | ||
| 469 | I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); | ||
| 470 | I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); | ||
| 471 | I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); | ||
| 472 | I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); | ||
| 473 | I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); | ||
| 474 | |||
| 475 | /* Restore plane info */ | ||
| 476 | I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); | ||
| 477 | I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); | ||
| 478 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | ||
| 479 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | ||
| 480 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | ||
| 481 | if (IS_I965G(dev)) { | ||
| 482 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | ||
| 483 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | ||
| 484 | } | ||
| 485 | |||
| 486 | I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); | ||
| 487 | |||
| 488 | i915_restore_palette(dev, PIPE_B); | ||
| 489 | /* Enable the plane */ | ||
| 490 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | ||
| 491 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | ||
| 492 | |||
| 493 | /* Cursor state */ | 540 | /* Cursor state */ |
| 494 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | 541 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); |
| 495 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | 542 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); |
| @@ -518,6 +565,12 @@ int i915_restore_state(struct drm_device *dev) | |||
| 518 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); | 565 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); |
| 519 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); | 566 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); |
| 520 | 567 | ||
| 568 | /* Display Port state */ | ||
| 569 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
| 570 | I915_WRITE(DP_B, dev_priv->saveDP_B); | ||
| 571 | I915_WRITE(DP_C, dev_priv->saveDP_C); | ||
| 572 | I915_WRITE(DP_D, dev_priv->saveDP_D); | ||
| 573 | } | ||
| 521 | /* FIXME: restore TV & SDVO state */ | 574 | /* FIXME: restore TV & SDVO state */ |
| 522 | 575 | ||
| 523 | /* FBC info */ | 576 | /* FBC info */ |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index cdd126d068a7..7cc447191028 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -97,11 +97,14 @@ static void | |||
| 97 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, | 97 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, |
| 98 | struct bdb_header *bdb) | 98 | struct bdb_header *bdb) |
| 99 | { | 99 | { |
| 100 | struct drm_device *dev = dev_priv->dev; | ||
| 100 | struct bdb_lvds_options *lvds_options; | 101 | struct bdb_lvds_options *lvds_options; |
| 101 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 102 | struct bdb_lvds_lfp_data *lvds_lfp_data; |
| 103 | struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; | ||
| 102 | struct bdb_lvds_lfp_data_entry *entry; | 104 | struct bdb_lvds_lfp_data_entry *entry; |
| 103 | struct lvds_dvo_timing *dvo_timing; | 105 | struct lvds_dvo_timing *dvo_timing; |
| 104 | struct drm_display_mode *panel_fixed_mode; | 106 | struct drm_display_mode *panel_fixed_mode; |
| 107 | int lfp_data_size; | ||
| 105 | 108 | ||
| 106 | /* Defaults if we can't find VBT info */ | 109 | /* Defaults if we can't find VBT info */ |
| 107 | dev_priv->lvds_dither = 0; | 110 | dev_priv->lvds_dither = 0; |
| @@ -119,10 +122,25 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 119 | if (!lvds_lfp_data) | 122 | if (!lvds_lfp_data) |
| 120 | return; | 123 | return; |
| 121 | 124 | ||
| 125 | lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); | ||
| 126 | if (!lvds_lfp_data_ptrs) | ||
| 127 | return; | ||
| 128 | |||
| 122 | dev_priv->lvds_vbt = 1; | 129 | dev_priv->lvds_vbt = 1; |
| 123 | 130 | ||
| 124 | entry = &lvds_lfp_data->data[lvds_options->panel_type]; | 131 | lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - |
| 125 | dvo_timing = &entry->dvo_timing; | 132 | lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; |
| 133 | entry = (struct bdb_lvds_lfp_data_entry *) | ||
| 134 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * | ||
| 135 | lvds_options->panel_type)); | ||
| 136 | |||
| 137 | /* On IGDNG mobile, LVDS data block removes panel fitting registers. | ||
| 138 | So dec 2 dword from dvo_timing offset */ | ||
| 139 | if (IS_IGDNG(dev)) | ||
| 140 | dvo_timing = (struct lvds_dvo_timing *) | ||
| 141 | ((u8 *)&entry->dvo_timing - 8); | ||
| 142 | else | ||
| 143 | dvo_timing = &entry->dvo_timing; | ||
| 126 | 144 | ||
| 127 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 145 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
| 128 | 146 | ||
| @@ -185,10 +203,12 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
| 185 | dev_priv->lvds_use_ssc = general->enable_ssc; | 203 | dev_priv->lvds_use_ssc = general->enable_ssc; |
| 186 | 204 | ||
| 187 | if (dev_priv->lvds_use_ssc) { | 205 | if (dev_priv->lvds_use_ssc) { |
| 188 | if (IS_I855(dev_priv->dev)) | 206 | if (IS_I85X(dev_priv->dev)) |
| 189 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; | 207 | dev_priv->lvds_ssc_freq = |
| 190 | else | 208 | general->ssc_freq ? 66 : 48; |
| 191 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; | 209 | else |
| 210 | dev_priv->lvds_ssc_freq = | ||
| 211 | general->ssc_freq ? 100 : 96; | ||
| 192 | } | 212 | } |
| 193 | } | 213 | } |
| 194 | } | 214 | } |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6de97fc66029..d6a1a6e5539a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -46,7 +46,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
| 46 | 46 | ||
| 47 | temp = I915_READ(reg); | 47 | temp = I915_READ(reg); |
| 48 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 48 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
| 49 | temp |= ADPA_DAC_ENABLE; | 49 | temp &= ~ADPA_DAC_ENABLE; |
| 50 | 50 | ||
| 51 | switch(mode) { | 51 | switch(mode) { |
| 52 | case DRM_MODE_DPMS_ON: | 52 | case DRM_MODE_DPMS_ON: |
| @@ -428,8 +428,34 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
| 428 | 428 | ||
| 429 | static int intel_crt_get_modes(struct drm_connector *connector) | 429 | static int intel_crt_get_modes(struct drm_connector *connector) |
| 430 | { | 430 | { |
| 431 | int ret; | ||
| 431 | struct intel_output *intel_output = to_intel_output(connector); | 432 | struct intel_output *intel_output = to_intel_output(connector); |
| 432 | return intel_ddc_get_modes(intel_output); | 433 | struct i2c_adapter *ddcbus; |
| 434 | struct drm_device *dev = connector->dev; | ||
| 435 | |||
| 436 | |||
| 437 | ret = intel_ddc_get_modes(intel_output); | ||
| 438 | if (ret || !IS_G4X(dev)) | ||
| 439 | goto end; | ||
| 440 | |||
| 441 | ddcbus = intel_output->ddc_bus; | ||
| 442 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | ||
| 443 | intel_output->ddc_bus = | ||
| 444 | intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); | ||
| 445 | |||
| 446 | if (!intel_output->ddc_bus) { | ||
| 447 | intel_output->ddc_bus = ddcbus; | ||
| 448 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, | ||
| 449 | "DDC bus registration failed for CRTDDC_D.\n"); | ||
| 450 | goto end; | ||
| 451 | } | ||
| 452 | /* Try to get modes by GPIOD port */ | ||
| 453 | ret = intel_ddc_get_modes(intel_output); | ||
| 454 | intel_i2c_destroy(ddcbus); | ||
| 455 | |||
| 456 | end: | ||
| 457 | return ret; | ||
| 458 | |||
| 433 | } | 459 | } |
| 434 | 460 | ||
| 435 | static int intel_crt_set_property(struct drm_connector *connector, | 461 | static int intel_crt_set_property(struct drm_connector *connector, |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c78162119..508838ee31e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -25,14 +25,17 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 28 | #include <linux/kernel.h> | ||
| 28 | #include "drmP.h" | 29 | #include "drmP.h" |
| 29 | #include "intel_drv.h" | 30 | #include "intel_drv.h" |
| 30 | #include "i915_drm.h" | 31 | #include "i915_drm.h" |
| 31 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
| 33 | #include "intel_dp.h" | ||
| 32 | 34 | ||
| 33 | #include "drm_crtc_helper.h" | 35 | #include "drm_crtc_helper.h" |
| 34 | 36 | ||
| 35 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 37 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
| 38 | static void intel_update_watermarks(struct drm_device *dev); | ||
| 36 | 39 | ||
| 37 | typedef struct { | 40 | typedef struct { |
| 38 | /* given values */ | 41 | /* given values */ |
| @@ -127,19 +130,6 @@ struct intel_limit { | |||
| 127 | #define I9XX_P2_LVDS_FAST 7 | 130 | #define I9XX_P2_LVDS_FAST 7 |
| 128 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | 131 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 |
| 129 | 132 | ||
| 130 | #define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
| 131 | #define INTEL_LIMIT_I8XX_LVDS 1 | ||
| 132 | #define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
| 133 | #define INTEL_LIMIT_I9XX_LVDS 3 | ||
| 134 | #define INTEL_LIMIT_G4X_SDVO 4 | ||
| 135 | #define INTEL_LIMIT_G4X_HDMI_DAC 5 | ||
| 136 | #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 | ||
| 137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 | ||
| 138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 | ||
| 139 | #define INTEL_LIMIT_IGD_LVDS 9 | ||
| 140 | #define INTEL_LIMIT_IGDNG_SDVO_DAC 10 | ||
| 141 | #define INTEL_LIMIT_IGDNG_LVDS 11 | ||
| 142 | |||
| 143 | /*The parameter is for SDVO on G4x platform*/ | 133 | /*The parameter is for SDVO on G4x platform*/ |
| 144 | #define G4X_DOT_SDVO_MIN 25000 | 134 | #define G4X_DOT_SDVO_MIN 25000 |
| 145 | #define G4X_DOT_SDVO_MAX 270000 | 135 | #define G4X_DOT_SDVO_MAX 270000 |
| @@ -218,6 +208,25 @@ struct intel_limit { | |||
| 218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 208 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
| 219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 209 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
| 220 | 210 | ||
| 211 | /*The parameter is for DISPLAY PORT on G4x platform*/ | ||
| 212 | #define G4X_DOT_DISPLAY_PORT_MIN 161670 | ||
| 213 | #define G4X_DOT_DISPLAY_PORT_MAX 227000 | ||
| 214 | #define G4X_N_DISPLAY_PORT_MIN 1 | ||
| 215 | #define G4X_N_DISPLAY_PORT_MAX 2 | ||
| 216 | #define G4X_M_DISPLAY_PORT_MIN 97 | ||
| 217 | #define G4X_M_DISPLAY_PORT_MAX 108 | ||
| 218 | #define G4X_M1_DISPLAY_PORT_MIN 0x10 | ||
| 219 | #define G4X_M1_DISPLAY_PORT_MAX 0x12 | ||
| 220 | #define G4X_M2_DISPLAY_PORT_MIN 0x05 | ||
| 221 | #define G4X_M2_DISPLAY_PORT_MAX 0x06 | ||
| 222 | #define G4X_P_DISPLAY_PORT_MIN 10 | ||
| 223 | #define G4X_P_DISPLAY_PORT_MAX 20 | ||
| 224 | #define G4X_P1_DISPLAY_PORT_MIN 1 | ||
| 225 | #define G4X_P1_DISPLAY_PORT_MAX 2 | ||
| 226 | #define G4X_P2_DISPLAY_PORT_SLOW 10 | ||
| 227 | #define G4X_P2_DISPLAY_PORT_FAST 10 | ||
| 228 | #define G4X_P2_DISPLAY_PORT_LIMIT 0 | ||
| 229 | |||
| 221 | /* IGDNG */ | 230 | /* IGDNG */ |
| 222 | /* as we calculate clock using (register_value + 2) for | 231 | /* as we calculate clock using (register_value + 2) for |
| 223 | N/M1/M2, so here the range value for them is (actual_value-2). | 232 | N/M1/M2, so here the range value for them is (actual_value-2). |
| @@ -256,8 +265,11 @@ static bool | |||
| 256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 265 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 257 | int target, int refclk, intel_clock_t *best_clock); | 266 | int target, int refclk, intel_clock_t *best_clock); |
| 258 | 267 | ||
| 259 | static const intel_limit_t intel_limits[] = { | 268 | static bool |
| 260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 269 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
| 270 | int target, int refclk, intel_clock_t *best_clock); | ||
| 271 | |||
| 272 | static const intel_limit_t intel_limits_i8xx_dvo = { | ||
| 261 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 273 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
| 262 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 274 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
| 263 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 275 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
| @@ -269,8 +281,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 269 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 281 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 270 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 282 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
| 271 | .find_pll = intel_find_best_PLL, | 283 | .find_pll = intel_find_best_PLL, |
| 272 | }, | 284 | }; |
| 273 | { /* INTEL_LIMIT_I8XX_LVDS */ | 285 | |
| 286 | static const intel_limit_t intel_limits_i8xx_lvds = { | ||
| 274 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 287 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
| 275 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 288 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
| 276 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 289 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
| @@ -282,8 +295,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 282 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 295 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 283 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 296 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
| 284 | .find_pll = intel_find_best_PLL, | 297 | .find_pll = intel_find_best_PLL, |
| 285 | }, | 298 | }; |
| 286 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | 299 | |
| 300 | static const intel_limit_t intel_limits_i9xx_sdvo = { | ||
| 287 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 301 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 288 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 302 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
| 289 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 303 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
| @@ -295,8 +309,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 295 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 309 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 296 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 310 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 297 | .find_pll = intel_find_best_PLL, | 311 | .find_pll = intel_find_best_PLL, |
| 298 | }, | 312 | }; |
| 299 | { /* INTEL_LIMIT_I9XX_LVDS */ | 313 | |
| 314 | static const intel_limit_t intel_limits_i9xx_lvds = { | ||
| 300 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 315 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 301 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 316 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
| 302 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 317 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
| @@ -311,9 +326,10 @@ static const intel_limit_t intel_limits[] = { | |||
| 311 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 326 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 312 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 327 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
| 313 | .find_pll = intel_find_best_PLL, | 328 | .find_pll = intel_find_best_PLL, |
| 314 | }, | 329 | }; |
| 330 | |||
| 315 | /* below parameter and function is for G4X Chipset Family*/ | 331 | /* below parameter and function is for G4X Chipset Family*/ |
| 316 | { /* INTEL_LIMIT_G4X_SDVO */ | 332 | static const intel_limit_t intel_limits_g4x_sdvo = { |
| 317 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, | 333 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, |
| 318 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 334 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
| 319 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, | 335 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, |
| @@ -327,8 +343,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 327 | .p2_fast = G4X_P2_SDVO_FAST | 343 | .p2_fast = G4X_P2_SDVO_FAST |
| 328 | }, | 344 | }, |
| 329 | .find_pll = intel_g4x_find_best_PLL, | 345 | .find_pll = intel_g4x_find_best_PLL, |
| 330 | }, | 346 | }; |
| 331 | { /* INTEL_LIMIT_G4X_HDMI_DAC */ | 347 | |
| 348 | static const intel_limit_t intel_limits_g4x_hdmi = { | ||
| 332 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, | 349 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, |
| 333 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 350 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
| 334 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, | 351 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, |
| @@ -342,8 +359,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 342 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 359 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
| 343 | }, | 360 | }, |
| 344 | .find_pll = intel_g4x_find_best_PLL, | 361 | .find_pll = intel_g4x_find_best_PLL, |
| 345 | }, | 362 | }; |
| 346 | { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ | 363 | |
| 364 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | ||
| 347 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, | 365 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, |
| 348 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, | 366 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, |
| 349 | .vco = { .min = G4X_VCO_MIN, | 367 | .vco = { .min = G4X_VCO_MIN, |
| @@ -365,8 +383,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 365 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 383 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
| 366 | }, | 384 | }, |
| 367 | .find_pll = intel_g4x_find_best_PLL, | 385 | .find_pll = intel_g4x_find_best_PLL, |
| 368 | }, | 386 | }; |
| 369 | { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ | 387 | |
| 388 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | ||
| 370 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, | 389 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, |
| 371 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, | 390 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, |
| 372 | .vco = { .min = G4X_VCO_MIN, | 391 | .vco = { .min = G4X_VCO_MIN, |
| @@ -388,8 +407,32 @@ static const intel_limit_t intel_limits[] = { | |||
| 388 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 407 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
| 389 | }, | 408 | }, |
| 390 | .find_pll = intel_g4x_find_best_PLL, | 409 | .find_pll = intel_g4x_find_best_PLL, |
| 391 | }, | 410 | }; |
| 392 | { /* INTEL_LIMIT_IGD_SDVO */ | 411 | |
| 412 | static const intel_limit_t intel_limits_g4x_display_port = { | ||
| 413 | .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, | ||
| 414 | .max = G4X_DOT_DISPLAY_PORT_MAX }, | ||
| 415 | .vco = { .min = G4X_VCO_MIN, | ||
| 416 | .max = G4X_VCO_MAX}, | ||
| 417 | .n = { .min = G4X_N_DISPLAY_PORT_MIN, | ||
| 418 | .max = G4X_N_DISPLAY_PORT_MAX }, | ||
| 419 | .m = { .min = G4X_M_DISPLAY_PORT_MIN, | ||
| 420 | .max = G4X_M_DISPLAY_PORT_MAX }, | ||
| 421 | .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, | ||
| 422 | .max = G4X_M1_DISPLAY_PORT_MAX }, | ||
| 423 | .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, | ||
| 424 | .max = G4X_M2_DISPLAY_PORT_MAX }, | ||
| 425 | .p = { .min = G4X_P_DISPLAY_PORT_MIN, | ||
| 426 | .max = G4X_P_DISPLAY_PORT_MAX }, | ||
| 427 | .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, | ||
| 428 | .max = G4X_P1_DISPLAY_PORT_MAX}, | ||
| 429 | .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, | ||
| 430 | .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, | ||
| 431 | .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, | ||
| 432 | .find_pll = intel_find_pll_g4x_dp, | ||
| 433 | }; | ||
| 434 | |||
| 435 | static const intel_limit_t intel_limits_igd_sdvo = { | ||
| 393 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | 436 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, |
| 394 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 437 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
| 395 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 438 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
| @@ -401,8 +444,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 401 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 444 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 402 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 445 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 403 | .find_pll = intel_find_best_PLL, | 446 | .find_pll = intel_find_best_PLL, |
| 404 | }, | 447 | }; |
| 405 | { /* INTEL_LIMIT_IGD_LVDS */ | 448 | |
| 449 | static const intel_limit_t intel_limits_igd_lvds = { | ||
| 406 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 450 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 407 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 451 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
| 408 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 452 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
| @@ -415,8 +459,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 415 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 459 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 460 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
| 417 | .find_pll = intel_find_best_PLL, | 461 | .find_pll = intel_find_best_PLL, |
| 418 | }, | 462 | }; |
| 419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | 463 | |
| 464 | static const intel_limit_t intel_limits_igdng_sdvo = { | ||
| 420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 465 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
| 421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 466 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
| 422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 467 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
| @@ -429,8 +474,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | 474 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, |
| 430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | 475 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, |
| 431 | .find_pll = intel_igdng_find_best_PLL, | 476 | .find_pll = intel_igdng_find_best_PLL, |
| 432 | }, | 477 | }; |
| 433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | 478 | |
| 479 | static const intel_limit_t intel_limits_igdng_lvds = { | ||
| 434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 480 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
| 435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 481 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
| 436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 482 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
| @@ -443,16 +489,15 @@ static const intel_limit_t intel_limits[] = { | |||
| 443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | 489 | .p2_slow = IGDNG_P2_LVDS_SLOW, |
| 444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | 490 | .p2_fast = IGDNG_P2_LVDS_FAST }, |
| 445 | .find_pll = intel_igdng_find_best_PLL, | 491 | .find_pll = intel_igdng_find_best_PLL, |
| 446 | }, | ||
| 447 | }; | 492 | }; |
| 448 | 493 | ||
| 449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | 494 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) |
| 450 | { | 495 | { |
| 451 | const intel_limit_t *limit; | 496 | const intel_limit_t *limit; |
| 452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | 498 | limit = &intel_limits_igdng_lvds; |
| 454 | else | 499 | else |
| 455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | 500 | limit = &intel_limits_igdng_sdvo; |
| 456 | 501 | ||
| 457 | return limit; | 502 | return limit; |
| 458 | } | 503 | } |
| @@ -467,19 +512,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | |||
| 467 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 512 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
| 468 | LVDS_CLKB_POWER_UP) | 513 | LVDS_CLKB_POWER_UP) |
| 469 | /* LVDS with dual channel */ | 514 | /* LVDS with dual channel */ |
| 470 | limit = &intel_limits | 515 | limit = &intel_limits_g4x_dual_channel_lvds; |
| 471 | [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; | ||
| 472 | else | 516 | else |
| 473 | /* LVDS with dual channel */ | 517 | /* LVDS with dual channel */ |
| 474 | limit = &intel_limits | 518 | limit = &intel_limits_g4x_single_channel_lvds; |
| 475 | [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; | ||
| 476 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || | 519 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || |
| 477 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | 520 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
| 478 | limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; | 521 | limit = &intel_limits_g4x_hdmi; |
| 479 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { | 522 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { |
| 480 | limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; | 523 | limit = &intel_limits_g4x_sdvo; |
| 524 | } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
| 525 | limit = &intel_limits_g4x_display_port; | ||
| 481 | } else /* The option is for other outputs */ | 526 | } else /* The option is for other outputs */ |
| 482 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 527 | limit = &intel_limits_i9xx_sdvo; |
| 483 | 528 | ||
| 484 | return limit; | 529 | return limit; |
| 485 | } | 530 | } |
| @@ -495,19 +540,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
| 495 | limit = intel_g4x_limit(crtc); | 540 | limit = intel_g4x_limit(crtc); |
| 496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 541 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
| 497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 542 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 498 | limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | 543 | limit = &intel_limits_i9xx_lvds; |
| 499 | else | 544 | else |
| 500 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 545 | limit = &intel_limits_i9xx_sdvo; |
| 501 | } else if (IS_IGD(dev)) { | 546 | } else if (IS_IGD(dev)) { |
| 502 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 547 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 503 | limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; | 548 | limit = &intel_limits_igd_lvds; |
| 504 | else | 549 | else |
| 505 | limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; | 550 | limit = &intel_limits_igd_sdvo; |
| 506 | } else { | 551 | } else { |
| 507 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 552 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 508 | limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | 553 | limit = &intel_limits_i8xx_lvds; |
| 509 | else | 554 | else |
| 510 | limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | 555 | limit = &intel_limits_i8xx_dvo; |
| 511 | } | 556 | } |
| 512 | return limit; | 557 | return limit; |
| 513 | } | 558 | } |
| @@ -764,6 +809,32 @@ out: | |||
| 764 | return found; | 809 | return found; |
| 765 | } | 810 | } |
| 766 | 811 | ||
| 812 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | ||
| 813 | static bool | ||
| 814 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 815 | int target, int refclk, intel_clock_t *best_clock) | ||
| 816 | { | ||
| 817 | intel_clock_t clock; | ||
| 818 | if (target < 200000) { | ||
| 819 | clock.p1 = 2; | ||
| 820 | clock.p2 = 10; | ||
| 821 | clock.n = 2; | ||
| 822 | clock.m1 = 23; | ||
| 823 | clock.m2 = 8; | ||
| 824 | } else { | ||
| 825 | clock.p1 = 1; | ||
| 826 | clock.p2 = 10; | ||
| 827 | clock.n = 1; | ||
| 828 | clock.m1 = 14; | ||
| 829 | clock.m2 = 2; | ||
| 830 | } | ||
| 831 | clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); | ||
| 832 | clock.p = (clock.p1 * clock.p2); | ||
| 833 | clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; | ||
| 834 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
| 835 | return true; | ||
| 836 | } | ||
| 837 | |||
| 767 | void | 838 | void |
| 768 | intel_wait_for_vblank(struct drm_device *dev) | 839 | intel_wait_for_vblank(struct drm_device *dev) |
| 769 | { | 840 | { |
| @@ -933,7 +1004,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 933 | struct drm_i915_private *dev_priv = dev->dev_private; | 1004 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 934 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1005 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 935 | int pipe = intel_crtc->pipe; | 1006 | int pipe = intel_crtc->pipe; |
| 936 | int plane = intel_crtc->pipe; | 1007 | int plane = intel_crtc->plane; |
| 937 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | 1008 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; |
| 938 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 1009 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
| 939 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | 1010 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
| @@ -1263,8 +1334,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 1263 | 1334 | ||
| 1264 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 1335 | /* Give the overlay scaler a chance to enable if it's on this pipe */ |
| 1265 | //intel_crtc_dpms_video(crtc, true); TODO | 1336 | //intel_crtc_dpms_video(crtc, true); TODO |
| 1337 | intel_update_watermarks(dev); | ||
| 1266 | break; | 1338 | break; |
| 1267 | case DRM_MODE_DPMS_OFF: | 1339 | case DRM_MODE_DPMS_OFF: |
| 1340 | intel_update_watermarks(dev); | ||
| 1268 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | 1341 | /* Give the overlay scaler a chance to disable if it's on this pipe */ |
| 1269 | //intel_crtc_dpms_video(crtc, FALSE); TODO | 1342 | //intel_crtc_dpms_video(crtc, FALSE); TODO |
| 1270 | 1343 | ||
| @@ -1443,7 +1516,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev) | |||
| 1443 | return 0; /* Silence gcc warning */ | 1516 | return 0; /* Silence gcc warning */ |
| 1444 | } | 1517 | } |
| 1445 | 1518 | ||
| 1446 | |||
| 1447 | /** | 1519 | /** |
| 1448 | * Return the pipe currently connected to the panel fitter, | 1520 | * Return the pipe currently connected to the panel fitter, |
| 1449 | * or -1 if the panel fitter is not present or not in use | 1521 | * or -1 if the panel fitter is not present or not in use |
| @@ -1502,7 +1574,7 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
| 1502 | 1574 | ||
| 1503 | temp = (u64) DATA_N * pixel_clock; | 1575 | temp = (u64) DATA_N * pixel_clock; |
| 1504 | temp = div_u64(temp, link_clock); | 1576 | temp = div_u64(temp, link_clock); |
| 1505 | m_n->gmch_m = (temp * bytes_per_pixel) / nlanes; | 1577 | m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes); |
| 1506 | m_n->gmch_n = DATA_N; | 1578 | m_n->gmch_n = DATA_N; |
| 1507 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 1579 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
| 1508 | 1580 | ||
| @@ -1513,6 +1585,420 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
| 1513 | } | 1585 | } |
| 1514 | 1586 | ||
| 1515 | 1587 | ||
| 1588 | struct intel_watermark_params { | ||
| 1589 | unsigned long fifo_size; | ||
| 1590 | unsigned long max_wm; | ||
| 1591 | unsigned long default_wm; | ||
| 1592 | unsigned long guard_size; | ||
| 1593 | unsigned long cacheline_size; | ||
| 1594 | }; | ||
| 1595 | |||
| 1596 | /* IGD has different values for various configs */ | ||
| 1597 | static struct intel_watermark_params igd_display_wm = { | ||
| 1598 | IGD_DISPLAY_FIFO, | ||
| 1599 | IGD_MAX_WM, | ||
| 1600 | IGD_DFT_WM, | ||
| 1601 | IGD_GUARD_WM, | ||
| 1602 | IGD_FIFO_LINE_SIZE | ||
| 1603 | }; | ||
| 1604 | static struct intel_watermark_params igd_display_hplloff_wm = { | ||
| 1605 | IGD_DISPLAY_FIFO, | ||
| 1606 | IGD_MAX_WM, | ||
| 1607 | IGD_DFT_HPLLOFF_WM, | ||
| 1608 | IGD_GUARD_WM, | ||
| 1609 | IGD_FIFO_LINE_SIZE | ||
| 1610 | }; | ||
| 1611 | static struct intel_watermark_params igd_cursor_wm = { | ||
| 1612 | IGD_CURSOR_FIFO, | ||
| 1613 | IGD_CURSOR_MAX_WM, | ||
| 1614 | IGD_CURSOR_DFT_WM, | ||
| 1615 | IGD_CURSOR_GUARD_WM, | ||
| 1616 | IGD_FIFO_LINE_SIZE, | ||
| 1617 | }; | ||
| 1618 | static struct intel_watermark_params igd_cursor_hplloff_wm = { | ||
| 1619 | IGD_CURSOR_FIFO, | ||
| 1620 | IGD_CURSOR_MAX_WM, | ||
| 1621 | IGD_CURSOR_DFT_WM, | ||
| 1622 | IGD_CURSOR_GUARD_WM, | ||
| 1623 | IGD_FIFO_LINE_SIZE | ||
| 1624 | }; | ||
| 1625 | static struct intel_watermark_params i945_wm_info = { | ||
| 1626 | I915_FIFO_LINE_SIZE, | ||
| 1627 | I915_MAX_WM, | ||
| 1628 | 1, | ||
| 1629 | 0, | ||
| 1630 | IGD_FIFO_LINE_SIZE | ||
| 1631 | }; | ||
| 1632 | static struct intel_watermark_params i915_wm_info = { | ||
| 1633 | I945_FIFO_SIZE, | ||
| 1634 | I915_MAX_WM, | ||
| 1635 | 1, | ||
| 1636 | 0, | ||
| 1637 | I915_FIFO_LINE_SIZE | ||
| 1638 | }; | ||
| 1639 | static struct intel_watermark_params i855_wm_info = { | ||
| 1640 | I855GM_FIFO_SIZE, | ||
| 1641 | I915_MAX_WM, | ||
| 1642 | 1, | ||
| 1643 | 0, | ||
| 1644 | I830_FIFO_LINE_SIZE | ||
| 1645 | }; | ||
| 1646 | static struct intel_watermark_params i830_wm_info = { | ||
| 1647 | I830_FIFO_SIZE, | ||
| 1648 | I915_MAX_WM, | ||
| 1649 | 1, | ||
| 1650 | 0, | ||
| 1651 | I830_FIFO_LINE_SIZE | ||
| 1652 | }; | ||
| 1653 | |||
| 1654 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | ||
| 1655 | struct intel_watermark_params *wm, | ||
| 1656 | int pixel_size, | ||
| 1657 | unsigned long latency_ns) | ||
| 1658 | { | ||
| 1659 | unsigned long bytes_required, wm_size; | ||
| 1660 | |||
| 1661 | bytes_required = (clock_in_khz * pixel_size * latency_ns) / 1000000; | ||
| 1662 | bytes_required /= wm->cacheline_size; | ||
| 1663 | wm_size = wm->fifo_size - bytes_required - wm->guard_size; | ||
| 1664 | |||
| 1665 | if (wm_size > wm->max_wm) | ||
| 1666 | wm_size = wm->max_wm; | ||
| 1667 | if (wm_size == 0) | ||
| 1668 | wm_size = wm->default_wm; | ||
| 1669 | return wm_size; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | struct cxsr_latency { | ||
| 1673 | int is_desktop; | ||
| 1674 | unsigned long fsb_freq; | ||
| 1675 | unsigned long mem_freq; | ||
| 1676 | unsigned long display_sr; | ||
| 1677 | unsigned long display_hpll_disable; | ||
| 1678 | unsigned long cursor_sr; | ||
| 1679 | unsigned long cursor_hpll_disable; | ||
| 1680 | }; | ||
| 1681 | |||
| 1682 | static struct cxsr_latency cxsr_latency_table[] = { | ||
| 1683 | {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ | ||
| 1684 | {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ | ||
| 1685 | {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ | ||
| 1686 | |||
| 1687 | {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ | ||
| 1688 | {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ | ||
| 1689 | {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ | ||
| 1690 | |||
| 1691 | {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ | ||
| 1692 | {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ | ||
| 1693 | {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ | ||
| 1694 | |||
| 1695 | {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ | ||
| 1696 | {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ | ||
| 1697 | {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ | ||
| 1698 | |||
| 1699 | {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ | ||
| 1700 | {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ | ||
| 1701 | {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ | ||
| 1702 | |||
| 1703 | {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ | ||
| 1704 | {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ | ||
| 1705 | {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ | ||
| 1706 | }; | ||
| 1707 | |||
| 1708 | static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, | ||
| 1709 | int mem) | ||
| 1710 | { | ||
| 1711 | int i; | ||
| 1712 | struct cxsr_latency *latency; | ||
| 1713 | |||
| 1714 | if (fsb == 0 || mem == 0) | ||
| 1715 | return NULL; | ||
| 1716 | |||
| 1717 | for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { | ||
| 1718 | latency = &cxsr_latency_table[i]; | ||
| 1719 | if (is_desktop == latency->is_desktop && | ||
| 1720 | fsb == latency->fsb_freq && mem == latency->mem_freq) | ||
| 1721 | break; | ||
| 1722 | } | ||
| 1723 | if (i >= ARRAY_SIZE(cxsr_latency_table)) { | ||
| 1724 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
| 1725 | return NULL; | ||
| 1726 | } | ||
| 1727 | return latency; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | static void igd_disable_cxsr(struct drm_device *dev) | ||
| 1731 | { | ||
| 1732 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1733 | u32 reg; | ||
| 1734 | |||
| 1735 | /* deactivate cxsr */ | ||
| 1736 | reg = I915_READ(DSPFW3); | ||
| 1737 | reg &= ~(IGD_SELF_REFRESH_EN); | ||
| 1738 | I915_WRITE(DSPFW3, reg); | ||
| 1739 | DRM_INFO("Big FIFO is disabled\n"); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, | ||
| 1743 | int pixel_size) | ||
| 1744 | { | ||
| 1745 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1746 | u32 reg; | ||
| 1747 | unsigned long wm; | ||
| 1748 | struct cxsr_latency *latency; | ||
| 1749 | |||
| 1750 | latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq, | ||
| 1751 | dev_priv->mem_freq); | ||
| 1752 | if (!latency) { | ||
| 1753 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
| 1754 | igd_disable_cxsr(dev); | ||
| 1755 | return; | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | /* Display SR */ | ||
| 1759 | wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size, | ||
| 1760 | latency->display_sr); | ||
| 1761 | reg = I915_READ(DSPFW1); | ||
| 1762 | reg &= 0x7fffff; | ||
| 1763 | reg |= wm << 23; | ||
| 1764 | I915_WRITE(DSPFW1, reg); | ||
| 1765 | DRM_DEBUG("DSPFW1 register is %x\n", reg); | ||
| 1766 | |||
| 1767 | /* cursor SR */ | ||
| 1768 | wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size, | ||
| 1769 | latency->cursor_sr); | ||
| 1770 | reg = I915_READ(DSPFW3); | ||
| 1771 | reg &= ~(0x3f << 24); | ||
| 1772 | reg |= (wm & 0x3f) << 24; | ||
| 1773 | I915_WRITE(DSPFW3, reg); | ||
| 1774 | |||
| 1775 | /* Display HPLL off SR */ | ||
| 1776 | wm = intel_calculate_wm(clock, &igd_display_hplloff_wm, | ||
| 1777 | latency->display_hpll_disable, I915_FIFO_LINE_SIZE); | ||
| 1778 | reg = I915_READ(DSPFW3); | ||
| 1779 | reg &= 0xfffffe00; | ||
| 1780 | reg |= wm & 0x1ff; | ||
| 1781 | I915_WRITE(DSPFW3, reg); | ||
| 1782 | |||
| 1783 | /* cursor HPLL off SR */ | ||
| 1784 | wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size, | ||
| 1785 | latency->cursor_hpll_disable); | ||
| 1786 | reg = I915_READ(DSPFW3); | ||
| 1787 | reg &= ~(0x3f << 16); | ||
| 1788 | reg |= (wm & 0x3f) << 16; | ||
| 1789 | I915_WRITE(DSPFW3, reg); | ||
| 1790 | DRM_DEBUG("DSPFW3 register is %x\n", reg); | ||
| 1791 | |||
| 1792 | /* activate cxsr */ | ||
| 1793 | reg = I915_READ(DSPFW3); | ||
| 1794 | reg |= IGD_SELF_REFRESH_EN; | ||
| 1795 | I915_WRITE(DSPFW3, reg); | ||
| 1796 | |||
| 1797 | DRM_INFO("Big FIFO is enabled\n"); | ||
| 1798 | |||
| 1799 | return; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | const static int latency_ns = 5000; /* default for non-igd platforms */ | ||
| 1803 | |||
| 1804 | |||
| 1805 | static void i965_update_wm(struct drm_device *dev) | ||
| 1806 | { | ||
| 1807 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1808 | |||
| 1809 | DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); | ||
| 1810 | |||
| 1811 | /* 965 has limitations... */ | ||
| 1812 | I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); | ||
| 1813 | I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | ||
| 1817 | int planeb_clock, int sr_hdisplay, int pixel_size) | ||
| 1818 | { | ||
| 1819 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1820 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
| 1821 | uint32_t fwater_hi = I915_READ(FW_BLC2) & LM_FIFO_WATERMARK; | ||
| 1822 | int bsize, asize, cwm, bwm = 1, awm = 1, srwm = 1; | ||
| 1823 | uint32_t dsparb = I915_READ(DSPARB); | ||
| 1824 | int planea_entries, planeb_entries; | ||
| 1825 | struct intel_watermark_params *wm_params; | ||
| 1826 | unsigned long line_time_us; | ||
| 1827 | int sr_clock, sr_entries = 0; | ||
| 1828 | |||
| 1829 | if (IS_I965GM(dev) || IS_I945GM(dev)) | ||
| 1830 | wm_params = &i945_wm_info; | ||
| 1831 | else if (IS_I9XX(dev)) | ||
| 1832 | wm_params = &i915_wm_info; | ||
| 1833 | else | ||
| 1834 | wm_params = &i855_wm_info; | ||
| 1835 | |||
| 1836 | planea_entries = intel_calculate_wm(planea_clock, wm_params, | ||
| 1837 | pixel_size, latency_ns); | ||
| 1838 | planeb_entries = intel_calculate_wm(planeb_clock, wm_params, | ||
| 1839 | pixel_size, latency_ns); | ||
| 1840 | |||
| 1841 | DRM_DEBUG("FIFO entries - A: %d, B: %d\n", planea_entries, | ||
| 1842 | planeb_entries); | ||
| 1843 | |||
| 1844 | if (IS_I9XX(dev)) { | ||
| 1845 | asize = dsparb & 0x7f; | ||
| 1846 | bsize = (dsparb >> DSPARB_CSTART_SHIFT) & 0x7f; | ||
| 1847 | } else { | ||
| 1848 | asize = dsparb & 0x1ff; | ||
| 1849 | bsize = (dsparb >> DSPARB_BEND_SHIFT) & 0x1ff; | ||
| 1850 | } | ||
| 1851 | DRM_DEBUG("FIFO size - A: %d, B: %d\n", asize, bsize); | ||
| 1852 | |||
| 1853 | /* Two extra entries for padding */ | ||
| 1854 | awm = asize - (planea_entries + 2); | ||
| 1855 | bwm = bsize - (planeb_entries + 2); | ||
| 1856 | |||
| 1857 | /* Sanity check against potentially bad FIFO allocations */ | ||
| 1858 | if (awm <= 0) { | ||
| 1859 | /* pipe is on but has too few FIFO entries */ | ||
| 1860 | if (planea_entries != 0) | ||
| 1861 | DRM_DEBUG("plane A needs more FIFO entries\n"); | ||
| 1862 | awm = 1; | ||
| 1863 | } | ||
| 1864 | if (bwm <= 0) { | ||
| 1865 | if (planeb_entries != 0) | ||
| 1866 | DRM_DEBUG("plane B needs more FIFO entries\n"); | ||
| 1867 | bwm = 1; | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | /* | ||
| 1871 | * Overlay gets an aggressive default since video jitter is bad. | ||
| 1872 | */ | ||
| 1873 | cwm = 2; | ||
| 1874 | |||
| 1875 | /* Calc sr entries for one pipe configs */ | ||
| 1876 | if (!planea_clock || !planeb_clock) { | ||
| 1877 | sr_clock = planea_clock ? planea_clock : planeb_clock; | ||
| 1878 | line_time_us = (sr_hdisplay * 1000) / sr_clock; | ||
| 1879 | sr_entries = (((latency_ns / line_time_us) + 1) * pixel_size * | ||
| 1880 | sr_hdisplay) / 1000; | ||
| 1881 | sr_entries = roundup(sr_entries / wm_params->cacheline_size, 1); | ||
| 1882 | if (sr_entries < wm_params->fifo_size) | ||
| 1883 | srwm = wm_params->fifo_size - sr_entries; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | ||
| 1887 | awm, bwm, cwm, srwm); | ||
| 1888 | |||
| 1889 | fwater_lo = fwater_lo | ((bwm & 0x3f) << 16) | (awm & 0x3f); | ||
| 1890 | fwater_hi = fwater_hi | (cwm & 0x1f); | ||
| 1891 | |||
| 1892 | I915_WRITE(FW_BLC, fwater_lo); | ||
| 1893 | I915_WRITE(FW_BLC2, fwater_hi); | ||
| 1894 | if (IS_I9XX(dev)) | ||
| 1895 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | static void i830_update_wm(struct drm_device *dev, int planea_clock, | ||
| 1899 | int pixel_size) | ||
| 1900 | { | ||
| 1901 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1902 | uint32_t dsparb = I915_READ(DSPARB); | ||
| 1903 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
| 1904 | unsigned int asize, awm; | ||
| 1905 | int planea_entries; | ||
| 1906 | |||
| 1907 | planea_entries = intel_calculate_wm(planea_clock, &i830_wm_info, | ||
| 1908 | pixel_size, latency_ns); | ||
| 1909 | |||
| 1910 | asize = dsparb & 0x7f; | ||
| 1911 | |||
| 1912 | awm = asize - planea_entries; | ||
| 1913 | |||
| 1914 | fwater_lo = fwater_lo | awm; | ||
| 1915 | |||
| 1916 | I915_WRITE(FW_BLC, fwater_lo); | ||
| 1917 | } | ||
| 1918 | |||
| 1919 | /** | ||
| 1920 | * intel_update_watermarks - update FIFO watermark values based on current modes | ||
| 1921 | * | ||
| 1922 | * Calculate watermark values for the various WM regs based on current mode | ||
| 1923 | * and plane configuration. | ||
| 1924 | * | ||
| 1925 | * There are several cases to deal with here: | ||
| 1926 | * - normal (i.e. non-self-refresh) | ||
| 1927 | * - self-refresh (SR) mode | ||
| 1928 | * - lines are large relative to FIFO size (buffer can hold up to 2) | ||
| 1929 | * - lines are small relative to FIFO size (buffer can hold more than 2 | ||
| 1930 | * lines), so need to account for TLB latency | ||
| 1931 | * | ||
| 1932 | * The normal calculation is: | ||
| 1933 | * watermark = dotclock * bytes per pixel * latency | ||
| 1934 | * where latency is platform & configuration dependent (we assume pessimal | ||
| 1935 | * values here). | ||
| 1936 | * | ||
| 1937 | * The SR calculation is: | ||
| 1938 | * watermark = (trunc(latency/line time)+1) * surface width * | ||
| 1939 | * bytes per pixel | ||
| 1940 | * where | ||
| 1941 | * line time = htotal / dotclock | ||
| 1942 | * and latency is assumed to be high, as above. | ||
| 1943 | * | ||
| 1944 | * The final value programmed to the register should always be rounded up, | ||
| 1945 | * and include an extra 2 entries to account for clock crossings. | ||
| 1946 | * | ||
| 1947 | * We don't use the sprite, so we can ignore that. And on Crestline we have | ||
| 1948 | * to set the non-SR watermarks to 8. | ||
| 1949 | */ | ||
| 1950 | static void intel_update_watermarks(struct drm_device *dev) | ||
| 1951 | { | ||
| 1952 | struct drm_crtc *crtc; | ||
| 1953 | struct intel_crtc *intel_crtc; | ||
| 1954 | int sr_hdisplay = 0; | ||
| 1955 | unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; | ||
| 1956 | int enabled = 0, pixel_size = 0; | ||
| 1957 | |||
| 1958 | if (DSPARB_HWCONTROL(dev)) | ||
| 1959 | return; | ||
| 1960 | |||
| 1961 | /* Get the clock config from both planes */ | ||
| 1962 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 1963 | intel_crtc = to_intel_crtc(crtc); | ||
| 1964 | if (crtc->enabled) { | ||
| 1965 | enabled++; | ||
| 1966 | if (intel_crtc->plane == 0) { | ||
| 1967 | DRM_DEBUG("plane A (pipe %d) clock: %d\n", | ||
| 1968 | intel_crtc->pipe, crtc->mode.clock); | ||
| 1969 | planea_clock = crtc->mode.clock; | ||
| 1970 | } else { | ||
| 1971 | DRM_DEBUG("plane B (pipe %d) clock: %d\n", | ||
| 1972 | intel_crtc->pipe, crtc->mode.clock); | ||
| 1973 | planeb_clock = crtc->mode.clock; | ||
| 1974 | } | ||
| 1975 | sr_hdisplay = crtc->mode.hdisplay; | ||
| 1976 | sr_clock = crtc->mode.clock; | ||
| 1977 | if (crtc->fb) | ||
| 1978 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
| 1979 | else | ||
| 1980 | pixel_size = 4; /* by default */ | ||
| 1981 | } | ||
| 1982 | } | ||
| 1983 | |||
| 1984 | if (enabled <= 0) | ||
| 1985 | return; | ||
| 1986 | |||
| 1987 | /* Single pipe configs can enable self refresh */ | ||
| 1988 | if (enabled == 1 && IS_IGD(dev)) | ||
| 1989 | igd_enable_cxsr(dev, sr_clock, pixel_size); | ||
| 1990 | else if (IS_IGD(dev)) | ||
| 1991 | igd_disable_cxsr(dev); | ||
| 1992 | |||
| 1993 | if (IS_I965G(dev)) | ||
| 1994 | i965_update_wm(dev); | ||
| 1995 | else if (IS_I9XX(dev) || IS_MOBILE(dev)) | ||
| 1996 | i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay, | ||
| 1997 | pixel_size); | ||
| 1998 | else | ||
| 1999 | i830_update_wm(dev, planea_clock, pixel_size); | ||
| 2000 | } | ||
| 2001 | |||
| 1516 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 2002 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
| 1517 | struct drm_display_mode *mode, | 2003 | struct drm_display_mode *mode, |
| 1518 | struct drm_display_mode *adjusted_mode, | 2004 | struct drm_display_mode *adjusted_mode, |
| @@ -1541,7 +2027,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1541 | intel_clock_t clock; | 2027 | intel_clock_t clock; |
| 1542 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 2028 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
| 1543 | bool ok, is_sdvo = false, is_dvo = false; | 2029 | bool ok, is_sdvo = false, is_dvo = false; |
| 1544 | bool is_crt = false, is_lvds = false, is_tv = false; | 2030 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
| 1545 | struct drm_mode_config *mode_config = &dev->mode_config; | 2031 | struct drm_mode_config *mode_config = &dev->mode_config; |
| 1546 | struct drm_connector *connector; | 2032 | struct drm_connector *connector; |
| 1547 | const intel_limit_t *limit; | 2033 | const intel_limit_t *limit; |
| @@ -1585,6 +2071,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1585 | case INTEL_OUTPUT_ANALOG: | 2071 | case INTEL_OUTPUT_ANALOG: |
| 1586 | is_crt = true; | 2072 | is_crt = true; |
| 1587 | break; | 2073 | break; |
| 2074 | case INTEL_OUTPUT_DISPLAYPORT: | ||
| 2075 | is_dp = true; | ||
| 2076 | break; | ||
| 1588 | } | 2077 | } |
| 1589 | 2078 | ||
| 1590 | num_outputs++; | 2079 | num_outputs++; |
| @@ -1600,6 +2089,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1600 | } else { | 2089 | } else { |
| 1601 | refclk = 48000; | 2090 | refclk = 48000; |
| 1602 | } | 2091 | } |
| 2092 | |||
| 1603 | 2093 | ||
| 1604 | /* | 2094 | /* |
| 1605 | * Returns a set of divisors for the desired target clock with the given | 2095 | * Returns a set of divisors for the desired target clock with the given |
| @@ -1662,6 +2152,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1662 | else if (IS_IGDNG(dev)) | 2152 | else if (IS_IGDNG(dev)) |
| 1663 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | 2153 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; |
| 1664 | } | 2154 | } |
| 2155 | if (is_dp) | ||
| 2156 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 1665 | 2157 | ||
| 1666 | /* compute bitmask from p1 value */ | 2158 | /* compute bitmask from p1 value */ |
| 1667 | if (IS_IGD(dev)) | 2159 | if (IS_IGD(dev)) |
| @@ -1809,6 +2301,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1809 | I915_WRITE(lvds_reg, lvds); | 2301 | I915_WRITE(lvds_reg, lvds); |
| 1810 | I915_READ(lvds_reg); | 2302 | I915_READ(lvds_reg); |
| 1811 | } | 2303 | } |
| 2304 | if (is_dp) | ||
| 2305 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
| 1812 | 2306 | ||
| 1813 | I915_WRITE(fp_reg, fp); | 2307 | I915_WRITE(fp_reg, fp); |
| 1814 | I915_WRITE(dpll_reg, dpll); | 2308 | I915_WRITE(dpll_reg, dpll); |
| @@ -1871,6 +2365,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1871 | 2365 | ||
| 1872 | /* Flush the plane changes */ | 2366 | /* Flush the plane changes */ |
| 1873 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 2367 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
| 2368 | |||
| 2369 | intel_update_watermarks(dev); | ||
| 2370 | |||
| 1874 | drm_vblank_post_modeset(dev, pipe); | 2371 | drm_vblank_post_modeset(dev, pipe); |
| 1875 | 2372 | ||
| 1876 | return ret; | 2373 | return ret; |
| @@ -2359,6 +2856,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
| 2359 | 2856 | ||
| 2360 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); | 2857 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); |
| 2361 | intel_crtc->pipe = pipe; | 2858 | intel_crtc->pipe = pipe; |
| 2859 | intel_crtc->plane = pipe; | ||
| 2362 | for (i = 0; i < 256; i++) { | 2860 | for (i = 0; i < 256; i++) { |
| 2363 | intel_crtc->lut_r[i] = i; | 2861 | intel_crtc->lut_r[i] = i; |
| 2364 | intel_crtc->lut_g[i] = i; | 2862 | intel_crtc->lut_g[i] = i; |
| @@ -2475,6 +2973,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2475 | found = intel_sdvo_init(dev, SDVOB); | 2973 | found = intel_sdvo_init(dev, SDVOB); |
| 2476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2974 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
| 2477 | intel_hdmi_init(dev, SDVOB); | 2975 | intel_hdmi_init(dev, SDVOB); |
| 2976 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
| 2977 | intel_dp_init(dev, DP_B); | ||
| 2478 | } | 2978 | } |
| 2479 | 2979 | ||
| 2480 | /* Before G4X SDVOC doesn't have its own detect register */ | 2980 | /* Before G4X SDVOC doesn't have its own detect register */ |
| @@ -2487,7 +2987,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2487 | found = intel_sdvo_init(dev, SDVOC); | 2987 | found = intel_sdvo_init(dev, SDVOC); |
| 2488 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2988 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
| 2489 | intel_hdmi_init(dev, SDVOC); | 2989 | intel_hdmi_init(dev, SDVOC); |
| 2990 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
| 2991 | intel_dp_init(dev, DP_C); | ||
| 2490 | } | 2992 | } |
| 2993 | if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) | ||
| 2994 | intel_dp_init(dev, DP_D); | ||
| 2491 | } else | 2995 | } else |
| 2492 | intel_dvo_init(dev); | 2996 | intel_dvo_init(dev); |
| 2493 | 2997 | ||
| @@ -2530,6 +3034,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2530 | (1 << 1)); | 3034 | (1 << 1)); |
| 2531 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); | 3035 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); |
| 2532 | break; | 3036 | break; |
| 3037 | case INTEL_OUTPUT_DISPLAYPORT: | ||
| 3038 | crtc_mask = ((1 << 0) | | ||
| 3039 | (1 << 1)); | ||
| 3040 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
| 3041 | break; | ||
| 2533 | } | 3042 | } |
| 2534 | encoder->possible_crtcs = crtc_mask; | 3043 | encoder->possible_crtcs = crtc_mask; |
| 2535 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); | 3044 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c new file mode 100644 index 000000000000..6770ae88370d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -0,0 +1,1156 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Intel Corporation | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 21 | * IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Keith Packard <keithp@keithp.com> | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/i2c.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "drm.h" | ||
| 31 | #include "drm_crtc.h" | ||
| 32 | #include "drm_crtc_helper.h" | ||
| 33 | #include "intel_drv.h" | ||
| 34 | #include "i915_drm.h" | ||
| 35 | #include "i915_drv.h" | ||
| 36 | #include "intel_dp.h" | ||
| 37 | |||
| 38 | #define DP_LINK_STATUS_SIZE 6 | ||
| 39 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | ||
| 40 | |||
| 41 | #define DP_LINK_CONFIGURATION_SIZE 9 | ||
| 42 | |||
| 43 | struct intel_dp_priv { | ||
| 44 | uint32_t output_reg; | ||
| 45 | uint32_t DP; | ||
| 46 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
| 47 | uint32_t save_DP; | ||
| 48 | uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
| 49 | bool has_audio; | ||
| 50 | int dpms_mode; | ||
| 51 | uint8_t link_bw; | ||
| 52 | uint8_t lane_count; | ||
| 53 | uint8_t dpcd[4]; | ||
| 54 | struct intel_output *intel_output; | ||
| 55 | struct i2c_adapter adapter; | ||
| 56 | struct i2c_algo_dp_aux_data algo; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static void | ||
| 60 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
| 61 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]); | ||
| 62 | |||
| 63 | static void | ||
| 64 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP); | ||
| 65 | |||
| 66 | static int | ||
| 67 | intel_dp_max_lane_count(struct intel_output *intel_output) | ||
| 68 | { | ||
| 69 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 70 | int max_lane_count = 4; | ||
| 71 | |||
| 72 | if (dp_priv->dpcd[0] >= 0x11) { | ||
| 73 | max_lane_count = dp_priv->dpcd[2] & 0x1f; | ||
| 74 | switch (max_lane_count) { | ||
| 75 | case 1: case 2: case 4: | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | max_lane_count = 4; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | return max_lane_count; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int | ||
| 85 | intel_dp_max_link_bw(struct intel_output *intel_output) | ||
| 86 | { | ||
| 87 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 88 | int max_link_bw = dp_priv->dpcd[1]; | ||
| 89 | |||
| 90 | switch (max_link_bw) { | ||
| 91 | case DP_LINK_BW_1_62: | ||
| 92 | case DP_LINK_BW_2_7: | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | max_link_bw = DP_LINK_BW_1_62; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | return max_link_bw; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int | ||
| 102 | intel_dp_link_clock(uint8_t link_bw) | ||
| 103 | { | ||
| 104 | if (link_bw == DP_LINK_BW_2_7) | ||
| 105 | return 270000; | ||
| 106 | else | ||
| 107 | return 162000; | ||
| 108 | } | ||
| 109 | |||
| 110 | /* I think this is a fiction */ | ||
| 111 | static int | ||
| 112 | intel_dp_link_required(int pixel_clock) | ||
| 113 | { | ||
| 114 | return pixel_clock * 3; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int | ||
| 118 | intel_dp_mode_valid(struct drm_connector *connector, | ||
| 119 | struct drm_display_mode *mode) | ||
| 120 | { | ||
| 121 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 122 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); | ||
| 123 | int max_lanes = intel_dp_max_lane_count(intel_output); | ||
| 124 | |||
| 125 | if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) | ||
| 126 | return MODE_CLOCK_HIGH; | ||
| 127 | |||
| 128 | if (mode->clock < 10000) | ||
| 129 | return MODE_CLOCK_LOW; | ||
| 130 | |||
| 131 | return MODE_OK; | ||
| 132 | } | ||
| 133 | |||
| 134 | static uint32_t | ||
| 135 | pack_aux(uint8_t *src, int src_bytes) | ||
| 136 | { | ||
| 137 | int i; | ||
| 138 | uint32_t v = 0; | ||
| 139 | |||
| 140 | if (src_bytes > 4) | ||
| 141 | src_bytes = 4; | ||
| 142 | for (i = 0; i < src_bytes; i++) | ||
| 143 | v |= ((uint32_t) src[i]) << ((3-i) * 8); | ||
| 144 | return v; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void | ||
| 148 | unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) | ||
| 149 | { | ||
| 150 | int i; | ||
| 151 | if (dst_bytes > 4) | ||
| 152 | dst_bytes = 4; | ||
| 153 | for (i = 0; i < dst_bytes; i++) | ||
| 154 | dst[i] = src >> ((3-i) * 8); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* hrawclock is 1/4 the FSB frequency */ | ||
| 158 | static int | ||
| 159 | intel_hrawclk(struct drm_device *dev) | ||
| 160 | { | ||
| 161 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 162 | uint32_t clkcfg; | ||
| 163 | |||
| 164 | clkcfg = I915_READ(CLKCFG); | ||
| 165 | switch (clkcfg & CLKCFG_FSB_MASK) { | ||
| 166 | case CLKCFG_FSB_400: | ||
| 167 | return 100; | ||
| 168 | case CLKCFG_FSB_533: | ||
| 169 | return 133; | ||
| 170 | case CLKCFG_FSB_667: | ||
| 171 | return 166; | ||
| 172 | case CLKCFG_FSB_800: | ||
| 173 | return 200; | ||
| 174 | case CLKCFG_FSB_1067: | ||
| 175 | return 266; | ||
| 176 | case CLKCFG_FSB_1333: | ||
| 177 | return 333; | ||
| 178 | /* these two are just a guess; one of them might be right */ | ||
| 179 | case CLKCFG_FSB_1600: | ||
| 180 | case CLKCFG_FSB_1600_ALT: | ||
| 181 | return 400; | ||
| 182 | default: | ||
| 183 | return 133; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | intel_dp_aux_ch(struct intel_output *intel_output, | ||
| 189 | uint8_t *send, int send_bytes, | ||
| 190 | uint8_t *recv, int recv_size) | ||
| 191 | { | ||
| 192 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 193 | uint32_t output_reg = dp_priv->output_reg; | ||
| 194 | struct drm_device *dev = intel_output->base.dev; | ||
| 195 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 196 | uint32_t ch_ctl = output_reg + 0x10; | ||
| 197 | uint32_t ch_data = ch_ctl + 4; | ||
| 198 | int i; | ||
| 199 | int recv_bytes; | ||
| 200 | uint32_t ctl; | ||
| 201 | uint32_t status; | ||
| 202 | uint32_t aux_clock_divider; | ||
| 203 | int try; | ||
| 204 | |||
| 205 | /* The clock divider is based off the hrawclk, | ||
| 206 | * and would like to run at 2MHz. So, take the | ||
| 207 | * hrawclk value and divide by 2 and use that | ||
| 208 | */ | ||
| 209 | aux_clock_divider = intel_hrawclk(dev) / 2; | ||
| 210 | /* Must try at least 3 times according to DP spec */ | ||
| 211 | for (try = 0; try < 5; try++) { | ||
| 212 | /* Load the send data into the aux channel data registers */ | ||
| 213 | for (i = 0; i < send_bytes; i += 4) { | ||
| 214 | uint32_t d = pack_aux(send + i, send_bytes - i);; | ||
| 215 | |||
| 216 | I915_WRITE(ch_data + i, d); | ||
| 217 | } | ||
| 218 | |||
| 219 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | | ||
| 220 | DP_AUX_CH_CTL_TIME_OUT_400us | | ||
| 221 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | ||
| 222 | (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | ||
| 223 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | ||
| 224 | DP_AUX_CH_CTL_DONE | | ||
| 225 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
| 226 | DP_AUX_CH_CTL_RECEIVE_ERROR); | ||
| 227 | |||
| 228 | /* Send the command and wait for it to complete */ | ||
| 229 | I915_WRITE(ch_ctl, ctl); | ||
| 230 | (void) I915_READ(ch_ctl); | ||
| 231 | for (;;) { | ||
| 232 | udelay(100); | ||
| 233 | status = I915_READ(ch_ctl); | ||
| 234 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* Clear done status and any errors */ | ||
| 239 | I915_WRITE(ch_ctl, (ctl | | ||
| 240 | DP_AUX_CH_CTL_DONE | | ||
| 241 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
| 242 | DP_AUX_CH_CTL_RECEIVE_ERROR)); | ||
| 243 | (void) I915_READ(ch_ctl); | ||
| 244 | if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { | ||
| 249 | DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); | ||
| 250 | return -EBUSY; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* Check for timeout or receive error. | ||
| 254 | * Timeouts occur when the sink is not connected | ||
| 255 | */ | ||
| 256 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { | ||
| 257 | DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); | ||
| 258 | return -EIO; | ||
| 259 | } | ||
| 260 | |||
| 261 | /* Timeouts occur when the device isn't connected, so they're | ||
| 262 | * "normal" -- don't fill the kernel log with these */ | ||
| 263 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { | ||
| 264 | DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status); | ||
| 265 | return -ETIMEDOUT; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* Unload any bytes sent back from the other side */ | ||
| 269 | recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> | ||
| 270 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); | ||
| 271 | |||
| 272 | if (recv_bytes > recv_size) | ||
| 273 | recv_bytes = recv_size; | ||
| 274 | |||
| 275 | for (i = 0; i < recv_bytes; i += 4) { | ||
| 276 | uint32_t d = I915_READ(ch_data + i); | ||
| 277 | |||
| 278 | unpack_aux(d, recv + i, recv_bytes - i); | ||
| 279 | } | ||
| 280 | |||
| 281 | return recv_bytes; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* Write data to the aux channel in native mode */ | ||
| 285 | static int | ||
| 286 | intel_dp_aux_native_write(struct intel_output *intel_output, | ||
| 287 | uint16_t address, uint8_t *send, int send_bytes) | ||
| 288 | { | ||
| 289 | int ret; | ||
| 290 | uint8_t msg[20]; | ||
| 291 | int msg_bytes; | ||
| 292 | uint8_t ack; | ||
| 293 | |||
| 294 | if (send_bytes > 16) | ||
| 295 | return -1; | ||
| 296 | msg[0] = AUX_NATIVE_WRITE << 4; | ||
| 297 | msg[1] = address >> 8; | ||
| 298 | msg[2] = address; | ||
| 299 | msg[3] = send_bytes - 1; | ||
| 300 | memcpy(&msg[4], send, send_bytes); | ||
| 301 | msg_bytes = send_bytes + 4; | ||
| 302 | for (;;) { | ||
| 303 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1); | ||
| 304 | if (ret < 0) | ||
| 305 | return ret; | ||
| 306 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) | ||
| 307 | break; | ||
| 308 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
| 309 | udelay(100); | ||
| 310 | else | ||
| 311 | return -EIO; | ||
| 312 | } | ||
| 313 | return send_bytes; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* Write a single byte to the aux channel in native mode */ | ||
| 317 | static int | ||
| 318 | intel_dp_aux_native_write_1(struct intel_output *intel_output, | ||
| 319 | uint16_t address, uint8_t byte) | ||
| 320 | { | ||
| 321 | return intel_dp_aux_native_write(intel_output, address, &byte, 1); | ||
| 322 | } | ||
| 323 | |||
| 324 | /* read bytes from a native aux channel */ | ||
| 325 | static int | ||
| 326 | intel_dp_aux_native_read(struct intel_output *intel_output, | ||
| 327 | uint16_t address, uint8_t *recv, int recv_bytes) | ||
| 328 | { | ||
| 329 | uint8_t msg[4]; | ||
| 330 | int msg_bytes; | ||
| 331 | uint8_t reply[20]; | ||
| 332 | int reply_bytes; | ||
| 333 | uint8_t ack; | ||
| 334 | int ret; | ||
| 335 | |||
| 336 | msg[0] = AUX_NATIVE_READ << 4; | ||
| 337 | msg[1] = address >> 8; | ||
| 338 | msg[2] = address & 0xff; | ||
| 339 | msg[3] = recv_bytes - 1; | ||
| 340 | |||
| 341 | msg_bytes = 4; | ||
| 342 | reply_bytes = recv_bytes + 1; | ||
| 343 | |||
| 344 | for (;;) { | ||
| 345 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, | ||
| 346 | reply, reply_bytes); | ||
| 347 | if (ret == 0) | ||
| 348 | return -EPROTO; | ||
| 349 | if (ret < 0) | ||
| 350 | return ret; | ||
| 351 | ack = reply[0]; | ||
| 352 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { | ||
| 353 | memcpy(recv, reply + 1, ret - 1); | ||
| 354 | return ret - 1; | ||
| 355 | } | ||
| 356 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
| 357 | udelay(100); | ||
| 358 | else | ||
| 359 | return -EIO; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | static int | ||
| 364 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, | ||
| 365 | uint8_t *send, int send_bytes, | ||
| 366 | uint8_t *recv, int recv_bytes) | ||
| 367 | { | ||
| 368 | struct intel_dp_priv *dp_priv = container_of(adapter, | ||
| 369 | struct intel_dp_priv, | ||
| 370 | adapter); | ||
| 371 | struct intel_output *intel_output = dp_priv->intel_output; | ||
| 372 | |||
| 373 | return intel_dp_aux_ch(intel_output, | ||
| 374 | send, send_bytes, recv, recv_bytes); | ||
| 375 | } | ||
| 376 | |||
| 377 | static int | ||
| 378 | intel_dp_i2c_init(struct intel_output *intel_output, const char *name) | ||
| 379 | { | ||
| 380 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 381 | |||
| 382 | DRM_ERROR("i2c_init %s\n", name); | ||
| 383 | dp_priv->algo.running = false; | ||
| 384 | dp_priv->algo.address = 0; | ||
| 385 | dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch; | ||
| 386 | |||
| 387 | memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter)); | ||
| 388 | dp_priv->adapter.owner = THIS_MODULE; | ||
| 389 | dp_priv->adapter.class = I2C_CLASS_DDC; | ||
| 390 | strncpy (dp_priv->adapter.name, name, sizeof dp_priv->adapter.name - 1); | ||
| 391 | dp_priv->adapter.name[sizeof dp_priv->adapter.name - 1] = '\0'; | ||
| 392 | dp_priv->adapter.algo_data = &dp_priv->algo; | ||
| 393 | dp_priv->adapter.dev.parent = &intel_output->base.kdev; | ||
| 394 | |||
| 395 | return i2c_dp_aux_add_bus(&dp_priv->adapter); | ||
| 396 | } | ||
| 397 | |||
| 398 | static bool | ||
| 399 | intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
| 400 | struct drm_display_mode *adjusted_mode) | ||
| 401 | { | ||
| 402 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 403 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 404 | int lane_count, clock; | ||
| 405 | int max_lane_count = intel_dp_max_lane_count(intel_output); | ||
| 406 | int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0; | ||
| 407 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | ||
| 408 | |||
| 409 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | ||
| 410 | for (clock = 0; clock <= max_clock; clock++) { | ||
| 411 | int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; | ||
| 412 | |||
| 413 | if (intel_dp_link_required(mode->clock) <= link_avail) { | ||
| 414 | dp_priv->link_bw = bws[clock]; | ||
| 415 | dp_priv->lane_count = lane_count; | ||
| 416 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); | ||
| 417 | DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n", | ||
| 418 | dp_priv->link_bw, dp_priv->lane_count, | ||
| 419 | adjusted_mode->clock); | ||
| 420 | return true; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | } | ||
| 424 | return false; | ||
| 425 | } | ||
| 426 | |||
| 427 | struct intel_dp_m_n { | ||
| 428 | uint32_t tu; | ||
| 429 | uint32_t gmch_m; | ||
| 430 | uint32_t gmch_n; | ||
| 431 | uint32_t link_m; | ||
| 432 | uint32_t link_n; | ||
| 433 | }; | ||
| 434 | |||
| 435 | static void | ||
| 436 | intel_reduce_ratio(uint32_t *num, uint32_t *den) | ||
| 437 | { | ||
| 438 | while (*num > 0xffffff || *den > 0xffffff) { | ||
| 439 | *num >>= 1; | ||
| 440 | *den >>= 1; | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | static void | ||
| 445 | intel_dp_compute_m_n(int bytes_per_pixel, | ||
| 446 | int nlanes, | ||
| 447 | int pixel_clock, | ||
| 448 | int link_clock, | ||
| 449 | struct intel_dp_m_n *m_n) | ||
| 450 | { | ||
| 451 | m_n->tu = 64; | ||
| 452 | m_n->gmch_m = pixel_clock * bytes_per_pixel; | ||
| 453 | m_n->gmch_n = link_clock * nlanes; | ||
| 454 | intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | ||
| 455 | m_n->link_m = pixel_clock; | ||
| 456 | m_n->link_n = link_clock; | ||
| 457 | intel_reduce_ratio(&m_n->link_m, &m_n->link_n); | ||
| 458 | } | ||
| 459 | |||
| 460 | void | ||
| 461 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
| 462 | struct drm_display_mode *adjusted_mode) | ||
| 463 | { | ||
| 464 | struct drm_device *dev = crtc->dev; | ||
| 465 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 466 | struct drm_connector *connector; | ||
| 467 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 468 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 469 | int lane_count = 4; | ||
| 470 | struct intel_dp_m_n m_n; | ||
| 471 | |||
| 472 | /* | ||
| 473 | * Find the lane count in the intel_output private | ||
| 474 | */ | ||
| 475 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 476 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 477 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 478 | |||
| 479 | if (!connector->encoder || connector->encoder->crtc != crtc) | ||
| 480 | continue; | ||
| 481 | |||
| 482 | if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { | ||
| 483 | lane_count = dp_priv->lane_count; | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | /* | ||
| 489 | * Compute the GMCH and Link ratios. The '3' here is | ||
| 490 | * the number of bytes_per_pixel post-LUT, which we always | ||
| 491 | * set up for 8-bits of R/G/B, or 3 bytes total. | ||
| 492 | */ | ||
| 493 | intel_dp_compute_m_n(3, lane_count, | ||
| 494 | mode->clock, adjusted_mode->clock, &m_n); | ||
| 495 | |||
| 496 | if (intel_crtc->pipe == 0) { | ||
| 497 | I915_WRITE(PIPEA_GMCH_DATA_M, | ||
| 498 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 499 | m_n.gmch_m); | ||
| 500 | I915_WRITE(PIPEA_GMCH_DATA_N, | ||
| 501 | m_n.gmch_n); | ||
| 502 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | ||
| 503 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
| 504 | } else { | ||
| 505 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
| 506 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 507 | m_n.gmch_m); | ||
| 508 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
| 509 | m_n.gmch_n); | ||
| 510 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
| 511 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
| 512 | } | ||
| 513 | } | ||
| 514 | |||
| 515 | static void | ||
| 516 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
| 517 | struct drm_display_mode *adjusted_mode) | ||
| 518 | { | ||
| 519 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 520 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 521 | struct drm_crtc *crtc = intel_output->enc.crtc; | ||
| 522 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 523 | |||
| 524 | dp_priv->DP = (DP_LINK_TRAIN_OFF | | ||
| 525 | DP_VOLTAGE_0_4 | | ||
| 526 | DP_PRE_EMPHASIS_0 | | ||
| 527 | DP_SYNC_VS_HIGH | | ||
| 528 | DP_SYNC_HS_HIGH); | ||
| 529 | |||
| 530 | switch (dp_priv->lane_count) { | ||
| 531 | case 1: | ||
| 532 | dp_priv->DP |= DP_PORT_WIDTH_1; | ||
| 533 | break; | ||
| 534 | case 2: | ||
| 535 | dp_priv->DP |= DP_PORT_WIDTH_2; | ||
| 536 | break; | ||
| 537 | case 4: | ||
| 538 | dp_priv->DP |= DP_PORT_WIDTH_4; | ||
| 539 | break; | ||
| 540 | } | ||
| 541 | if (dp_priv->has_audio) | ||
| 542 | dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE; | ||
| 543 | |||
| 544 | memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); | ||
| 545 | dp_priv->link_configuration[0] = dp_priv->link_bw; | ||
| 546 | dp_priv->link_configuration[1] = dp_priv->lane_count; | ||
| 547 | |||
| 548 | /* | ||
| 549 | * Check for DPCD version > 1.1, | ||
| 550 | * enable enahanced frame stuff in that case | ||
| 551 | */ | ||
| 552 | if (dp_priv->dpcd[0] >= 0x11) { | ||
| 553 | dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | ||
| 554 | dp_priv->DP |= DP_ENHANCED_FRAMING; | ||
| 555 | } | ||
| 556 | |||
| 557 | if (intel_crtc->pipe == 1) | ||
| 558 | dp_priv->DP |= DP_PIPEB_SELECT; | ||
| 559 | } | ||
| 560 | |||
| 561 | |||
| 562 | static void | ||
| 563 | intel_dp_dpms(struct drm_encoder *encoder, int mode) | ||
| 564 | { | ||
| 565 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 566 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 567 | struct drm_device *dev = intel_output->base.dev; | ||
| 568 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 569 | uint32_t dp_reg = I915_READ(dp_priv->output_reg); | ||
| 570 | |||
| 571 | if (mode != DRM_MODE_DPMS_ON) { | ||
| 572 | if (dp_reg & DP_PORT_EN) | ||
| 573 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
| 574 | } else { | ||
| 575 | if (!(dp_reg & DP_PORT_EN)) | ||
| 576 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
| 577 | } | ||
| 578 | dp_priv->dpms_mode = mode; | ||
| 579 | } | ||
| 580 | |||
| 581 | /* | ||
| 582 | * Fetch AUX CH registers 0x202 - 0x207 which contain | ||
| 583 | * link status information | ||
| 584 | */ | ||
| 585 | static bool | ||
| 586 | intel_dp_get_link_status(struct intel_output *intel_output, | ||
| 587 | uint8_t link_status[DP_LINK_STATUS_SIZE]) | ||
| 588 | { | ||
| 589 | int ret; | ||
| 590 | |||
| 591 | ret = intel_dp_aux_native_read(intel_output, | ||
| 592 | DP_LANE0_1_STATUS, | ||
| 593 | link_status, DP_LINK_STATUS_SIZE); | ||
| 594 | if (ret != DP_LINK_STATUS_SIZE) | ||
| 595 | return false; | ||
| 596 | return true; | ||
| 597 | } | ||
| 598 | |||
| 599 | static uint8_t | ||
| 600 | intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 601 | int r) | ||
| 602 | { | ||
| 603 | return link_status[r - DP_LANE0_1_STATUS]; | ||
| 604 | } | ||
| 605 | |||
| 606 | static void | ||
| 607 | intel_dp_save(struct drm_connector *connector) | ||
| 608 | { | ||
| 609 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 610 | struct drm_device *dev = intel_output->base.dev; | ||
| 611 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 612 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 613 | |||
| 614 | dp_priv->save_DP = I915_READ(dp_priv->output_reg); | ||
| 615 | intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET, | ||
| 616 | dp_priv->save_link_configuration, | ||
| 617 | sizeof (dp_priv->save_link_configuration)); | ||
| 618 | } | ||
| 619 | |||
| 620 | static uint8_t | ||
| 621 | intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 622 | int lane) | ||
| 623 | { | ||
| 624 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 625 | int s = ((lane & 1) ? | ||
| 626 | DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : | ||
| 627 | DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); | ||
| 628 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 629 | |||
| 630 | return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; | ||
| 631 | } | ||
| 632 | |||
| 633 | static uint8_t | ||
| 634 | intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 635 | int lane) | ||
| 636 | { | ||
| 637 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 638 | int s = ((lane & 1) ? | ||
| 639 | DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : | ||
| 640 | DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); | ||
| 641 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 642 | |||
| 643 | return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; | ||
| 644 | } | ||
| 645 | |||
| 646 | |||
| 647 | #if 0 | ||
| 648 | static char *voltage_names[] = { | ||
| 649 | "0.4V", "0.6V", "0.8V", "1.2V" | ||
| 650 | }; | ||
| 651 | static char *pre_emph_names[] = { | ||
| 652 | "0dB", "3.5dB", "6dB", "9.5dB" | ||
| 653 | }; | ||
| 654 | static char *link_train_names[] = { | ||
| 655 | "pattern 1", "pattern 2", "idle", "off" | ||
| 656 | }; | ||
| 657 | #endif | ||
| 658 | |||
| 659 | /* | ||
| 660 | * These are source-specific values; current Intel hardware supports | ||
| 661 | * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB | ||
| 662 | */ | ||
| 663 | #define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 | ||
| 664 | |||
| 665 | static uint8_t | ||
| 666 | intel_dp_pre_emphasis_max(uint8_t voltage_swing) | ||
| 667 | { | ||
| 668 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
| 669 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
| 670 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
| 671 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
| 672 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
| 673 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
| 674 | return DP_TRAIN_PRE_EMPHASIS_3_5; | ||
| 675 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
| 676 | default: | ||
| 677 | return DP_TRAIN_PRE_EMPHASIS_0; | ||
| 678 | } | ||
| 679 | } | ||
| 680 | |||
| 681 | static void | ||
| 682 | intel_get_adjust_train(struct intel_output *intel_output, | ||
| 683 | uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 684 | int lane_count, | ||
| 685 | uint8_t train_set[4]) | ||
| 686 | { | ||
| 687 | uint8_t v = 0; | ||
| 688 | uint8_t p = 0; | ||
| 689 | int lane; | ||
| 690 | |||
| 691 | for (lane = 0; lane < lane_count; lane++) { | ||
| 692 | uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); | ||
| 693 | uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); | ||
| 694 | |||
| 695 | if (this_v > v) | ||
| 696 | v = this_v; | ||
| 697 | if (this_p > p) | ||
| 698 | p = this_p; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (v >= I830_DP_VOLTAGE_MAX) | ||
| 702 | v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; | ||
| 703 | |||
| 704 | if (p >= intel_dp_pre_emphasis_max(v)) | ||
| 705 | p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | ||
| 706 | |||
| 707 | for (lane = 0; lane < 4; lane++) | ||
| 708 | train_set[lane] = v | p; | ||
| 709 | } | ||
| 710 | |||
| 711 | static uint32_t | ||
| 712 | intel_dp_signal_levels(uint8_t train_set, int lane_count) | ||
| 713 | { | ||
| 714 | uint32_t signal_levels = 0; | ||
| 715 | |||
| 716 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
| 717 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
| 718 | default: | ||
| 719 | signal_levels |= DP_VOLTAGE_0_4; | ||
| 720 | break; | ||
| 721 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
| 722 | signal_levels |= DP_VOLTAGE_0_6; | ||
| 723 | break; | ||
| 724 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
| 725 | signal_levels |= DP_VOLTAGE_0_8; | ||
| 726 | break; | ||
| 727 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
| 728 | signal_levels |= DP_VOLTAGE_1_2; | ||
| 729 | break; | ||
| 730 | } | ||
| 731 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { | ||
| 732 | case DP_TRAIN_PRE_EMPHASIS_0: | ||
| 733 | default: | ||
| 734 | signal_levels |= DP_PRE_EMPHASIS_0; | ||
| 735 | break; | ||
| 736 | case DP_TRAIN_PRE_EMPHASIS_3_5: | ||
| 737 | signal_levels |= DP_PRE_EMPHASIS_3_5; | ||
| 738 | break; | ||
| 739 | case DP_TRAIN_PRE_EMPHASIS_6: | ||
| 740 | signal_levels |= DP_PRE_EMPHASIS_6; | ||
| 741 | break; | ||
| 742 | case DP_TRAIN_PRE_EMPHASIS_9_5: | ||
| 743 | signal_levels |= DP_PRE_EMPHASIS_9_5; | ||
| 744 | break; | ||
| 745 | } | ||
| 746 | return signal_levels; | ||
| 747 | } | ||
| 748 | |||
| 749 | static uint8_t | ||
| 750 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 751 | int lane) | ||
| 752 | { | ||
| 753 | int i = DP_LANE0_1_STATUS + (lane >> 1); | ||
| 754 | int s = (lane & 1) * 4; | ||
| 755 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 756 | |||
| 757 | return (l >> s) & 0xf; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* Check for clock recovery is done on all channels */ | ||
| 761 | static bool | ||
| 762 | intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
| 763 | { | ||
| 764 | int lane; | ||
| 765 | uint8_t lane_status; | ||
| 766 | |||
| 767 | for (lane = 0; lane < lane_count; lane++) { | ||
| 768 | lane_status = intel_get_lane_status(link_status, lane); | ||
| 769 | if ((lane_status & DP_LANE_CR_DONE) == 0) | ||
| 770 | return false; | ||
| 771 | } | ||
| 772 | return true; | ||
| 773 | } | ||
| 774 | |||
| 775 | /* Check to see if channel eq is done on all channels */ | ||
| 776 | #define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ | ||
| 777 | DP_LANE_CHANNEL_EQ_DONE|\ | ||
| 778 | DP_LANE_SYMBOL_LOCKED) | ||
| 779 | static bool | ||
| 780 | intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
| 781 | { | ||
| 782 | uint8_t lane_align; | ||
| 783 | uint8_t lane_status; | ||
| 784 | int lane; | ||
| 785 | |||
| 786 | lane_align = intel_dp_link_status(link_status, | ||
| 787 | DP_LANE_ALIGN_STATUS_UPDATED); | ||
| 788 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) | ||
| 789 | return false; | ||
| 790 | for (lane = 0; lane < lane_count; lane++) { | ||
| 791 | lane_status = intel_get_lane_status(link_status, lane); | ||
| 792 | if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) | ||
| 793 | return false; | ||
| 794 | } | ||
| 795 | return true; | ||
| 796 | } | ||
| 797 | |||
| 798 | static bool | ||
| 799 | intel_dp_set_link_train(struct intel_output *intel_output, | ||
| 800 | uint32_t dp_reg_value, | ||
| 801 | uint8_t dp_train_pat, | ||
| 802 | uint8_t train_set[4], | ||
| 803 | bool first) | ||
| 804 | { | ||
| 805 | struct drm_device *dev = intel_output->base.dev; | ||
| 806 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 807 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 808 | int ret; | ||
| 809 | |||
| 810 | I915_WRITE(dp_priv->output_reg, dp_reg_value); | ||
| 811 | POSTING_READ(dp_priv->output_reg); | ||
| 812 | if (first) | ||
| 813 | intel_wait_for_vblank(dev); | ||
| 814 | |||
| 815 | intel_dp_aux_native_write_1(intel_output, | ||
| 816 | DP_TRAINING_PATTERN_SET, | ||
| 817 | dp_train_pat); | ||
| 818 | |||
| 819 | ret = intel_dp_aux_native_write(intel_output, | ||
| 820 | DP_TRAINING_LANE0_SET, train_set, 4); | ||
| 821 | if (ret != 4) | ||
| 822 | return false; | ||
| 823 | |||
| 824 | return true; | ||
| 825 | } | ||
| 826 | |||
| 827 | static void | ||
| 828 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
| 829 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]) | ||
| 830 | { | ||
| 831 | struct drm_device *dev = intel_output->base.dev; | ||
| 832 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 833 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 834 | uint8_t train_set[4]; | ||
| 835 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
| 836 | int i; | ||
| 837 | uint8_t voltage; | ||
| 838 | bool clock_recovery = false; | ||
| 839 | bool channel_eq = false; | ||
| 840 | bool first = true; | ||
| 841 | int tries; | ||
| 842 | |||
| 843 | /* Write the link configuration data */ | ||
| 844 | intel_dp_aux_native_write(intel_output, 0x100, | ||
| 845 | link_configuration, DP_LINK_CONFIGURATION_SIZE); | ||
| 846 | |||
| 847 | DP |= DP_PORT_EN; | ||
| 848 | DP &= ~DP_LINK_TRAIN_MASK; | ||
| 849 | memset(train_set, 0, 4); | ||
| 850 | voltage = 0xff; | ||
| 851 | tries = 0; | ||
| 852 | clock_recovery = false; | ||
| 853 | for (;;) { | ||
| 854 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
| 855 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
| 856 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
| 857 | |||
| 858 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1, | ||
| 859 | DP_TRAINING_PATTERN_1, train_set, first)) | ||
| 860 | break; | ||
| 861 | first = false; | ||
| 862 | /* Set training pattern 1 */ | ||
| 863 | |||
| 864 | udelay(100); | ||
| 865 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
| 866 | break; | ||
| 867 | |||
| 868 | if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) { | ||
| 869 | clock_recovery = true; | ||
| 870 | break; | ||
| 871 | } | ||
| 872 | |||
| 873 | /* Check to see if we've tried the max voltage */ | ||
| 874 | for (i = 0; i < dp_priv->lane_count; i++) | ||
| 875 | if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | ||
| 876 | break; | ||
| 877 | if (i == dp_priv->lane_count) | ||
| 878 | break; | ||
| 879 | |||
| 880 | /* Check to see if we've tried the same voltage 5 times */ | ||
| 881 | if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | ||
| 882 | ++tries; | ||
| 883 | if (tries == 5) | ||
| 884 | break; | ||
| 885 | } else | ||
| 886 | tries = 0; | ||
| 887 | voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
| 888 | |||
| 889 | /* Compute new train_set as requested by target */ | ||
| 890 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
| 891 | } | ||
| 892 | |||
| 893 | /* channel equalization */ | ||
| 894 | tries = 0; | ||
| 895 | channel_eq = false; | ||
| 896 | for (;;) { | ||
| 897 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
| 898 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
| 899 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
| 900 | |||
| 901 | /* channel eq pattern */ | ||
| 902 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2, | ||
| 903 | DP_TRAINING_PATTERN_2, train_set, | ||
| 904 | false)) | ||
| 905 | break; | ||
| 906 | |||
| 907 | udelay(400); | ||
| 908 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
| 909 | break; | ||
| 910 | |||
| 911 | if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) { | ||
| 912 | channel_eq = true; | ||
| 913 | break; | ||
| 914 | } | ||
| 915 | |||
| 916 | /* Try 5 times */ | ||
| 917 | if (tries > 5) | ||
| 918 | break; | ||
| 919 | |||
| 920 | /* Compute new train_set as requested by target */ | ||
| 921 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
| 922 | ++tries; | ||
| 923 | } | ||
| 924 | |||
| 925 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF); | ||
| 926 | POSTING_READ(dp_priv->output_reg); | ||
| 927 | intel_dp_aux_native_write_1(intel_output, | ||
| 928 | DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); | ||
| 929 | } | ||
| 930 | |||
| 931 | static void | ||
| 932 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) | ||
| 933 | { | ||
| 934 | struct drm_device *dev = intel_output->base.dev; | ||
| 935 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 936 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 937 | |||
| 938 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); | ||
| 939 | POSTING_READ(dp_priv->output_reg); | ||
| 940 | } | ||
| 941 | |||
| 942 | static void | ||
| 943 | intel_dp_restore(struct drm_connector *connector) | ||
| 944 | { | ||
| 945 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 946 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 947 | |||
| 948 | if (dp_priv->save_DP & DP_PORT_EN) | ||
| 949 | intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration); | ||
| 950 | else | ||
| 951 | intel_dp_link_down(intel_output, dp_priv->save_DP); | ||
| 952 | } | ||
| 953 | |||
| 954 | /* | ||
| 955 | * According to DP spec | ||
| 956 | * 5.1.2: | ||
| 957 | * 1. Read DPCD | ||
| 958 | * 2. Configure link according to Receiver Capabilities | ||
| 959 | * 3. Use Link Training from 2.5.3.3 and 3.5.1.3 | ||
| 960 | * 4. Check link status on receipt of hot-plug interrupt | ||
| 961 | */ | ||
| 962 | |||
| 963 | static void | ||
| 964 | intel_dp_check_link_status(struct intel_output *intel_output) | ||
| 965 | { | ||
| 966 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 967 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
| 968 | |||
| 969 | if (!intel_output->enc.crtc) | ||
| 970 | return; | ||
| 971 | |||
| 972 | if (!intel_dp_get_link_status(intel_output, link_status)) { | ||
| 973 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
| 974 | return; | ||
| 975 | } | ||
| 976 | |||
| 977 | if (!intel_channel_eq_ok(link_status, dp_priv->lane_count)) | ||
| 978 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
| 979 | } | ||
| 980 | |||
| 981 | /** | ||
| 982 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. | ||
| 983 | * | ||
| 984 | * \return true if DP port is connected. | ||
| 985 | * \return false if DP port is disconnected. | ||
| 986 | */ | ||
| 987 | static enum drm_connector_status | ||
| 988 | intel_dp_detect(struct drm_connector *connector) | ||
| 989 | { | ||
| 990 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 991 | struct drm_device *dev = intel_output->base.dev; | ||
| 992 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 993 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 994 | uint32_t temp, bit; | ||
| 995 | enum drm_connector_status status; | ||
| 996 | |||
| 997 | dp_priv->has_audio = false; | ||
| 998 | |||
| 999 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
| 1000 | |||
| 1001 | I915_WRITE(PORT_HOTPLUG_EN, | ||
| 1002 | temp | | ||
| 1003 | DPB_HOTPLUG_INT_EN | | ||
| 1004 | DPC_HOTPLUG_INT_EN | | ||
| 1005 | DPD_HOTPLUG_INT_EN); | ||
| 1006 | |||
| 1007 | POSTING_READ(PORT_HOTPLUG_EN); | ||
| 1008 | |||
| 1009 | switch (dp_priv->output_reg) { | ||
| 1010 | case DP_B: | ||
| 1011 | bit = DPB_HOTPLUG_INT_STATUS; | ||
| 1012 | break; | ||
| 1013 | case DP_C: | ||
| 1014 | bit = DPC_HOTPLUG_INT_STATUS; | ||
| 1015 | break; | ||
| 1016 | case DP_D: | ||
| 1017 | bit = DPD_HOTPLUG_INT_STATUS; | ||
| 1018 | break; | ||
| 1019 | default: | ||
| 1020 | return connector_status_unknown; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
| 1024 | |||
| 1025 | if ((temp & bit) == 0) | ||
| 1026 | return connector_status_disconnected; | ||
| 1027 | |||
| 1028 | status = connector_status_disconnected; | ||
| 1029 | if (intel_dp_aux_native_read(intel_output, | ||
| 1030 | 0x000, dp_priv->dpcd, | ||
| 1031 | sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) | ||
| 1032 | { | ||
| 1033 | if (dp_priv->dpcd[0] != 0) | ||
| 1034 | status = connector_status_connected; | ||
| 1035 | } | ||
| 1036 | return status; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | static int intel_dp_get_modes(struct drm_connector *connector) | ||
| 1040 | { | ||
| 1041 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 1042 | |||
| 1043 | /* We should parse the EDID data and find out if it has an audio sink | ||
| 1044 | */ | ||
| 1045 | |||
| 1046 | return intel_ddc_get_modes(intel_output); | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | static void | ||
| 1050 | intel_dp_destroy (struct drm_connector *connector) | ||
| 1051 | { | ||
| 1052 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 1053 | |||
| 1054 | if (intel_output->i2c_bus) | ||
| 1055 | intel_i2c_destroy(intel_output->i2c_bus); | ||
| 1056 | drm_sysfs_connector_remove(connector); | ||
| 1057 | drm_connector_cleanup(connector); | ||
| 1058 | kfree(intel_output); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { | ||
| 1062 | .dpms = intel_dp_dpms, | ||
| 1063 | .mode_fixup = intel_dp_mode_fixup, | ||
| 1064 | .prepare = intel_encoder_prepare, | ||
| 1065 | .mode_set = intel_dp_mode_set, | ||
| 1066 | .commit = intel_encoder_commit, | ||
| 1067 | }; | ||
| 1068 | |||
| 1069 | static const struct drm_connector_funcs intel_dp_connector_funcs = { | ||
| 1070 | .dpms = drm_helper_connector_dpms, | ||
| 1071 | .save = intel_dp_save, | ||
| 1072 | .restore = intel_dp_restore, | ||
| 1073 | .detect = intel_dp_detect, | ||
| 1074 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
| 1075 | .destroy = intel_dp_destroy, | ||
| 1076 | }; | ||
| 1077 | |||
| 1078 | static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { | ||
| 1079 | .get_modes = intel_dp_get_modes, | ||
| 1080 | .mode_valid = intel_dp_mode_valid, | ||
| 1081 | .best_encoder = intel_best_encoder, | ||
| 1082 | }; | ||
| 1083 | |||
| 1084 | static void intel_dp_enc_destroy(struct drm_encoder *encoder) | ||
| 1085 | { | ||
| 1086 | drm_encoder_cleanup(encoder); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static const struct drm_encoder_funcs intel_dp_enc_funcs = { | ||
| 1090 | .destroy = intel_dp_enc_destroy, | ||
| 1091 | }; | ||
| 1092 | |||
| 1093 | void | ||
| 1094 | intel_dp_hot_plug(struct intel_output *intel_output) | ||
| 1095 | { | ||
| 1096 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 1097 | |||
| 1098 | if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) | ||
| 1099 | intel_dp_check_link_status(intel_output); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | void | ||
| 1103 | intel_dp_init(struct drm_device *dev, int output_reg) | ||
| 1104 | { | ||
| 1105 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1106 | struct drm_connector *connector; | ||
| 1107 | struct intel_output *intel_output; | ||
| 1108 | struct intel_dp_priv *dp_priv; | ||
| 1109 | |||
| 1110 | intel_output = kcalloc(sizeof(struct intel_output) + | ||
| 1111 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | ||
| 1112 | if (!intel_output) | ||
| 1113 | return; | ||
| 1114 | |||
| 1115 | dp_priv = (struct intel_dp_priv *)(intel_output + 1); | ||
| 1116 | |||
| 1117 | connector = &intel_output->base; | ||
| 1118 | drm_connector_init(dev, connector, &intel_dp_connector_funcs, | ||
| 1119 | DRM_MODE_CONNECTOR_DisplayPort); | ||
| 1120 | drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); | ||
| 1121 | |||
| 1122 | intel_output->type = INTEL_OUTPUT_DISPLAYPORT; | ||
| 1123 | |||
| 1124 | connector->interlace_allowed = true; | ||
| 1125 | connector->doublescan_allowed = 0; | ||
| 1126 | |||
| 1127 | dp_priv->intel_output = intel_output; | ||
| 1128 | dp_priv->output_reg = output_reg; | ||
| 1129 | dp_priv->has_audio = false; | ||
| 1130 | dp_priv->dpms_mode = DRM_MODE_DPMS_ON; | ||
| 1131 | intel_output->dev_priv = dp_priv; | ||
| 1132 | |||
| 1133 | drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs, | ||
| 1134 | DRM_MODE_ENCODER_TMDS); | ||
| 1135 | drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs); | ||
| 1136 | |||
| 1137 | drm_mode_connector_attach_encoder(&intel_output->base, | ||
| 1138 | &intel_output->enc); | ||
| 1139 | drm_sysfs_connector_add(connector); | ||
| 1140 | |||
| 1141 | /* Set up the DDC bus. */ | ||
| 1142 | intel_dp_i2c_init(intel_output, | ||
| 1143 | (output_reg == DP_B) ? "DPDDC-B" : | ||
| 1144 | (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); | ||
| 1145 | intel_output->ddc_bus = &dp_priv->adapter; | ||
| 1146 | intel_output->hot_plug = intel_dp_hot_plug; | ||
| 1147 | |||
| 1148 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | ||
| 1149 | * 0xd. Failure to do so will result in spurious interrupts being | ||
| 1150 | * generated on the port when a cable is not attached. | ||
| 1151 | */ | ||
| 1152 | if (IS_G4X(dev) && !IS_GM45(dev)) { | ||
| 1153 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | ||
| 1154 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | ||
| 1155 | } | ||
| 1156 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h new file mode 100644 index 000000000000..2b38054d3b6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.h | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Keith Packard | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
| 5 | * documentation for any purpose is hereby granted without fee, provided that | ||
| 6 | * the above copyright notice appear in all copies and that both that copyright | ||
| 7 | * notice and this permission notice appear in supporting documentation, and | ||
| 8 | * that the name of the copyright holders not be used in advertising or | ||
| 9 | * publicity pertaining to distribution of the software without specific, | ||
| 10 | * written prior permission. The copyright holders make no representations | ||
| 11 | * about the suitability of this software for any purpose. It is provided "as | ||
| 12 | * is" without express or implied warranty. | ||
| 13 | * | ||
| 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
| 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
| 20 | * OF THIS SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef _INTEL_DP_H_ | ||
| 24 | #define _INTEL_DP_H_ | ||
| 25 | |||
| 26 | /* From the VESA DisplayPort spec */ | ||
| 27 | |||
| 28 | #define AUX_NATIVE_WRITE 0x8 | ||
| 29 | #define AUX_NATIVE_READ 0x9 | ||
| 30 | #define AUX_I2C_WRITE 0x0 | ||
| 31 | #define AUX_I2C_READ 0x1 | ||
| 32 | #define AUX_I2C_STATUS 0x2 | ||
| 33 | #define AUX_I2C_MOT 0x4 | ||
| 34 | |||
| 35 | #define AUX_NATIVE_REPLY_ACK (0x0 << 4) | ||
| 36 | #define AUX_NATIVE_REPLY_NACK (0x1 << 4) | ||
| 37 | #define AUX_NATIVE_REPLY_DEFER (0x2 << 4) | ||
| 38 | #define AUX_NATIVE_REPLY_MASK (0x3 << 4) | ||
| 39 | |||
| 40 | #define AUX_I2C_REPLY_ACK (0x0 << 6) | ||
| 41 | #define AUX_I2C_REPLY_NACK (0x1 << 6) | ||
| 42 | #define AUX_I2C_REPLY_DEFER (0x2 << 6) | ||
| 43 | #define AUX_I2C_REPLY_MASK (0x3 << 6) | ||
| 44 | |||
| 45 | /* AUX CH addresses */ | ||
| 46 | #define DP_LINK_BW_SET 0x100 | ||
| 47 | # define DP_LINK_BW_1_62 0x06 | ||
| 48 | # define DP_LINK_BW_2_7 0x0a | ||
| 49 | |||
| 50 | #define DP_LANE_COUNT_SET 0x101 | ||
| 51 | # define DP_LANE_COUNT_MASK 0x0f | ||
| 52 | # define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) | ||
| 53 | |||
| 54 | #define DP_TRAINING_PATTERN_SET 0x102 | ||
| 55 | |||
| 56 | # define DP_TRAINING_PATTERN_DISABLE 0 | ||
| 57 | # define DP_TRAINING_PATTERN_1 1 | ||
| 58 | # define DP_TRAINING_PATTERN_2 2 | ||
| 59 | # define DP_TRAINING_PATTERN_MASK 0x3 | ||
| 60 | |||
| 61 | # define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) | ||
| 62 | # define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) | ||
| 63 | # define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) | ||
| 64 | # define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) | ||
| 65 | # define DP_LINK_QUAL_PATTERN_MASK (3 << 2) | ||
| 66 | |||
| 67 | # define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) | ||
| 68 | # define DP_LINK_SCRAMBLING_DISABLE (1 << 5) | ||
| 69 | |||
| 70 | # define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) | ||
| 71 | # define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) | ||
| 72 | # define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) | ||
| 73 | # define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) | ||
| 74 | |||
| 75 | #define DP_TRAINING_LANE0_SET 0x103 | ||
| 76 | #define DP_TRAINING_LANE1_SET 0x104 | ||
| 77 | #define DP_TRAINING_LANE2_SET 0x105 | ||
| 78 | #define DP_TRAINING_LANE3_SET 0x106 | ||
| 79 | |||
| 80 | # define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 | ||
| 81 | # define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 | ||
| 82 | # define DP_TRAIN_MAX_SWING_REACHED (1 << 2) | ||
| 83 | # define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) | ||
| 84 | # define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) | ||
| 85 | # define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) | ||
| 86 | # define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) | ||
| 87 | |||
| 88 | # define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) | ||
| 89 | # define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) | ||
| 90 | # define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) | ||
| 91 | # define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) | ||
| 92 | # define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) | ||
| 93 | |||
| 94 | # define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 | ||
| 95 | # define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) | ||
| 96 | |||
| 97 | #define DP_DOWNSPREAD_CTRL 0x107 | ||
| 98 | # define DP_SPREAD_AMP_0_5 (1 << 4) | ||
| 99 | |||
| 100 | #define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 | ||
| 101 | # define DP_SET_ANSI_8B10B (1 << 0) | ||
| 102 | |||
| 103 | #define DP_LANE0_1_STATUS 0x202 | ||
| 104 | #define DP_LANE2_3_STATUS 0x203 | ||
| 105 | |||
| 106 | # define DP_LANE_CR_DONE (1 << 0) | ||
| 107 | # define DP_LANE_CHANNEL_EQ_DONE (1 << 1) | ||
| 108 | # define DP_LANE_SYMBOL_LOCKED (1 << 2) | ||
| 109 | |||
| 110 | #define DP_LANE_ALIGN_STATUS_UPDATED 0x204 | ||
| 111 | |||
| 112 | #define DP_INTERLANE_ALIGN_DONE (1 << 0) | ||
| 113 | #define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) | ||
| 114 | #define DP_LINK_STATUS_UPDATED (1 << 7) | ||
| 115 | |||
| 116 | #define DP_SINK_STATUS 0x205 | ||
| 117 | |||
| 118 | #define DP_RECEIVE_PORT_0_STATUS (1 << 0) | ||
| 119 | #define DP_RECEIVE_PORT_1_STATUS (1 << 1) | ||
| 120 | |||
| 121 | #define DP_ADJUST_REQUEST_LANE0_1 0x206 | ||
| 122 | #define DP_ADJUST_REQUEST_LANE2_3 0x207 | ||
| 123 | |||
| 124 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 | ||
| 125 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 | ||
| 126 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c | ||
| 127 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 | ||
| 128 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 | ||
| 129 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 | ||
| 130 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 | ||
| 131 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 | ||
| 132 | |||
| 133 | struct i2c_algo_dp_aux_data { | ||
| 134 | bool running; | ||
| 135 | u16 address; | ||
| 136 | int (*aux_ch) (struct i2c_adapter *adapter, | ||
| 137 | uint8_t *send, int send_bytes, | ||
| 138 | uint8_t *recv, int recv_bytes); | ||
| 139 | }; | ||
| 140 | |||
| 141 | int | ||
| 142 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter); | ||
| 143 | |||
| 144 | #endif /* _INTEL_DP_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c new file mode 100644 index 000000000000..a63b6f57d2d4 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c | |||
| @@ -0,0 +1,273 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2009 Keith Packard | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
| 5 | * documentation for any purpose is hereby granted without fee, provided that | ||
| 6 | * the above copyright notice appear in all copies and that both that copyright | ||
| 7 | * notice and this permission notice appear in supporting documentation, and | ||
| 8 | * that the name of the copyright holders not be used in advertising or | ||
| 9 | * publicity pertaining to distribution of the software without specific, | ||
| 10 | * written prior permission. The copyright holders make no representations | ||
| 11 | * about the suitability of this software for any purpose. It is provided "as | ||
| 12 | * is" without express or implied warranty. | ||
| 13 | * | ||
| 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
| 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
| 20 | * OF THIS SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/errno.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include "intel_dp.h" | ||
| 32 | #include "drmP.h" | ||
| 33 | |||
| 34 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | ||
| 35 | |||
| 36 | #define MODE_I2C_START 1 | ||
| 37 | #define MODE_I2C_WRITE 2 | ||
| 38 | #define MODE_I2C_READ 4 | ||
| 39 | #define MODE_I2C_STOP 8 | ||
| 40 | |||
| 41 | static int | ||
| 42 | i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | ||
| 43 | uint8_t write_byte, uint8_t *read_byte) | ||
| 44 | { | ||
| 45 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 46 | uint16_t address = algo_data->address; | ||
| 47 | uint8_t msg[5]; | ||
| 48 | uint8_t reply[2]; | ||
| 49 | int msg_bytes; | ||
| 50 | int reply_bytes; | ||
| 51 | int ret; | ||
| 52 | |||
| 53 | /* Set up the command byte */ | ||
| 54 | if (mode & MODE_I2C_READ) | ||
| 55 | msg[0] = AUX_I2C_READ << 4; | ||
| 56 | else | ||
| 57 | msg[0] = AUX_I2C_WRITE << 4; | ||
| 58 | |||
| 59 | if (!(mode & MODE_I2C_STOP)) | ||
| 60 | msg[0] |= AUX_I2C_MOT << 4; | ||
| 61 | |||
| 62 | msg[1] = address >> 8; | ||
| 63 | msg[2] = address; | ||
| 64 | |||
| 65 | switch (mode) { | ||
| 66 | case MODE_I2C_WRITE: | ||
| 67 | msg[3] = 0; | ||
| 68 | msg[4] = write_byte; | ||
| 69 | msg_bytes = 5; | ||
| 70 | reply_bytes = 1; | ||
| 71 | break; | ||
| 72 | case MODE_I2C_READ: | ||
| 73 | msg[3] = 0; | ||
| 74 | msg_bytes = 4; | ||
| 75 | reply_bytes = 2; | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | msg_bytes = 3; | ||
| 79 | reply_bytes = 1; | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | |||
| 83 | for (;;) { | ||
| 84 | ret = (*algo_data->aux_ch)(adapter, | ||
| 85 | msg, msg_bytes, | ||
| 86 | reply, reply_bytes); | ||
| 87 | if (ret < 0) { | ||
| 88 | DRM_DEBUG("aux_ch failed %d\n", ret); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | switch (reply[0] & AUX_I2C_REPLY_MASK) { | ||
| 92 | case AUX_I2C_REPLY_ACK: | ||
| 93 | if (mode == MODE_I2C_READ) { | ||
| 94 | *read_byte = reply[1]; | ||
| 95 | } | ||
| 96 | return reply_bytes - 1; | ||
| 97 | case AUX_I2C_REPLY_NACK: | ||
| 98 | DRM_DEBUG("aux_ch nack\n"); | ||
| 99 | return -EREMOTEIO; | ||
| 100 | case AUX_I2C_REPLY_DEFER: | ||
| 101 | DRM_DEBUG("aux_ch defer\n"); | ||
| 102 | udelay(100); | ||
| 103 | break; | ||
| 104 | default: | ||
| 105 | DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); | ||
| 106 | return -EREMOTEIO; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | /* | ||
| 112 | * I2C over AUX CH | ||
| 113 | */ | ||
| 114 | |||
| 115 | /* | ||
| 116 | * Send the address. If the I2C link is running, this 'restarts' | ||
| 117 | * the connection with the new address, this is used for doing | ||
| 118 | * a write followed by a read (as needed for DDC) | ||
| 119 | */ | ||
| 120 | static int | ||
| 121 | i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) | ||
| 122 | { | ||
| 123 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 124 | int mode = MODE_I2C_START; | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | if (reading) | ||
| 128 | mode |= MODE_I2C_READ; | ||
| 129 | else | ||
| 130 | mode |= MODE_I2C_WRITE; | ||
| 131 | algo_data->address = address; | ||
| 132 | algo_data->running = true; | ||
| 133 | ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
| 134 | return ret; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* | ||
| 138 | * Stop the I2C transaction. This closes out the link, sending | ||
| 139 | * a bare address packet with the MOT bit turned off | ||
| 140 | */ | ||
| 141 | static void | ||
| 142 | i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) | ||
| 143 | { | ||
| 144 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 145 | int mode = MODE_I2C_STOP; | ||
| 146 | |||
| 147 | if (reading) | ||
| 148 | mode |= MODE_I2C_READ; | ||
| 149 | else | ||
| 150 | mode |= MODE_I2C_WRITE; | ||
| 151 | if (algo_data->running) { | ||
| 152 | (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
| 153 | algo_data->running = false; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | /* | ||
| 158 | * Write a single byte to the current I2C address, the | ||
| 159 | * the I2C link must be running or this returns -EIO | ||
| 160 | */ | ||
| 161 | static int | ||
| 162 | i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) | ||
| 163 | { | ||
| 164 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 165 | int ret; | ||
| 166 | |||
| 167 | if (!algo_data->running) | ||
| 168 | return -EIO; | ||
| 169 | |||
| 170 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* | ||
| 175 | * Read a single byte from the current I2C address, the | ||
| 176 | * I2C link must be running or this returns -EIO | ||
| 177 | */ | ||
| 178 | static int | ||
| 179 | i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) | ||
| 180 | { | ||
| 181 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 182 | int ret; | ||
| 183 | |||
| 184 | if (!algo_data->running) | ||
| 185 | return -EIO; | ||
| 186 | |||
| 187 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); | ||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int | ||
| 192 | i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | ||
| 193 | struct i2c_msg *msgs, | ||
| 194 | int num) | ||
| 195 | { | ||
| 196 | int ret = 0; | ||
| 197 | bool reading = false; | ||
| 198 | int m; | ||
| 199 | int b; | ||
| 200 | |||
| 201 | for (m = 0; m < num; m++) { | ||
| 202 | u16 len = msgs[m].len; | ||
| 203 | u8 *buf = msgs[m].buf; | ||
| 204 | reading = (msgs[m].flags & I2C_M_RD) != 0; | ||
| 205 | ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); | ||
| 206 | if (ret < 0) | ||
| 207 | break; | ||
| 208 | if (reading) { | ||
| 209 | for (b = 0; b < len; b++) { | ||
| 210 | ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); | ||
| 211 | if (ret < 0) | ||
| 212 | break; | ||
| 213 | } | ||
| 214 | } else { | ||
| 215 | for (b = 0; b < len; b++) { | ||
| 216 | ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); | ||
| 217 | if (ret < 0) | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | if (ret < 0) | ||
| 222 | break; | ||
| 223 | } | ||
| 224 | if (ret >= 0) | ||
| 225 | ret = num; | ||
| 226 | i2c_algo_dp_aux_stop(adapter, reading); | ||
| 227 | DRM_DEBUG("dp_aux_xfer return %d\n", ret); | ||
| 228 | return ret; | ||
| 229 | } | ||
| 230 | |||
| 231 | static u32 | ||
| 232 | i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) | ||
| 233 | { | ||
| 234 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
| 235 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
| 236 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
| 237 | I2C_FUNC_10BIT_ADDR; | ||
| 238 | } | ||
| 239 | |||
| 240 | static const struct i2c_algorithm i2c_dp_aux_algo = { | ||
| 241 | .master_xfer = i2c_algo_dp_aux_xfer, | ||
| 242 | .functionality = i2c_algo_dp_aux_functionality, | ||
| 243 | }; | ||
| 244 | |||
| 245 | static void | ||
| 246 | i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) | ||
| 247 | { | ||
| 248 | (void) i2c_algo_dp_aux_address(adapter, 0, false); | ||
| 249 | (void) i2c_algo_dp_aux_stop(adapter, false); | ||
| 250 | |||
| 251 | } | ||
| 252 | |||
| 253 | static int | ||
| 254 | i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) | ||
| 255 | { | ||
| 256 | adapter->algo = &i2c_dp_aux_algo; | ||
| 257 | adapter->retries = 3; | ||
| 258 | i2c_dp_aux_reset_bus(adapter); | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | int | ||
| 263 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) | ||
| 264 | { | ||
| 265 | int error; | ||
| 266 | |||
| 267 | error = i2c_dp_aux_prepare_bus(adapter); | ||
| 268 | if (error) | ||
| 269 | return error; | ||
| 270 | error = i2c_add_adapter(adapter); | ||
| 271 | return error; | ||
| 272 | } | ||
| 273 | EXPORT_SYMBOL(i2c_dp_aux_add_bus); | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cd4b9c5f715e..004541c935a8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #define INTEL_OUTPUT_LVDS 4 | 54 | #define INTEL_OUTPUT_LVDS 4 |
| 55 | #define INTEL_OUTPUT_TVOUT 5 | 55 | #define INTEL_OUTPUT_TVOUT 5 |
| 56 | #define INTEL_OUTPUT_HDMI 6 | 56 | #define INTEL_OUTPUT_HDMI 6 |
| 57 | #define INTEL_OUTPUT_DISPLAYPORT 7 | ||
| 57 | 58 | ||
| 58 | #define INTEL_DVO_CHIP_NONE 0 | 59 | #define INTEL_DVO_CHIP_NONE 0 |
| 59 | #define INTEL_DVO_CHIP_LVDS 1 | 60 | #define INTEL_DVO_CHIP_LVDS 1 |
| @@ -65,7 +66,6 @@ struct intel_i2c_chan { | |||
| 65 | u32 reg; /* GPIO reg */ | 66 | u32 reg; /* GPIO reg */ |
| 66 | struct i2c_adapter adapter; | 67 | struct i2c_adapter adapter; |
| 67 | struct i2c_algo_bit_data algo; | 68 | struct i2c_algo_bit_data algo; |
| 68 | u8 slave_addr; | ||
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | struct intel_framebuffer { | 71 | struct intel_framebuffer { |
| @@ -79,11 +79,12 @@ struct intel_output { | |||
| 79 | 79 | ||
| 80 | struct drm_encoder enc; | 80 | struct drm_encoder enc; |
| 81 | int type; | 81 | int type; |
| 82 | struct intel_i2c_chan *i2c_bus; /* for control functions */ | 82 | struct i2c_adapter *i2c_bus; |
| 83 | struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ | 83 | struct i2c_adapter *ddc_bus; |
| 84 | bool load_detect_temp; | 84 | bool load_detect_temp; |
| 85 | bool needs_tv_clock; | 85 | bool needs_tv_clock; |
| 86 | void *dev_priv; | 86 | void *dev_priv; |
| 87 | void (*hot_plug)(struct intel_output *); | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | struct intel_crtc { | 90 | struct intel_crtc { |
| @@ -104,9 +105,9 @@ struct intel_crtc { | |||
| 104 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) | 105 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) |
| 105 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) | 106 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) |
| 106 | 107 | ||
| 107 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 108 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
| 108 | const char *name); | 109 | const char *name); |
| 109 | void intel_i2c_destroy(struct intel_i2c_chan *chan); | 110 | void intel_i2c_destroy(struct i2c_adapter *adapter); |
| 110 | int intel_ddc_get_modes(struct intel_output *intel_output); | 111 | int intel_ddc_get_modes(struct intel_output *intel_output); |
| 111 | extern bool intel_ddc_probe(struct intel_output *intel_output); | 112 | extern bool intel_ddc_probe(struct intel_output *intel_output); |
| 112 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); | 113 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); |
| @@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | |||
| 116 | extern void intel_dvo_init(struct drm_device *dev); | 117 | extern void intel_dvo_init(struct drm_device *dev); |
| 117 | extern void intel_tv_init(struct drm_device *dev); | 118 | extern void intel_tv_init(struct drm_device *dev); |
| 118 | extern void intel_lvds_init(struct drm_device *dev); | 119 | extern void intel_lvds_init(struct drm_device *dev); |
| 120 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); | ||
| 121 | void | ||
| 122 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
| 123 | struct drm_display_mode *adjusted_mode); | ||
| 119 | 124 | ||
| 120 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); | 125 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); |
| 121 | extern void intel_encoder_prepare (struct drm_encoder *encoder); | 126 | extern void intel_encoder_prepare (struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 1ee3007d6ec0..13bff20930e8 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 384 | { | 384 | { |
| 385 | struct intel_output *intel_output; | 385 | struct intel_output *intel_output; |
| 386 | struct intel_dvo_device *dvo; | 386 | struct intel_dvo_device *dvo; |
| 387 | struct intel_i2c_chan *i2cbus = NULL; | 387 | struct i2c_adapter *i2cbus = NULL; |
| 388 | int ret = 0; | 388 | int ret = 0; |
| 389 | int i; | 389 | int i; |
| 390 | int gpio_inited = 0; | ||
| 391 | int encoder_type = DRM_MODE_ENCODER_NONE; | 390 | int encoder_type = DRM_MODE_ENCODER_NONE; |
| 392 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); | 391 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); |
| 393 | if (!intel_output) | 392 | if (!intel_output) |
| @@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 420 | * It appears that everything is on GPIOE except for panels | 419 | * It appears that everything is on GPIOE except for panels |
| 421 | * on i830 laptops, which are on GPIOB (DVOA). | 420 | * on i830 laptops, which are on GPIOB (DVOA). |
| 422 | */ | 421 | */ |
| 423 | if (gpio_inited != gpio) { | 422 | if (i2cbus != NULL) |
| 424 | if (i2cbus != NULL) | 423 | intel_i2c_destroy(i2cbus); |
| 425 | intel_i2c_destroy(i2cbus); | 424 | if (!(i2cbus = intel_i2c_create(dev, gpio, |
| 426 | if (!(i2cbus = intel_i2c_create(dev, gpio, | 425 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { |
| 427 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { | 426 | continue; |
| 428 | continue; | ||
| 429 | } | ||
| 430 | gpio_inited = gpio; | ||
| 431 | } | 427 | } |
| 432 | 428 | ||
| 433 | if (dvo->dev_ops!= NULL) | 429 | if (dvo->dev_ops!= NULL) |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 1af7d68e3807..1d30802e773e 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -453,7 +453,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 453 | size = ALIGN(size, PAGE_SIZE); | 453 | size = ALIGN(size, PAGE_SIZE); |
| 454 | fbo = drm_gem_object_alloc(dev, size); | 454 | fbo = drm_gem_object_alloc(dev, size); |
| 455 | if (!fbo) { | 455 | if (!fbo) { |
| 456 | printk(KERN_ERR "failed to allocate framebuffer\n"); | 456 | DRM_ERROR("failed to allocate framebuffer\n"); |
| 457 | ret = -ENOMEM; | 457 | ret = -ENOMEM; |
| 458 | goto out; | 458 | goto out; |
| 459 | } | 459 | } |
| @@ -610,8 +610,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 610 | par->dev = dev; | 610 | par->dev = dev; |
| 611 | 611 | ||
| 612 | /* To allow resizeing without swapping buffers */ | 612 | /* To allow resizeing without swapping buffers */ |
| 613 | printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, | 613 | DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, |
| 614 | intel_fb->base.height, obj_priv->gtt_offset, fbo); | 614 | intel_fb->base.height, obj_priv->gtt_offset, fbo); |
| 615 | 615 | ||
| 616 | mutex_unlock(&dev->struct_mutex); | 616 | mutex_unlock(&dev->struct_mutex); |
| 617 | return 0; | 617 | return 0; |
| @@ -698,13 +698,13 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc * | |||
| 698 | } else | 698 | } else |
| 699 | intelfb_set_par(info); | 699 | intelfb_set_par(info); |
| 700 | 700 | ||
| 701 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 701 | DRM_INFO("fb%d: %s frame buffer device\n", info->node, |
| 702 | info->fix.id); | 702 | info->fix.id); |
| 703 | 703 | ||
| 704 | /* Switch back to kernel console on panic */ | 704 | /* Switch back to kernel console on panic */ |
| 705 | kernelfb_mode = *modeset; | 705 | kernelfb_mode = *modeset; |
| 706 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | 706 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
| 707 | printk(KERN_INFO "registered panic notifier\n"); | 707 | DRM_DEBUG("registered panic notifier\n"); |
| 708 | 708 | ||
| 709 | return 0; | 709 | return 0; |
| 710 | } | 710 | } |
| @@ -852,13 +852,13 @@ static int intelfb_single_fb_probe(struct drm_device *dev) | |||
| 852 | } else | 852 | } else |
| 853 | intelfb_set_par(info); | 853 | intelfb_set_par(info); |
| 854 | 854 | ||
| 855 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 855 | DRM_INFO("fb%d: %s frame buffer device\n", info->node, |
| 856 | info->fix.id); | 856 | info->fix.id); |
| 857 | 857 | ||
| 858 | /* Switch back to kernel console on panic */ | 858 | /* Switch back to kernel console on panic */ |
| 859 | kernelfb_mode = *modeset; | 859 | kernelfb_mode = *modeset; |
| 860 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | 860 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
| 861 | printk(KERN_INFO "registered panic notifier\n"); | 861 | DRM_DEBUG("registered panic notifier\n"); |
| 862 | 862 | ||
| 863 | return 0; | 863 | return 0; |
| 864 | } | 864 | } |
| @@ -872,8 +872,8 @@ void intelfb_restore(void) | |||
| 872 | { | 872 | { |
| 873 | int ret; | 873 | int ret; |
| 874 | if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { | 874 | if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { |
| 875 | printk(KERN_ERR "Failed to restore crtc configuration: %d\n", | 875 | DRM_ERROR("Failed to restore crtc configuration: %d\n", |
| 876 | ret); | 876 | ret); |
| 877 | } | 877 | } |
| 878 | } | 878 | } |
| 879 | 879 | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4ea2a651b92c..9e30daae37dc 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "drmP.h" | 31 | #include "drmP.h" |
| 32 | #include "drm.h" | 32 | #include "drm.h" |
| 33 | #include "drm_crtc.h" | 33 | #include "drm_crtc.h" |
| 34 | #include "drm_edid.h" | ||
| 34 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
| 35 | #include "i915_drm.h" | 36 | #include "i915_drm.h" |
| 36 | #include "i915_drv.h" | 37 | #include "i915_drv.h" |
| @@ -56,8 +57,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 56 | sdvox = SDVO_ENCODING_HDMI | | 57 | sdvox = SDVO_ENCODING_HDMI | |
| 57 | SDVO_BORDER_ENABLE | | 58 | SDVO_BORDER_ENABLE | |
| 58 | SDVO_VSYNC_ACTIVE_HIGH | | 59 | SDVO_VSYNC_ACTIVE_HIGH | |
| 59 | SDVO_HSYNC_ACTIVE_HIGH | | 60 | SDVO_HSYNC_ACTIVE_HIGH; |
| 60 | SDVO_NULL_PACKETS_DURING_VSYNC; | ||
| 61 | 61 | ||
| 62 | if (hdmi_priv->has_hdmi_sink) | 62 | if (hdmi_priv->has_hdmi_sink) |
| 63 | sdvox |= SDVO_AUDIO_ENABLE; | 63 | sdvox |= SDVO_AUDIO_ENABLE; |
| @@ -129,20 +129,26 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
| 129 | return true; | 129 | return true; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static void | 132 | static enum drm_connector_status |
| 133 | intel_hdmi_sink_detect(struct drm_connector *connector) | 133 | intel_hdmi_edid_detect(struct drm_connector *connector) |
| 134 | { | 134 | { |
| 135 | struct intel_output *intel_output = to_intel_output(connector); | 135 | struct intel_output *intel_output = to_intel_output(connector); |
| 136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; |
| 137 | struct edid *edid = NULL; | 137 | struct edid *edid = NULL; |
| 138 | enum drm_connector_status status = connector_status_disconnected; | ||
| 138 | 139 | ||
| 139 | edid = drm_get_edid(&intel_output->base, | 140 | edid = drm_get_edid(&intel_output->base, |
| 140 | &intel_output->ddc_bus->adapter); | 141 | intel_output->ddc_bus); |
| 141 | if (edid != NULL) { | 142 | hdmi_priv->has_hdmi_sink = false; |
| 142 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | 143 | if (edid) { |
| 143 | kfree(edid); | 144 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 145 | status = connector_status_connected; | ||
| 146 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | ||
| 147 | } | ||
| 144 | intel_output->base.display_info.raw_edid = NULL; | 148 | intel_output->base.display_info.raw_edid = NULL; |
| 149 | kfree(edid); | ||
| 145 | } | 150 | } |
| 151 | return status; | ||
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | static enum drm_connector_status | 154 | static enum drm_connector_status |
| @@ -154,11 +160,7 @@ igdng_hdmi_detect(struct drm_connector *connector) | |||
| 154 | /* FIXME hotplug detect */ | 160 | /* FIXME hotplug detect */ |
| 155 | 161 | ||
| 156 | hdmi_priv->has_hdmi_sink = false; | 162 | hdmi_priv->has_hdmi_sink = false; |
| 157 | intel_hdmi_sink_detect(connector); | 163 | return intel_hdmi_edid_detect(connector); |
| 158 | if (hdmi_priv->has_hdmi_sink) | ||
| 159 | return connector_status_connected; | ||
| 160 | else | ||
| 161 | return connector_status_disconnected; | ||
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | static enum drm_connector_status | 166 | static enum drm_connector_status |
| @@ -201,10 +203,9 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
| 201 | return connector_status_unknown; | 203 | return connector_status_unknown; |
| 202 | } | 204 | } |
| 203 | 205 | ||
| 204 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) { | 206 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) |
| 205 | intel_hdmi_sink_detect(connector); | 207 | return intel_hdmi_edid_detect(connector); |
| 206 | return connector_status_connected; | 208 | else |
| 207 | } else | ||
| 208 | return connector_status_disconnected; | 209 | return connector_status_disconnected; |
| 209 | } | 210 | } |
| 210 | 211 | ||
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index f7061f68d050..62b8bead7652 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
| @@ -124,6 +124,7 @@ static void set_data(void *data, int state_high) | |||
| 124 | * @output: driver specific output device | 124 | * @output: driver specific output device |
| 125 | * @reg: GPIO reg to use | 125 | * @reg: GPIO reg to use |
| 126 | * @name: name for this bus | 126 | * @name: name for this bus |
| 127 | * @slave_addr: slave address (if fixed) | ||
| 127 | * | 128 | * |
| 128 | * Creates and registers a new i2c bus with the Linux i2c layer, for use | 129 | * Creates and registers a new i2c bus with the Linux i2c layer, for use |
| 129 | * in output probing and control (e.g. DDC or SDVO control functions). | 130 | * in output probing and control (e.g. DDC or SDVO control functions). |
| @@ -139,8 +140,8 @@ static void set_data(void *data, int state_high) | |||
| 139 | * %GPIOH | 140 | * %GPIOH |
| 140 | * see PRM for details on how these different busses are used. | 141 | * see PRM for details on how these different busses are used. |
| 141 | */ | 142 | */ |
| 142 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 143 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
| 143 | const char *name) | 144 | const char *name) |
| 144 | { | 145 | { |
| 145 | struct intel_i2c_chan *chan; | 146 | struct intel_i2c_chan *chan; |
| 146 | 147 | ||
| @@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | |||
| 174 | intel_i2c_quirk_set(dev, false); | 175 | intel_i2c_quirk_set(dev, false); |
| 175 | udelay(20); | 176 | udelay(20); |
| 176 | 177 | ||
| 177 | return chan; | 178 | return &chan->adapter; |
| 178 | 179 | ||
| 179 | out_free: | 180 | out_free: |
| 180 | kfree(chan); | 181 | kfree(chan); |
| @@ -187,11 +188,16 @@ out_free: | |||
| 187 | * | 188 | * |
| 188 | * Unregister the adapter from the i2c layer, then free the structure. | 189 | * Unregister the adapter from the i2c layer, then free the structure. |
| 189 | */ | 190 | */ |
| 190 | void intel_i2c_destroy(struct intel_i2c_chan *chan) | 191 | void intel_i2c_destroy(struct i2c_adapter *adapter) |
| 191 | { | 192 | { |
| 192 | if (!chan) | 193 | struct intel_i2c_chan *chan; |
| 194 | |||
| 195 | if (!adapter) | ||
| 193 | return; | 196 | return; |
| 194 | 197 | ||
| 198 | chan = container_of(adapter, | ||
| 199 | struct intel_i2c_chan, | ||
| 200 | adapter); | ||
| 195 | i2c_del_adapter(&chan->adapter); | 201 | i2c_del_adapter(&chan->adapter); |
| 196 | kfree(chan); | 202 | kfree(chan); |
| 197 | } | 203 | } |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f073ed8432e8..9ab38efffecf 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -36,9 +36,25 @@ | |||
| 36 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
| 37 | #include "i915_drm.h" | 37 | #include "i915_drm.h" |
| 38 | #include "i915_drv.h" | 38 | #include "i915_drv.h" |
| 39 | #include <linux/acpi.h> | ||
| 39 | 40 | ||
| 40 | #define I915_LVDS "i915_lvds" | 41 | #define I915_LVDS "i915_lvds" |
| 41 | 42 | ||
| 43 | /* | ||
| 44 | * the following four scaling options are defined. | ||
| 45 | * #define DRM_MODE_SCALE_NON_GPU 0 | ||
| 46 | * #define DRM_MODE_SCALE_FULLSCREEN 1 | ||
| 47 | * #define DRM_MODE_SCALE_NO_SCALE 2 | ||
| 48 | * #define DRM_MODE_SCALE_ASPECT 3 | ||
| 49 | */ | ||
| 50 | |||
| 51 | /* Private structure for the integrated LVDS support */ | ||
| 52 | struct intel_lvds_priv { | ||
| 53 | int fitting_mode; | ||
| 54 | u32 pfit_control; | ||
| 55 | u32 pfit_pgm_ratios; | ||
| 56 | }; | ||
| 57 | |||
| 42 | /** | 58 | /** |
| 43 | * Sets the backlight level. | 59 | * Sets the backlight level. |
| 44 | * | 60 | * |
| @@ -213,26 +229,45 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 213 | struct drm_display_mode *mode, | 229 | struct drm_display_mode *mode, |
| 214 | struct drm_display_mode *adjusted_mode) | 230 | struct drm_display_mode *adjusted_mode) |
| 215 | { | 231 | { |
| 232 | /* | ||
| 233 | * float point operation is not supported . So the PANEL_RATIO_FACTOR | ||
| 234 | * is defined, which can avoid the float point computation when | ||
| 235 | * calculating the panel ratio. | ||
| 236 | */ | ||
| 237 | #define PANEL_RATIO_FACTOR 8192 | ||
| 216 | struct drm_device *dev = encoder->dev; | 238 | struct drm_device *dev = encoder->dev; |
| 217 | struct drm_i915_private *dev_priv = dev->dev_private; | 239 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 218 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 240 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 219 | struct drm_encoder *tmp_encoder; | 241 | struct drm_encoder *tmp_encoder; |
| 242 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 243 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
| 244 | u32 pfit_control = 0, pfit_pgm_ratios = 0; | ||
| 245 | int left_border = 0, right_border = 0, top_border = 0; | ||
| 246 | int bottom_border = 0; | ||
| 247 | bool border = 0; | ||
| 248 | int panel_ratio, desired_ratio, vert_scale, horiz_scale; | ||
| 249 | int horiz_ratio, vert_ratio; | ||
| 250 | u32 hsync_width, vsync_width; | ||
| 251 | u32 hblank_width, vblank_width; | ||
| 252 | u32 hsync_pos, vsync_pos; | ||
| 220 | 253 | ||
| 221 | /* Should never happen!! */ | 254 | /* Should never happen!! */ |
| 222 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { | 255 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { |
| 223 | printk(KERN_ERR "Can't support LVDS on pipe A\n"); | 256 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
| 224 | return false; | 257 | return false; |
| 225 | } | 258 | } |
| 226 | 259 | ||
| 227 | /* Should never happen!! */ | 260 | /* Should never happen!! */ |
| 228 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { | 261 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { |
| 229 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { | 262 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { |
| 230 | printk(KERN_ERR "Can't enable LVDS and another " | 263 | DRM_ERROR("Can't enable LVDS and another " |
| 231 | "encoder on the same pipe\n"); | 264 | "encoder on the same pipe\n"); |
| 232 | return false; | 265 | return false; |
| 233 | } | 266 | } |
| 234 | } | 267 | } |
| 235 | 268 | /* If we don't have a panel mode, there is nothing we can do */ | |
| 269 | if (dev_priv->panel_fixed_mode == NULL) | ||
| 270 | return true; | ||
| 236 | /* | 271 | /* |
| 237 | * If we have timings from the BIOS for the panel, put them in | 272 | * If we have timings from the BIOS for the panel, put them in |
| 238 | * to the adjusted mode. The CRTC will be set up for this mode, | 273 | * to the adjusted mode. The CRTC will be set up for this mode, |
| @@ -256,6 +291,243 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 256 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | 291 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
| 257 | } | 292 | } |
| 258 | 293 | ||
| 294 | /* Make sure pre-965s set dither correctly */ | ||
| 295 | if (!IS_I965G(dev)) { | ||
| 296 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
| 297 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
| 298 | } | ||
| 299 | |||
| 300 | /* Native modes don't need fitting */ | ||
| 301 | if (adjusted_mode->hdisplay == mode->hdisplay && | ||
| 302 | adjusted_mode->vdisplay == mode->vdisplay) { | ||
| 303 | pfit_pgm_ratios = 0; | ||
| 304 | border = 0; | ||
| 305 | goto out; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* 965+ wants fuzzy fitting */ | ||
| 309 | if (IS_I965G(dev)) | ||
| 310 | pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | | ||
| 311 | PFIT_FILTER_FUZZY; | ||
| 312 | |||
| 313 | hsync_width = adjusted_mode->crtc_hsync_end - | ||
| 314 | adjusted_mode->crtc_hsync_start; | ||
| 315 | vsync_width = adjusted_mode->crtc_vsync_end - | ||
| 316 | adjusted_mode->crtc_vsync_start; | ||
| 317 | hblank_width = adjusted_mode->crtc_hblank_end - | ||
| 318 | adjusted_mode->crtc_hblank_start; | ||
| 319 | vblank_width = adjusted_mode->crtc_vblank_end - | ||
| 320 | adjusted_mode->crtc_vblank_start; | ||
| 321 | /* | ||
| 322 | * Deal with panel fitting options. Figure out how to stretch the | ||
| 323 | * image based on its aspect ratio & the current panel fitting mode. | ||
| 324 | */ | ||
| 325 | panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR / | ||
| 326 | adjusted_mode->vdisplay; | ||
| 327 | desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR / | ||
| 328 | mode->vdisplay; | ||
| 329 | /* | ||
| 330 | * Enable automatic panel scaling for non-native modes so that they fill | ||
| 331 | * the screen. Should be enabled before the pipe is enabled, according | ||
| 332 | * to register description and PRM. | ||
| 333 | * Change the value here to see the borders for debugging | ||
| 334 | */ | ||
| 335 | I915_WRITE(BCLRPAT_A, 0); | ||
| 336 | I915_WRITE(BCLRPAT_B, 0); | ||
| 337 | |||
| 338 | switch (lvds_priv->fitting_mode) { | ||
| 339 | case DRM_MODE_SCALE_NO_SCALE: | ||
| 340 | /* | ||
| 341 | * For centered modes, we have to calculate border widths & | ||
| 342 | * heights and modify the values programmed into the CRTC. | ||
| 343 | */ | ||
| 344 | left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2; | ||
| 345 | right_border = left_border; | ||
| 346 | if (mode->hdisplay & 1) | ||
| 347 | right_border++; | ||
| 348 | top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2; | ||
| 349 | bottom_border = top_border; | ||
| 350 | if (mode->vdisplay & 1) | ||
| 351 | bottom_border++; | ||
| 352 | /* Set active & border values */ | ||
| 353 | adjusted_mode->crtc_hdisplay = mode->hdisplay; | ||
| 354 | /* Keep the boder be even */ | ||
| 355 | if (right_border & 1) | ||
| 356 | right_border++; | ||
| 357 | /* use the border directly instead of border minuse one */ | ||
| 358 | adjusted_mode->crtc_hblank_start = mode->hdisplay + | ||
| 359 | right_border; | ||
| 360 | /* keep the blank width constant */ | ||
| 361 | adjusted_mode->crtc_hblank_end = | ||
| 362 | adjusted_mode->crtc_hblank_start + hblank_width; | ||
| 363 | /* get the hsync pos relative to hblank start */ | ||
| 364 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
| 365 | /* keep the hsync pos be even */ | ||
| 366 | if (hsync_pos & 1) | ||
| 367 | hsync_pos++; | ||
| 368 | adjusted_mode->crtc_hsync_start = | ||
| 369 | adjusted_mode->crtc_hblank_start + hsync_pos; | ||
| 370 | /* keep the hsync width constant */ | ||
| 371 | adjusted_mode->crtc_hsync_end = | ||
| 372 | adjusted_mode->crtc_hsync_start + hsync_width; | ||
| 373 | adjusted_mode->crtc_vdisplay = mode->vdisplay; | ||
| 374 | /* use the border instead of border minus one */ | ||
| 375 | adjusted_mode->crtc_vblank_start = mode->vdisplay + | ||
| 376 | bottom_border; | ||
| 377 | /* keep the vblank width constant */ | ||
| 378 | adjusted_mode->crtc_vblank_end = | ||
| 379 | adjusted_mode->crtc_vblank_start + vblank_width; | ||
| 380 | /* get the vsync start postion relative to vblank start */ | ||
| 381 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
| 382 | adjusted_mode->crtc_vsync_start = | ||
| 383 | adjusted_mode->crtc_vblank_start + vsync_pos; | ||
| 384 | /* keep the vsync width constant */ | ||
| 385 | adjusted_mode->crtc_vsync_end = | ||
| 386 | adjusted_mode->crtc_vblank_start + vsync_width; | ||
| 387 | border = 1; | ||
| 388 | break; | ||
| 389 | case DRM_MODE_SCALE_ASPECT: | ||
| 390 | /* Scale but preserve the spect ratio */ | ||
| 391 | pfit_control |= PFIT_ENABLE; | ||
| 392 | if (IS_I965G(dev)) { | ||
| 393 | /* 965+ is easy, it does everything in hw */ | ||
| 394 | if (panel_ratio > desired_ratio) | ||
| 395 | pfit_control |= PFIT_SCALING_PILLAR; | ||
| 396 | else if (panel_ratio < desired_ratio) | ||
| 397 | pfit_control |= PFIT_SCALING_LETTER; | ||
| 398 | else | ||
| 399 | pfit_control |= PFIT_SCALING_AUTO; | ||
| 400 | } else { | ||
| 401 | /* | ||
| 402 | * For earlier chips we have to calculate the scaling | ||
| 403 | * ratio by hand and program it into the | ||
| 404 | * PFIT_PGM_RATIO register | ||
| 405 | */ | ||
| 406 | u32 horiz_bits, vert_bits, bits = 12; | ||
| 407 | horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/ | ||
| 408 | adjusted_mode->hdisplay; | ||
| 409 | vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/ | ||
| 410 | adjusted_mode->vdisplay; | ||
| 411 | horiz_scale = adjusted_mode->hdisplay * | ||
| 412 | PANEL_RATIO_FACTOR / mode->hdisplay; | ||
| 413 | vert_scale = adjusted_mode->vdisplay * | ||
| 414 | PANEL_RATIO_FACTOR / mode->vdisplay; | ||
| 415 | |||
| 416 | /* retain aspect ratio */ | ||
| 417 | if (panel_ratio > desired_ratio) { /* Pillar */ | ||
| 418 | u32 scaled_width; | ||
| 419 | scaled_width = mode->hdisplay * vert_scale / | ||
| 420 | PANEL_RATIO_FACTOR; | ||
| 421 | horiz_ratio = vert_ratio; | ||
| 422 | pfit_control |= (VERT_AUTO_SCALE | | ||
| 423 | VERT_INTERP_BILINEAR | | ||
| 424 | HORIZ_INTERP_BILINEAR); | ||
| 425 | /* Pillar will have left/right borders */ | ||
| 426 | left_border = (adjusted_mode->hdisplay - | ||
| 427 | scaled_width) / 2; | ||
| 428 | right_border = left_border; | ||
| 429 | if (mode->hdisplay & 1) /* odd resolutions */ | ||
| 430 | right_border++; | ||
| 431 | /* keep the border be even */ | ||
| 432 | if (right_border & 1) | ||
| 433 | right_border++; | ||
| 434 | adjusted_mode->crtc_hdisplay = scaled_width; | ||
| 435 | /* use border instead of border minus one */ | ||
| 436 | adjusted_mode->crtc_hblank_start = | ||
| 437 | scaled_width + right_border; | ||
| 438 | /* keep the hblank width constant */ | ||
| 439 | adjusted_mode->crtc_hblank_end = | ||
| 440 | adjusted_mode->crtc_hblank_start + | ||
| 441 | hblank_width; | ||
| 442 | /* | ||
| 443 | * get the hsync start pos relative to | ||
| 444 | * hblank start | ||
| 445 | */ | ||
| 446 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
| 447 | /* keep the hsync_pos be even */ | ||
| 448 | if (hsync_pos & 1) | ||
| 449 | hsync_pos++; | ||
| 450 | adjusted_mode->crtc_hsync_start = | ||
| 451 | adjusted_mode->crtc_hblank_start + | ||
| 452 | hsync_pos; | ||
| 453 | /* keept hsync width constant */ | ||
| 454 | adjusted_mode->crtc_hsync_end = | ||
| 455 | adjusted_mode->crtc_hsync_start + | ||
| 456 | hsync_width; | ||
| 457 | border = 1; | ||
| 458 | } else if (panel_ratio < desired_ratio) { /* letter */ | ||
| 459 | u32 scaled_height = mode->vdisplay * | ||
| 460 | horiz_scale / PANEL_RATIO_FACTOR; | ||
| 461 | vert_ratio = horiz_ratio; | ||
| 462 | pfit_control |= (HORIZ_AUTO_SCALE | | ||
| 463 | VERT_INTERP_BILINEAR | | ||
| 464 | HORIZ_INTERP_BILINEAR); | ||
| 465 | /* Letterbox will have top/bottom border */ | ||
| 466 | top_border = (adjusted_mode->vdisplay - | ||
| 467 | scaled_height) / 2; | ||
| 468 | bottom_border = top_border; | ||
| 469 | if (mode->vdisplay & 1) | ||
| 470 | bottom_border++; | ||
| 471 | adjusted_mode->crtc_vdisplay = scaled_height; | ||
| 472 | /* use border instead of border minus one */ | ||
| 473 | adjusted_mode->crtc_vblank_start = | ||
| 474 | scaled_height + bottom_border; | ||
| 475 | /* keep the vblank width constant */ | ||
| 476 | adjusted_mode->crtc_vblank_end = | ||
| 477 | adjusted_mode->crtc_vblank_start + | ||
| 478 | vblank_width; | ||
| 479 | /* | ||
| 480 | * get the vsync start pos relative to | ||
| 481 | * vblank start | ||
| 482 | */ | ||
| 483 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
| 484 | adjusted_mode->crtc_vsync_start = | ||
| 485 | adjusted_mode->crtc_vblank_start + | ||
| 486 | vsync_pos; | ||
| 487 | /* keep the vsync width constant */ | ||
| 488 | adjusted_mode->crtc_vsync_end = | ||
| 489 | adjusted_mode->crtc_vsync_start + | ||
| 490 | vsync_width; | ||
| 491 | border = 1; | ||
| 492 | } else { | ||
| 493 | /* Aspects match, Let hw scale both directions */ | ||
| 494 | pfit_control |= (VERT_AUTO_SCALE | | ||
| 495 | HORIZ_AUTO_SCALE | | ||
| 496 | VERT_INTERP_BILINEAR | | ||
| 497 | HORIZ_INTERP_BILINEAR); | ||
| 498 | } | ||
| 499 | horiz_bits = (1 << bits) * horiz_ratio / | ||
| 500 | PANEL_RATIO_FACTOR; | ||
| 501 | vert_bits = (1 << bits) * vert_ratio / | ||
| 502 | PANEL_RATIO_FACTOR; | ||
| 503 | pfit_pgm_ratios = | ||
| 504 | ((vert_bits << PFIT_VERT_SCALE_SHIFT) & | ||
| 505 | PFIT_VERT_SCALE_MASK) | | ||
| 506 | ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) & | ||
| 507 | PFIT_HORIZ_SCALE_MASK); | ||
| 508 | } | ||
| 509 | break; | ||
| 510 | |||
| 511 | case DRM_MODE_SCALE_FULLSCREEN: | ||
| 512 | /* | ||
| 513 | * Full scaling, even if it changes the aspect ratio. | ||
| 514 | * Fortunately this is all done for us in hw. | ||
| 515 | */ | ||
| 516 | pfit_control |= PFIT_ENABLE; | ||
| 517 | if (IS_I965G(dev)) | ||
| 518 | pfit_control |= PFIT_SCALING_AUTO; | ||
| 519 | else | ||
| 520 | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | | ||
| 521 | VERT_INTERP_BILINEAR | | ||
| 522 | HORIZ_INTERP_BILINEAR); | ||
| 523 | break; | ||
| 524 | default: | ||
| 525 | break; | ||
| 526 | } | ||
| 527 | |||
| 528 | out: | ||
| 529 | lvds_priv->pfit_control = pfit_control; | ||
| 530 | lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; | ||
| 259 | /* | 531 | /* |
| 260 | * XXX: It would be nice to support lower refresh rates on the | 532 | * XXX: It would be nice to support lower refresh rates on the |
| 261 | * panels to reduce power consumption, and perhaps match the | 533 | * panels to reduce power consumption, and perhaps match the |
| @@ -301,8 +573,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 301 | { | 573 | { |
| 302 | struct drm_device *dev = encoder->dev; | 574 | struct drm_device *dev = encoder->dev; |
| 303 | struct drm_i915_private *dev_priv = dev->dev_private; | 575 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 304 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 576 | struct intel_output *intel_output = enc_to_intel_output(encoder); |
| 305 | u32 pfit_control; | 577 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; |
| 306 | 578 | ||
| 307 | /* | 579 | /* |
| 308 | * The LVDS pin pair will already have been turned on in the | 580 | * The LVDS pin pair will already have been turned on in the |
| @@ -319,22 +591,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 319 | * screen. Should be enabled before the pipe is enabled, according to | 591 | * screen. Should be enabled before the pipe is enabled, according to |
| 320 | * register description and PRM. | 592 | * register description and PRM. |
| 321 | */ | 593 | */ |
| 322 | if (mode->hdisplay != adjusted_mode->hdisplay || | 594 | I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); |
| 323 | mode->vdisplay != adjusted_mode->vdisplay) | 595 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); |
| 324 | pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | | ||
| 325 | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | | ||
| 326 | HORIZ_INTERP_BILINEAR); | ||
| 327 | else | ||
| 328 | pfit_control = 0; | ||
| 329 | |||
| 330 | if (!IS_I965G(dev)) { | ||
| 331 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
| 332 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; | ||
| 336 | |||
| 337 | I915_WRITE(PFIT_CONTROL, pfit_control); | ||
| 338 | } | 596 | } |
| 339 | 597 | ||
| 340 | /** | 598 | /** |
| @@ -406,6 +664,34 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
| 406 | struct drm_property *property, | 664 | struct drm_property *property, |
| 407 | uint64_t value) | 665 | uint64_t value) |
| 408 | { | 666 | { |
| 667 | struct drm_device *dev = connector->dev; | ||
| 668 | struct intel_output *intel_output = | ||
| 669 | to_intel_output(connector); | ||
| 670 | |||
| 671 | if (property == dev->mode_config.scaling_mode_property && | ||
| 672 | connector->encoder) { | ||
| 673 | struct drm_crtc *crtc = connector->encoder->crtc; | ||
| 674 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
| 675 | if (value == DRM_MODE_SCALE_NON_GPU) { | ||
| 676 | DRM_DEBUG_KMS(I915_LVDS, | ||
| 677 | "non_GPU property is unsupported\n"); | ||
| 678 | return 0; | ||
| 679 | } | ||
| 680 | if (lvds_priv->fitting_mode == value) { | ||
| 681 | /* the LVDS scaling property is not changed */ | ||
| 682 | return 0; | ||
| 683 | } | ||
| 684 | lvds_priv->fitting_mode = value; | ||
| 685 | if (crtc && crtc->enabled) { | ||
| 686 | /* | ||
| 687 | * If the CRTC is enabled, the display will be changed | ||
| 688 | * according to the new panel fitting mode. | ||
| 689 | */ | ||
| 690 | drm_crtc_helper_set_mode(crtc, &crtc->mode, | ||
| 691 | crtc->x, crtc->y, crtc->fb); | ||
| 692 | } | ||
| 693 | } | ||
| 694 | |||
| 409 | return 0; | 695 | return 0; |
| 410 | } | 696 | } |
| 411 | 697 | ||
| @@ -456,7 +742,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 456 | .callback = intel_no_lvds_dmi_callback, | 742 | .callback = intel_no_lvds_dmi_callback, |
| 457 | .ident = "Apple Mac Mini (Core series)", | 743 | .ident = "Apple Mac Mini (Core series)", |
| 458 | .matches = { | 744 | .matches = { |
| 459 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 745 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
| 460 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), | 746 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), |
| 461 | }, | 747 | }, |
| 462 | }, | 748 | }, |
| @@ -464,7 +750,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 464 | .callback = intel_no_lvds_dmi_callback, | 750 | .callback = intel_no_lvds_dmi_callback, |
| 465 | .ident = "Apple Mac Mini (Core 2 series)", | 751 | .ident = "Apple Mac Mini (Core 2 series)", |
| 466 | .matches = { | 752 | .matches = { |
| 467 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 753 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
| 468 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), | 754 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), |
| 469 | }, | 755 | }, |
| 470 | }, | 756 | }, |
| @@ -503,6 +789,65 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 503 | { } /* terminating entry */ | 789 | { } /* terminating entry */ |
| 504 | }; | 790 | }; |
| 505 | 791 | ||
| 792 | #ifdef CONFIG_ACPI | ||
| 793 | /* | ||
| 794 | * check_lid_device -- check whether @handle is an ACPI LID device. | ||
| 795 | * @handle: ACPI device handle | ||
| 796 | * @level : depth in the ACPI namespace tree | ||
| 797 | * @context: the number of LID device when we find the device | ||
| 798 | * @rv: a return value to fill if desired (Not use) | ||
| 799 | */ | ||
| 800 | static acpi_status | ||
| 801 | check_lid_device(acpi_handle handle, u32 level, void *context, | ||
| 802 | void **return_value) | ||
| 803 | { | ||
| 804 | struct acpi_device *acpi_dev; | ||
| 805 | int *lid_present = context; | ||
| 806 | |||
| 807 | acpi_dev = NULL; | ||
| 808 | /* Get the acpi device for device handle */ | ||
| 809 | if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { | ||
| 810 | /* If there is no ACPI device for handle, return */ | ||
| 811 | return AE_OK; | ||
| 812 | } | ||
| 813 | |||
| 814 | if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) | ||
| 815 | *lid_present = 1; | ||
| 816 | |||
| 817 | return AE_OK; | ||
| 818 | } | ||
| 819 | |||
| 820 | /** | ||
| 821 | * check whether there exists the ACPI LID device by enumerating the ACPI | ||
| 822 | * device tree. | ||
| 823 | */ | ||
| 824 | static int intel_lid_present(void) | ||
| 825 | { | ||
| 826 | int lid_present = 0; | ||
| 827 | |||
| 828 | if (acpi_disabled) { | ||
| 829 | /* If ACPI is disabled, there is no ACPI device tree to | ||
| 830 | * check, so assume the LID device would have been present. | ||
| 831 | */ | ||
| 832 | return 1; | ||
| 833 | } | ||
| 834 | |||
| 835 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 836 | ACPI_UINT32_MAX, | ||
| 837 | check_lid_device, &lid_present, NULL); | ||
| 838 | |||
| 839 | return lid_present; | ||
| 840 | } | ||
| 841 | #else | ||
| 842 | static int intel_lid_present(void) | ||
| 843 | { | ||
| 844 | /* In the absence of ACPI built in, assume that the LID device would | ||
| 845 | * have been present. | ||
| 846 | */ | ||
| 847 | return 1; | ||
| 848 | } | ||
| 849 | #endif | ||
| 850 | |||
| 506 | /** | 851 | /** |
| 507 | * intel_lvds_init - setup LVDS connectors on this device | 852 | * intel_lvds_init - setup LVDS connectors on this device |
| 508 | * @dev: drm device | 853 | * @dev: drm device |
| @@ -518,6 +863,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 518 | struct drm_encoder *encoder; | 863 | struct drm_encoder *encoder; |
| 519 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 864 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
| 520 | struct drm_crtc *crtc; | 865 | struct drm_crtc *crtc; |
| 866 | struct intel_lvds_priv *lvds_priv; | ||
| 521 | u32 lvds; | 867 | u32 lvds; |
| 522 | int pipe, gpio = GPIOC; | 868 | int pipe, gpio = GPIOC; |
| 523 | 869 | ||
| @@ -525,13 +871,24 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 525 | if (dmi_check_system(intel_no_lvds)) | 871 | if (dmi_check_system(intel_no_lvds)) |
| 526 | return; | 872 | return; |
| 527 | 873 | ||
| 874 | /* Assume that any device without an ACPI LID device also doesn't | ||
| 875 | * have an integrated LVDS. We would be better off parsing the BIOS | ||
| 876 | * to get a reliable indicator, but that code isn't written yet. | ||
| 877 | * | ||
| 878 | * In the case of all-in-one desktops using LVDS that we've seen, | ||
| 879 | * they're using SDVO LVDS. | ||
| 880 | */ | ||
| 881 | if (!intel_lid_present()) | ||
| 882 | return; | ||
| 883 | |||
| 528 | if (IS_IGDNG(dev)) { | 884 | if (IS_IGDNG(dev)) { |
| 529 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 885 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
| 530 | return; | 886 | return; |
| 531 | gpio = PCH_GPIOC; | 887 | gpio = PCH_GPIOC; |
| 532 | } | 888 | } |
| 533 | 889 | ||
| 534 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 890 | intel_output = kzalloc(sizeof(struct intel_output) + |
| 891 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | ||
| 535 | if (!intel_output) { | 892 | if (!intel_output) { |
| 536 | return; | 893 | return; |
| 537 | } | 894 | } |
| @@ -553,7 +910,18 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 553 | connector->interlace_allowed = false; | 910 | connector->interlace_allowed = false; |
| 554 | connector->doublescan_allowed = false; | 911 | connector->doublescan_allowed = false; |
| 555 | 912 | ||
| 913 | lvds_priv = (struct intel_lvds_priv *)(intel_output + 1); | ||
| 914 | intel_output->dev_priv = lvds_priv; | ||
| 915 | /* create the scaling mode property */ | ||
| 916 | drm_mode_create_scaling_mode_property(dev); | ||
| 917 | /* | ||
| 918 | * the initial panel fitting mode will be FULL_SCREEN. | ||
| 919 | */ | ||
| 556 | 920 | ||
| 921 | drm_connector_attach_property(&intel_output->base, | ||
| 922 | dev->mode_config.scaling_mode_property, | ||
| 923 | DRM_MODE_SCALE_FULLSCREEN); | ||
| 924 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; | ||
| 557 | /* | 925 | /* |
| 558 | * LVDS discovery: | 926 | * LVDS discovery: |
| 559 | * 1) check for EDID on DDC | 927 | * 1) check for EDID on DDC |
| @@ -649,5 +1017,5 @@ failed: | |||
| 649 | if (intel_output->ddc_bus) | 1017 | if (intel_output->ddc_bus) |
| 650 | intel_i2c_destroy(intel_output->ddc_bus); | 1018 | intel_i2c_destroy(intel_output->ddc_bus); |
| 651 | drm_connector_cleanup(connector); | 1019 | drm_connector_cleanup(connector); |
| 652 | kfree(connector); | 1020 | kfree(intel_output); |
| 653 | } | 1021 | } |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index e0910fefce87..67e2f4632a24 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
| @@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output) | |||
| 53 | } | 53 | } |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 56 | intel_i2c_quirk_set(intel_output->base.dev, true); |
| 57 | ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2); | 57 | ret = i2c_transfer(intel_output->ddc_bus, msgs, 2); |
| 58 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | 58 | intel_i2c_quirk_set(intel_output->base.dev, false); |
| 59 | |||
| 60 | if (ret == 2) | 59 | if (ret == 2) |
| 61 | return true; | 60 | return true; |
| 62 | 61 | ||
| @@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output) | |||
| 74 | struct edid *edid; | 73 | struct edid *edid; |
| 75 | int ret = 0; | 74 | int ret = 0; |
| 76 | 75 | ||
| 77 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 76 | intel_i2c_quirk_set(intel_output->base.dev, true); |
| 78 | edid = drm_get_edid(&intel_output->base, | 77 | edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); |
| 79 | &intel_output->ddc_bus->adapter); | 78 | intel_i2c_quirk_set(intel_output->base.dev, false); |
| 80 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | ||
| 81 | if (edid) { | 79 | if (edid) { |
| 82 | drm_mode_connector_update_edid_property(&intel_output->base, | 80 | drm_mode_connector_update_edid_property(&intel_output->base, |
| 83 | edid); | 81 | edid); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9a00adb3a508..4f0c30948bc4 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | #undef SDVO_DEBUG | 38 | #undef SDVO_DEBUG |
| 39 | #define I915_SDVO "i915_sdvo" | 39 | #define I915_SDVO "i915_sdvo" |
| 40 | struct intel_sdvo_priv { | 40 | struct intel_sdvo_priv { |
| 41 | struct intel_i2c_chan *i2c_bus; | 41 | u8 slave_addr; |
| 42 | int slaveaddr; | ||
| 43 | 42 | ||
| 44 | /* Register for the SDVO device: SDVOB or SDVOC */ | 43 | /* Register for the SDVO device: SDVOB or SDVOC */ |
| 45 | int output_device; | 44 | int output_device; |
| @@ -69,12 +68,23 @@ struct intel_sdvo_priv { | |||
| 69 | * This is set if we treat the device as HDMI, instead of DVI. | 68 | * This is set if we treat the device as HDMI, instead of DVI. |
| 70 | */ | 69 | */ |
| 71 | bool is_hdmi; | 70 | bool is_hdmi; |
| 71 | |||
| 72 | /** | 72 | /** |
| 73 | * This is set if we detect output of sdvo device as LVDS. | 73 | * This is set if we detect output of sdvo device as LVDS. |
| 74 | */ | 74 | */ |
| 75 | bool is_lvds; | 75 | bool is_lvds; |
| 76 | 76 | ||
| 77 | /** | 77 | /** |
| 78 | * This is sdvo flags for input timing. | ||
| 79 | */ | ||
| 80 | uint8_t sdvo_flags; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * This is sdvo fixed pannel mode pointer | ||
| 84 | */ | ||
| 85 | struct drm_display_mode *sdvo_lvds_fixed_mode; | ||
| 86 | |||
| 87 | /** | ||
| 78 | * Returned SDTV resolutions allowed for the current format, if the | 88 | * Returned SDTV resolutions allowed for the current format, if the |
| 79 | * device reported it. | 89 | * device reported it. |
| 80 | */ | 90 | */ |
| @@ -146,13 +156,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 146 | 156 | ||
| 147 | struct i2c_msg msgs[] = { | 157 | struct i2c_msg msgs[] = { |
| 148 | { | 158 | { |
| 149 | .addr = sdvo_priv->i2c_bus->slave_addr, | 159 | .addr = sdvo_priv->slave_addr >> 1, |
| 150 | .flags = 0, | 160 | .flags = 0, |
| 151 | .len = 1, | 161 | .len = 1, |
| 152 | .buf = out_buf, | 162 | .buf = out_buf, |
| 153 | }, | 163 | }, |
| 154 | { | 164 | { |
| 155 | .addr = sdvo_priv->i2c_bus->slave_addr, | 165 | .addr = sdvo_priv->slave_addr >> 1, |
| 156 | .flags = I2C_M_RD, | 166 | .flags = I2C_M_RD, |
| 157 | .len = 1, | 167 | .len = 1, |
| 158 | .buf = buf, | 168 | .buf = buf, |
| @@ -162,7 +172,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 162 | out_buf[0] = addr; | 172 | out_buf[0] = addr; |
| 163 | out_buf[1] = 0; | 173 | out_buf[1] = 0; |
| 164 | 174 | ||
| 165 | if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) | 175 | if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2) |
| 166 | { | 176 | { |
| 167 | *ch = buf[0]; | 177 | *ch = buf[0]; |
| 168 | return true; | 178 | return true; |
| @@ -175,10 +185,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 175 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | 185 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, |
| 176 | u8 ch) | 186 | u8 ch) |
| 177 | { | 187 | { |
| 188 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 178 | u8 out_buf[2]; | 189 | u8 out_buf[2]; |
| 179 | struct i2c_msg msgs[] = { | 190 | struct i2c_msg msgs[] = { |
| 180 | { | 191 | { |
| 181 | .addr = intel_output->i2c_bus->slave_addr, | 192 | .addr = sdvo_priv->slave_addr >> 1, |
| 182 | .flags = 0, | 193 | .flags = 0, |
| 183 | .len = 2, | 194 | .len = 2, |
| 184 | .buf = out_buf, | 195 | .buf = out_buf, |
| @@ -188,7 +199,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
| 188 | out_buf[0] = addr; | 199 | out_buf[0] = addr; |
| 189 | out_buf[1] = ch; | 200 | out_buf[1] = ch; |
| 190 | 201 | ||
| 191 | if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) | 202 | if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1) |
| 192 | { | 203 | { |
| 193 | return true; | 204 | return true; |
| 194 | } | 205 | } |
| @@ -592,6 +603,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 592 | uint16_t height) | 603 | uint16_t height) |
| 593 | { | 604 | { |
| 594 | struct intel_sdvo_preferred_input_timing_args args; | 605 | struct intel_sdvo_preferred_input_timing_args args; |
| 606 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
| 595 | uint8_t status; | 607 | uint8_t status; |
| 596 | 608 | ||
| 597 | memset(&args, 0, sizeof(args)); | 609 | memset(&args, 0, sizeof(args)); |
| @@ -599,7 +611,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 599 | args.width = width; | 611 | args.width = width; |
| 600 | args.height = height; | 612 | args.height = height; |
| 601 | args.interlace = 0; | 613 | args.interlace = 0; |
| 602 | args.scaled = 0; | 614 | |
| 615 | if (sdvo_priv->is_lvds && | ||
| 616 | (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width || | ||
| 617 | sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height)) | ||
| 618 | args.scaled = 1; | ||
| 619 | |||
| 603 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, | 620 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, |
| 604 | &args, sizeof(args)); | 621 | &args, sizeof(args)); |
| 605 | status = intel_sdvo_read_response(output, NULL, 0); | 622 | status = intel_sdvo_read_response(output, NULL, 0); |
| @@ -944,12 +961,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 944 | struct intel_output *output = enc_to_intel_output(encoder); | 961 | struct intel_output *output = enc_to_intel_output(encoder); |
| 945 | struct intel_sdvo_priv *dev_priv = output->dev_priv; | 962 | struct intel_sdvo_priv *dev_priv = output->dev_priv; |
| 946 | 963 | ||
| 947 | if (!dev_priv->is_tv) { | 964 | if (dev_priv->is_tv) { |
| 948 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 949 | * SDVO device will be told of the multiplier during mode_set. | ||
| 950 | */ | ||
| 951 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 952 | } else { | ||
| 953 | struct intel_sdvo_dtd output_dtd; | 965 | struct intel_sdvo_dtd output_dtd; |
| 954 | bool success; | 966 | bool success; |
| 955 | 967 | ||
| @@ -980,6 +992,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 980 | intel_sdvo_get_preferred_input_timing(output, | 992 | intel_sdvo_get_preferred_input_timing(output, |
| 981 | &input_dtd); | 993 | &input_dtd); |
| 982 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | 994 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
| 995 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 983 | 996 | ||
| 984 | drm_mode_set_crtcinfo(adjusted_mode, 0); | 997 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
| 985 | 998 | ||
| @@ -990,6 +1003,52 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 990 | } else { | 1003 | } else { |
| 991 | return false; | 1004 | return false; |
| 992 | } | 1005 | } |
| 1006 | } else if (dev_priv->is_lvds) { | ||
| 1007 | struct intel_sdvo_dtd output_dtd; | ||
| 1008 | bool success; | ||
| 1009 | |||
| 1010 | drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0); | ||
| 1011 | /* Set output timings */ | ||
| 1012 | intel_sdvo_get_dtd_from_mode(&output_dtd, | ||
| 1013 | dev_priv->sdvo_lvds_fixed_mode); | ||
| 1014 | |||
| 1015 | intel_sdvo_set_target_output(output, | ||
| 1016 | dev_priv->controlled_output); | ||
| 1017 | intel_sdvo_set_output_timing(output, &output_dtd); | ||
| 1018 | |||
| 1019 | /* Set the input timing to the screen. Assume always input 0. */ | ||
| 1020 | intel_sdvo_set_target_input(output, true, false); | ||
| 1021 | |||
| 1022 | |||
| 1023 | success = intel_sdvo_create_preferred_input_timing( | ||
| 1024 | output, | ||
| 1025 | mode->clock / 10, | ||
| 1026 | mode->hdisplay, | ||
| 1027 | mode->vdisplay); | ||
| 1028 | |||
| 1029 | if (success) { | ||
| 1030 | struct intel_sdvo_dtd input_dtd; | ||
| 1031 | |||
| 1032 | intel_sdvo_get_preferred_input_timing(output, | ||
| 1033 | &input_dtd); | ||
| 1034 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | ||
| 1035 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 1036 | |||
| 1037 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 1038 | |||
| 1039 | mode->clock = adjusted_mode->clock; | ||
| 1040 | |||
| 1041 | adjusted_mode->clock *= | ||
| 1042 | intel_sdvo_get_pixel_multiplier(mode); | ||
| 1043 | } else { | ||
| 1044 | return false; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | } else { | ||
| 1048 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 1049 | * SDVO device will be told of the multiplier during mode_set. | ||
| 1050 | */ | ||
| 1051 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 993 | } | 1052 | } |
| 994 | return true; | 1053 | return true; |
| 995 | } | 1054 | } |
| @@ -1033,15 +1092,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1033 | 1092 | ||
| 1034 | /* We have tried to get input timing in mode_fixup, and filled into | 1093 | /* We have tried to get input timing in mode_fixup, and filled into |
| 1035 | adjusted_mode */ | 1094 | adjusted_mode */ |
| 1036 | if (sdvo_priv->is_tv) | 1095 | if (sdvo_priv->is_tv || sdvo_priv->is_lvds) { |
| 1037 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1096 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
| 1038 | else | 1097 | input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags; |
| 1098 | } else | ||
| 1039 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); | 1099 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); |
| 1040 | 1100 | ||
| 1041 | /* If it's a TV, we already set the output timing in mode_fixup. | 1101 | /* If it's a TV, we already set the output timing in mode_fixup. |
| 1042 | * Otherwise, the output timing is equal to the input timing. | 1102 | * Otherwise, the output timing is equal to the input timing. |
| 1043 | */ | 1103 | */ |
| 1044 | if (!sdvo_priv->is_tv) { | 1104 | if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) { |
| 1045 | /* Set the output timing to the screen */ | 1105 | /* Set the output timing to the screen */ |
| 1046 | intel_sdvo_set_target_output(output, | 1106 | intel_sdvo_set_target_output(output, |
| 1047 | sdvo_priv->controlled_output); | 1107 | sdvo_priv->controlled_output); |
| @@ -1116,6 +1176,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1116 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; | 1176 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; |
| 1117 | } | 1177 | } |
| 1118 | 1178 | ||
| 1179 | if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL) | ||
| 1180 | sdvox |= SDVO_STALL_SELECT; | ||
| 1119 | intel_sdvo_write_sdvox(output, sdvox); | 1181 | intel_sdvo_write_sdvox(output, sdvox); |
| 1120 | } | 1182 | } |
| 1121 | 1183 | ||
| @@ -1276,6 +1338,17 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, | |||
| 1276 | if (sdvo_priv->pixel_clock_max < mode->clock) | 1338 | if (sdvo_priv->pixel_clock_max < mode->clock) |
| 1277 | return MODE_CLOCK_HIGH; | 1339 | return MODE_CLOCK_HIGH; |
| 1278 | 1340 | ||
| 1341 | if (sdvo_priv->is_lvds == true) { | ||
| 1342 | if (sdvo_priv->sdvo_lvds_fixed_mode == NULL) | ||
| 1343 | return MODE_PANEL; | ||
| 1344 | |||
| 1345 | if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay) | ||
| 1346 | return MODE_PANEL; | ||
| 1347 | |||
| 1348 | if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay) | ||
| 1349 | return MODE_PANEL; | ||
| 1350 | } | ||
| 1351 | |||
| 1279 | return MODE_OK; | 1352 | return MODE_OK; |
| 1280 | } | 1353 | } |
| 1281 | 1354 | ||
| @@ -1369,9 +1442,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1442 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
| 1370 | struct edid *edid = NULL; | 1443 | struct edid *edid = NULL; |
| 1371 | 1444 | ||
| 1372 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
| 1373 | edid = drm_get_edid(&intel_output->base, | 1445 | edid = drm_get_edid(&intel_output->base, |
| 1374 | &intel_output->ddc_bus->adapter); | 1446 | intel_output->ddc_bus); |
| 1375 | if (edid != NULL) { | 1447 | if (edid != NULL) { |
| 1376 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | 1448 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); |
| 1377 | kfree(edid); | 1449 | kfree(edid); |
| @@ -1549,23 +1621,21 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | |||
| 1549 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | 1621 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) |
| 1550 | { | 1622 | { |
| 1551 | struct intel_output *intel_output = to_intel_output(connector); | 1623 | struct intel_output *intel_output = to_intel_output(connector); |
| 1552 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1553 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1624 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1625 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1626 | struct drm_display_mode *newmode; | ||
| 1554 | 1627 | ||
| 1555 | /* | 1628 | /* |
| 1556 | * Attempt to get the mode list from DDC. | 1629 | * Attempt to get the mode list from DDC. |
| 1557 | * Assume that the preferred modes are | 1630 | * Assume that the preferred modes are |
| 1558 | * arranged in priority order. | 1631 | * arranged in priority order. |
| 1559 | */ | 1632 | */ |
| 1560 | /* set the bus switch and get the modes */ | ||
| 1561 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
| 1562 | intel_ddc_get_modes(intel_output); | 1633 | intel_ddc_get_modes(intel_output); |
| 1563 | if (list_empty(&connector->probed_modes) == false) | 1634 | if (list_empty(&connector->probed_modes) == false) |
| 1564 | return; | 1635 | goto end; |
| 1565 | 1636 | ||
| 1566 | /* Fetch modes from VBT */ | 1637 | /* Fetch modes from VBT */ |
| 1567 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { | 1638 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { |
| 1568 | struct drm_display_mode *newmode; | ||
| 1569 | newmode = drm_mode_duplicate(connector->dev, | 1639 | newmode = drm_mode_duplicate(connector->dev, |
| 1570 | dev_priv->sdvo_lvds_vbt_mode); | 1640 | dev_priv->sdvo_lvds_vbt_mode); |
| 1571 | if (newmode != NULL) { | 1641 | if (newmode != NULL) { |
| @@ -1575,6 +1645,16 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1575 | drm_mode_probed_add(connector, newmode); | 1645 | drm_mode_probed_add(connector, newmode); |
| 1576 | } | 1646 | } |
| 1577 | } | 1647 | } |
| 1648 | |||
| 1649 | end: | ||
| 1650 | list_for_each_entry(newmode, &connector->probed_modes, head) { | ||
| 1651 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
| 1652 | sdvo_priv->sdvo_lvds_fixed_mode = | ||
| 1653 | drm_mode_duplicate(connector->dev, newmode); | ||
| 1654 | break; | ||
| 1655 | } | ||
| 1656 | } | ||
| 1657 | |||
| 1578 | } | 1658 | } |
| 1579 | 1659 | ||
| 1580 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 1660 | static int intel_sdvo_get_modes(struct drm_connector *connector) |
| @@ -1597,14 +1677,20 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) | |||
| 1597 | static void intel_sdvo_destroy(struct drm_connector *connector) | 1677 | static void intel_sdvo_destroy(struct drm_connector *connector) |
| 1598 | { | 1678 | { |
| 1599 | struct intel_output *intel_output = to_intel_output(connector); | 1679 | struct intel_output *intel_output = to_intel_output(connector); |
| 1680 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1600 | 1681 | ||
| 1601 | if (intel_output->i2c_bus) | 1682 | if (intel_output->i2c_bus) |
| 1602 | intel_i2c_destroy(intel_output->i2c_bus); | 1683 | intel_i2c_destroy(intel_output->i2c_bus); |
| 1603 | if (intel_output->ddc_bus) | 1684 | if (intel_output->ddc_bus) |
| 1604 | intel_i2c_destroy(intel_output->ddc_bus); | 1685 | intel_i2c_destroy(intel_output->ddc_bus); |
| 1605 | 1686 | ||
| 1687 | if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) | ||
| 1688 | drm_mode_destroy(connector->dev, | ||
| 1689 | sdvo_priv->sdvo_lvds_fixed_mode); | ||
| 1690 | |||
| 1606 | drm_sysfs_connector_remove(connector); | 1691 | drm_sysfs_connector_remove(connector); |
| 1607 | drm_connector_cleanup(connector); | 1692 | drm_connector_cleanup(connector); |
| 1693 | |||
| 1608 | kfree(intel_output); | 1694 | kfree(intel_output); |
| 1609 | } | 1695 | } |
| 1610 | 1696 | ||
| @@ -1709,7 +1795,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan) | |||
| 1709 | 1795 | ||
| 1710 | list_for_each_entry(connector, | 1796 | list_for_each_entry(connector, |
| 1711 | &dev->mode_config.connector_list, head) { | 1797 | &dev->mode_config.connector_list, head) { |
| 1712 | if (to_intel_output(connector)->ddc_bus == chan) { | 1798 | if (to_intel_output(connector)->ddc_bus == &chan->adapter) { |
| 1713 | intel_output = to_intel_output(connector); | 1799 | intel_output = to_intel_output(connector); |
| 1714 | break; | 1800 | break; |
| 1715 | } | 1801 | } |
| @@ -1723,7 +1809,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
| 1723 | struct intel_output *intel_output; | 1809 | struct intel_output *intel_output; |
| 1724 | struct intel_sdvo_priv *sdvo_priv; | 1810 | struct intel_sdvo_priv *sdvo_priv; |
| 1725 | struct i2c_algo_bit_data *algo_data; | 1811 | struct i2c_algo_bit_data *algo_data; |
| 1726 | struct i2c_algorithm *algo; | 1812 | const struct i2c_algorithm *algo; |
| 1727 | 1813 | ||
| 1728 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; | 1814 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; |
| 1729 | intel_output = | 1815 | intel_output = |
| @@ -1733,7 +1819,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
| 1733 | return -EINVAL; | 1819 | return -EINVAL; |
| 1734 | 1820 | ||
| 1735 | sdvo_priv = intel_output->dev_priv; | 1821 | sdvo_priv = intel_output->dev_priv; |
| 1736 | algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo; | 1822 | algo = intel_output->i2c_bus->algo; |
| 1737 | 1823 | ||
| 1738 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | 1824 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); |
| 1739 | return algo->master_xfer(i2c_adap, msgs, num); | 1825 | return algo->master_xfer(i2c_adap, msgs, num); |
| @@ -1785,13 +1871,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1785 | struct drm_connector *connector; | 1871 | struct drm_connector *connector; |
| 1786 | struct intel_output *intel_output; | 1872 | struct intel_output *intel_output; |
| 1787 | struct intel_sdvo_priv *sdvo_priv; | 1873 | struct intel_sdvo_priv *sdvo_priv; |
| 1788 | struct intel_i2c_chan *i2cbus = NULL; | 1874 | |
| 1789 | struct intel_i2c_chan *ddcbus = NULL; | ||
| 1790 | int connector_type; | 1875 | int connector_type; |
| 1791 | u8 ch[0x40]; | 1876 | u8 ch[0x40]; |
| 1792 | int i; | 1877 | int i; |
| 1793 | int encoder_type, output_id; | 1878 | int encoder_type; |
| 1794 | u8 slave_addr; | ||
| 1795 | 1879 | ||
| 1796 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 1880 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
| 1797 | if (!intel_output) { | 1881 | if (!intel_output) { |
| @@ -1799,29 +1883,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1799 | } | 1883 | } |
| 1800 | 1884 | ||
| 1801 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); | 1885 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); |
| 1886 | sdvo_priv->output_device = output_device; | ||
| 1887 | |||
| 1888 | intel_output->dev_priv = sdvo_priv; | ||
| 1802 | intel_output->type = INTEL_OUTPUT_SDVO; | 1889 | intel_output->type = INTEL_OUTPUT_SDVO; |
| 1803 | 1890 | ||
| 1804 | /* setup the DDC bus. */ | 1891 | /* setup the DDC bus. */ |
| 1805 | if (output_device == SDVOB) | 1892 | if (output_device == SDVOB) |
| 1806 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); | 1893 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); |
| 1807 | else | 1894 | else |
| 1808 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); | 1895 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); |
| 1809 | 1896 | ||
| 1810 | if (!i2cbus) | 1897 | if (!intel_output->i2c_bus) |
| 1811 | goto err_inteloutput; | 1898 | goto err_inteloutput; |
| 1812 | 1899 | ||
| 1813 | slave_addr = intel_sdvo_get_slave_addr(dev, output_device); | 1900 | sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device); |
| 1814 | sdvo_priv->i2c_bus = i2cbus; | ||
| 1815 | 1901 | ||
| 1816 | if (output_device == SDVOB) { | 1902 | /* Save the bit-banging i2c functionality for use by the DDC wrapper */ |
| 1817 | output_id = 1; | 1903 | intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality; |
| 1818 | } else { | ||
| 1819 | output_id = 2; | ||
| 1820 | } | ||
| 1821 | sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1; | ||
| 1822 | sdvo_priv->output_device = output_device; | ||
| 1823 | intel_output->i2c_bus = i2cbus; | ||
| 1824 | intel_output->dev_priv = sdvo_priv; | ||
| 1825 | 1904 | ||
| 1826 | /* Read the regs to test if we can talk to the device */ | 1905 | /* Read the regs to test if we can talk to the device */ |
| 1827 | for (i = 0; i < 0x40; i++) { | 1906 | for (i = 0; i < 0x40; i++) { |
| @@ -1835,17 +1914,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1835 | 1914 | ||
| 1836 | /* setup the DDC bus. */ | 1915 | /* setup the DDC bus. */ |
| 1837 | if (output_device == SDVOB) | 1916 | if (output_device == SDVOB) |
| 1838 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); | 1917 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); |
| 1839 | else | 1918 | else |
| 1840 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); | 1919 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); |
| 1841 | 1920 | ||
| 1842 | if (ddcbus == NULL) | 1921 | if (intel_output->ddc_bus == NULL) |
| 1843 | goto err_i2c; | 1922 | goto err_i2c; |
| 1844 | 1923 | ||
| 1845 | intel_sdvo_i2c_bit_algo.functionality = | 1924 | /* Wrap with our custom algo which switches to DDC mode */ |
| 1846 | intel_output->i2c_bus->adapter.algo->functionality; | 1925 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
| 1847 | ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo; | ||
| 1848 | intel_output->ddc_bus = ddcbus; | ||
| 1849 | 1926 | ||
| 1850 | /* In defaut case sdvo lvds is false */ | 1927 | /* In defaut case sdvo lvds is false */ |
| 1851 | sdvo_priv->is_lvds = false; | 1928 | sdvo_priv->is_lvds = false; |
| @@ -1965,9 +2042,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1965 | return true; | 2042 | return true; |
| 1966 | 2043 | ||
| 1967 | err_i2c: | 2044 | err_i2c: |
| 1968 | if (ddcbus != NULL) | 2045 | if (intel_output->ddc_bus != NULL) |
| 1969 | intel_i2c_destroy(intel_output->ddc_bus); | 2046 | intel_i2c_destroy(intel_output->ddc_bus); |
| 1970 | intel_i2c_destroy(intel_output->i2c_bus); | 2047 | if (intel_output->i2c_bus != NULL) |
| 2048 | intel_i2c_destroy(intel_output->i2c_bus); | ||
| 1971 | err_inteloutput: | 2049 | err_inteloutput: |
| 1972 | kfree(intel_output); | 2050 | kfree(intel_output); |
| 1973 | 2051 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 193938b7d7f9..ba5cdf8ae40b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h | |||
| @@ -715,6 +715,7 @@ struct intel_sdvo_enhancements_arg { | |||
| 715 | #define SDVO_HBUF_TX_ONCE (2 << 6) | 715 | #define SDVO_HBUF_TX_ONCE (2 << 6) |
| 716 | #define SDVO_HBUF_TX_VSYNC (3 << 6) | 716 | #define SDVO_HBUF_TX_VSYNC (3 << 6) |
| 717 | #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c | 717 | #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c |
| 718 | #define SDVO_NEED_TO_STALL (1 << 7) | ||
| 718 | 719 | ||
| 719 | struct intel_sdvo_encode{ | 720 | struct intel_sdvo_encode{ |
| 720 | u8 dvi_rev; | 721 | u8 dvi_rev; |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index ea68992e4416..a43c98e3f077 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) | |||
| 1383 | /* | 1383 | /* |
| 1384 | * Detect TV by polling) | 1384 | * Detect TV by polling) |
| 1385 | */ | 1385 | */ |
| 1386 | if (intel_output->load_detect_temp) { | 1386 | save_tv_dac = tv_dac; |
| 1387 | /* TV not currently running, prod it with destructive detect */ | 1387 | tv_ctl = I915_READ(TV_CTL); |
| 1388 | save_tv_dac = tv_dac; | 1388 | save_tv_ctl = tv_ctl; |
| 1389 | tv_ctl = I915_READ(TV_CTL); | 1389 | tv_ctl &= ~TV_ENC_ENABLE; |
| 1390 | save_tv_ctl = tv_ctl; | 1390 | tv_ctl &= ~TV_TEST_MODE_MASK; |
| 1391 | tv_ctl &= ~TV_ENC_ENABLE; | 1391 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; |
| 1392 | tv_ctl &= ~TV_TEST_MODE_MASK; | 1392 | tv_dac &= ~TVDAC_SENSE_MASK; |
| 1393 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; | 1393 | tv_dac &= ~DAC_A_MASK; |
| 1394 | tv_dac &= ~TVDAC_SENSE_MASK; | 1394 | tv_dac &= ~DAC_B_MASK; |
| 1395 | tv_dac &= ~DAC_A_MASK; | 1395 | tv_dac &= ~DAC_C_MASK; |
| 1396 | tv_dac &= ~DAC_B_MASK; | 1396 | tv_dac |= (TVDAC_STATE_CHG_EN | |
| 1397 | tv_dac &= ~DAC_C_MASK; | 1397 | TVDAC_A_SENSE_CTL | |
| 1398 | tv_dac |= (TVDAC_STATE_CHG_EN | | 1398 | TVDAC_B_SENSE_CTL | |
| 1399 | TVDAC_A_SENSE_CTL | | 1399 | TVDAC_C_SENSE_CTL | |
| 1400 | TVDAC_B_SENSE_CTL | | 1400 | DAC_CTL_OVERRIDE | |
| 1401 | TVDAC_C_SENSE_CTL | | 1401 | DAC_A_0_7_V | |
| 1402 | DAC_CTL_OVERRIDE | | 1402 | DAC_B_0_7_V | |
| 1403 | DAC_A_0_7_V | | 1403 | DAC_C_0_7_V); |
| 1404 | DAC_B_0_7_V | | 1404 | I915_WRITE(TV_CTL, tv_ctl); |
| 1405 | DAC_C_0_7_V); | 1405 | I915_WRITE(TV_DAC, tv_dac); |
| 1406 | I915_WRITE(TV_CTL, tv_ctl); | 1406 | intel_wait_for_vblank(dev); |
| 1407 | I915_WRITE(TV_DAC, tv_dac); | 1407 | tv_dac = I915_READ(TV_DAC); |
| 1408 | intel_wait_for_vblank(dev); | 1408 | I915_WRITE(TV_DAC, save_tv_dac); |
| 1409 | tv_dac = I915_READ(TV_DAC); | 1409 | I915_WRITE(TV_CTL, save_tv_ctl); |
| 1410 | I915_WRITE(TV_DAC, save_tv_dac); | 1410 | intel_wait_for_vblank(dev); |
| 1411 | I915_WRITE(TV_CTL, save_tv_ctl); | ||
| 1412 | intel_wait_for_vblank(dev); | ||
| 1413 | } | ||
| 1414 | /* | 1411 | /* |
| 1415 | * A B C | 1412 | * A B C |
| 1416 | * 0 1 1 Composite | 1413 | * 0 1 1 Composite |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f30aa7274a54..f97563db4e59 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -35,6 +35,23 @@ | |||
| 35 | #include "atom.h" | 35 | #include "atom.h" |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * Clear GPU surface registers. | ||
| 39 | */ | ||
| 40 | static void radeon_surface_init(struct radeon_device *rdev) | ||
| 41 | { | ||
| 42 | /* FIXME: check this out */ | ||
| 43 | if (rdev->family < CHIP_R600) { | ||
| 44 | int i; | ||
| 45 | |||
| 46 | for (i = 0; i < 8; i++) { | ||
| 47 | WREG32(RADEON_SURFACE0_INFO + | ||
| 48 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | ||
| 49 | 0); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 38 | * GPU scratch registers helpers function. | 55 | * GPU scratch registers helpers function. |
| 39 | */ | 56 | */ |
| 40 | static void radeon_scratch_init(struct radeon_device *rdev) | 57 | static void radeon_scratch_init(struct radeon_device *rdev) |
| @@ -496,6 +513,8 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 496 | radeon_errata(rdev); | 513 | radeon_errata(rdev); |
| 497 | /* Initialize scratch registers */ | 514 | /* Initialize scratch registers */ |
| 498 | radeon_scratch_init(rdev); | 515 | radeon_scratch_init(rdev); |
| 516 | /* Initialize surface registers */ | ||
| 517 | radeon_surface_init(rdev); | ||
| 499 | 518 | ||
| 500 | /* TODO: disable VGA need to use VGA request */ | 519 | /* TODO: disable VGA need to use VGA request */ |
| 501 | /* BIOS*/ | 520 | /* BIOS*/ |
| @@ -604,9 +623,6 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 604 | if (r) { | 623 | if (r) { |
| 605 | return r; | 624 | return r; |
| 606 | } | 625 | } |
| 607 | if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { | ||
| 608 | rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; | ||
| 609 | } | ||
| 610 | if (!ret) { | 626 | if (!ret) { |
| 611 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); | 627 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); |
| 612 | } | 628 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 09c9fb9f6210..84ba69f48784 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -345,7 +345,7 @@ static void __exit radeon_exit(void) | |||
| 345 | drm_exit(driver); | 345 | drm_exit(driver); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | late_initcall(radeon_init); | 348 | module_init(radeon_init); |
| 349 | module_exit(radeon_exit); | 349 | module_exit(radeon_exit); |
| 350 | 350 | ||
| 351 | MODULE_AUTHOR(DRIVER_AUTHOR); | 351 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fa86d398945e..9e8f191eb64a 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 478 | { | 478 | { |
| 479 | struct fb_info *info; | 479 | struct fb_info *info; |
| 480 | struct radeon_fb_device *rfbdev; | 480 | struct radeon_fb_device *rfbdev; |
| 481 | struct drm_framebuffer *fb; | 481 | struct drm_framebuffer *fb = NULL; |
| 482 | struct radeon_framebuffer *rfb; | 482 | struct radeon_framebuffer *rfb; |
| 483 | struct drm_mode_fb_cmd mode_cmd; | 483 | struct drm_mode_fb_cmd mode_cmd; |
| 484 | struct drm_gem_object *gobj = NULL; | 484 | struct drm_gem_object *gobj = NULL; |
| 485 | struct radeon_object *robj = NULL; | 485 | struct radeon_object *robj = NULL; |
| 486 | struct device *device = &rdev->pdev->dev; | 486 | struct device *device = &rdev->pdev->dev; |
| 487 | int size, aligned_size, ret; | 487 | int size, aligned_size, ret; |
| 488 | u64 fb_gpuaddr; | ||
| 488 | void *fbptr = NULL; | 489 | void *fbptr = NULL; |
| 490 | unsigned long tmp; | ||
| 489 | 491 | ||
| 490 | mode_cmd.width = surface_width; | 492 | mode_cmd.width = surface_width; |
| 491 | mode_cmd.height = surface_height; | 493 | mode_cmd.height = surface_height; |
| @@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 498 | aligned_size = ALIGN(size, PAGE_SIZE); | 500 | aligned_size = ALIGN(size, PAGE_SIZE); |
| 499 | 501 | ||
| 500 | ret = radeon_gem_object_create(rdev, aligned_size, 0, | 502 | ret = radeon_gem_object_create(rdev, aligned_size, 0, |
| 501 | RADEON_GEM_DOMAIN_VRAM, | 503 | RADEON_GEM_DOMAIN_VRAM, |
| 502 | false, ttm_bo_type_kernel, | 504 | false, ttm_bo_type_kernel, |
| 503 | false, &gobj); | 505 | false, &gobj); |
| 504 | if (ret) { | 506 | if (ret) { |
| 505 | printk(KERN_ERR "failed to allocate framebuffer\n"); | 507 | printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", |
| 508 | surface_width, surface_height); | ||
| 506 | ret = -ENOMEM; | 509 | ret = -ENOMEM; |
| 507 | goto out; | 510 | goto out; |
| 508 | } | 511 | } |
| @@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 515 | ret = -ENOMEM; | 518 | ret = -ENOMEM; |
| 516 | goto out_unref; | 519 | goto out_unref; |
| 517 | } | 520 | } |
| 521 | ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); | ||
| 522 | if (ret) { | ||
| 523 | printk(KERN_ERR "failed to pin framebuffer\n"); | ||
| 524 | ret = -ENOMEM; | ||
| 525 | goto out_unref; | ||
| 526 | } | ||
| 518 | 527 | ||
| 519 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); | 528 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); |
| 520 | 529 | ||
| 521 | rfb = to_radeon_framebuffer(fb); | 530 | rfb = to_radeon_framebuffer(fb); |
| 522 | *rfb_p = rfb; | 531 | *rfb_p = rfb; |
| 523 | rdev->fbdev_rfb = rfb; | 532 | rdev->fbdev_rfb = rfb; |
| 533 | rdev->fbdev_robj = robj; | ||
| 524 | 534 | ||
| 525 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); | 535 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); |
| 526 | if (info == NULL) { | 536 | if (info == NULL) { |
| @@ -541,13 +551,13 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 541 | info->fix.xpanstep = 1; /* doing it in hw */ | 551 | info->fix.xpanstep = 1; /* doing it in hw */ |
| 542 | info->fix.ypanstep = 1; /* doing it in hw */ | 552 | info->fix.ypanstep = 1; /* doing it in hw */ |
| 543 | info->fix.ywrapstep = 0; | 553 | info->fix.ywrapstep = 0; |
| 544 | info->fix.accel = FB_ACCEL_I830; | 554 | info->fix.accel = FB_ACCEL_NONE; |
| 545 | info->fix.type_aux = 0; | 555 | info->fix.type_aux = 0; |
| 546 | info->flags = FBINFO_DEFAULT; | 556 | info->flags = FBINFO_DEFAULT; |
| 547 | info->fbops = &radeonfb_ops; | 557 | info->fbops = &radeonfb_ops; |
| 548 | info->fix.line_length = fb->pitch; | 558 | info->fix.line_length = fb->pitch; |
| 549 | info->screen_base = fbptr; | 559 | tmp = fb_gpuaddr - rdev->mc.vram_location; |
| 550 | info->fix.smem_start = (unsigned long)fbptr; | 560 | info->fix.smem_start = rdev->mc.aper_base + tmp; |
| 551 | info->fix.smem_len = size; | 561 | info->fix.smem_len = size; |
| 552 | info->screen_base = fbptr; | 562 | info->screen_base = fbptr; |
| 553 | info->screen_size = size; | 563 | info->screen_size = size; |
| @@ -562,8 +572,8 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 562 | info->var.width = -1; | 572 | info->var.width = -1; |
| 563 | info->var.xres = fb_width; | 573 | info->var.xres = fb_width; |
| 564 | info->var.yres = fb_height; | 574 | info->var.yres = fb_height; |
| 565 | info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); | 575 | info->fix.mmio_start = 0; |
| 566 | info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); | 576 | info->fix.mmio_len = 0; |
| 567 | info->pixmap.size = 64*1024; | 577 | info->pixmap.size = 64*1024; |
| 568 | info->pixmap.buf_align = 8; | 578 | info->pixmap.buf_align = 8; |
| 569 | info->pixmap.access_align = 32; | 579 | info->pixmap.access_align = 32; |
| @@ -644,7 +654,7 @@ out_unref: | |||
| 644 | if (robj) { | 654 | if (robj) { |
| 645 | radeon_object_kunmap(robj); | 655 | radeon_object_kunmap(robj); |
| 646 | } | 656 | } |
| 647 | if (ret) { | 657 | if (fb && ret) { |
| 648 | list_del(&fb->filp_head); | 658 | list_del(&fb->filp_head); |
| 649 | drm_gem_object_unreference(gobj); | 659 | drm_gem_object_unreference(gobj); |
| 650 | drm_framebuffer_cleanup(fb); | 660 | drm_framebuffer_cleanup(fb); |
| @@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | |||
| 813 | robj = rfb->obj->driver_private; | 823 | robj = rfb->obj->driver_private; |
| 814 | unregister_framebuffer(info); | 824 | unregister_framebuffer(info); |
| 815 | radeon_object_kunmap(robj); | 825 | radeon_object_kunmap(robj); |
| 826 | radeon_object_unpin(robj); | ||
| 816 | framebuffer_release(info); | 827 | framebuffer_release(info); |
| 817 | } | 828 | } |
| 818 | 829 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 983e8df5e000..bac0d06c52ac 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 223 | { | 223 | { |
| 224 | uint32_t flags; | 224 | uint32_t flags; |
| 225 | uint32_t tmp; | 225 | uint32_t tmp; |
| 226 | void *fbptr; | ||
| 227 | int r; | 226 | int r; |
| 228 | 227 | ||
| 229 | flags = radeon_object_flags_from_domain(domain); | 228 | flags = radeon_object_flags_from_domain(domain); |
| @@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 242 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); | 241 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); |
| 243 | return r; | 242 | return r; |
| 244 | } | 243 | } |
| 245 | if (robj->rdev->fbdev_robj == robj) { | ||
| 246 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 247 | radeon_object_kunmap(robj); | ||
| 248 | } | ||
| 249 | tmp = robj->tobj.mem.placement; | 244 | tmp = robj->tobj.mem.placement; |
| 250 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); | 245 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); |
| 251 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; | 246 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; |
| @@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 261 | DRM_ERROR("radeon: failed to pin object.\n"); | 256 | DRM_ERROR("radeon: failed to pin object.\n"); |
| 262 | } | 257 | } |
| 263 | radeon_object_unreserve(robj); | 258 | radeon_object_unreserve(robj); |
| 264 | if (robj->rdev->fbdev_robj == robj) { | ||
| 265 | if (!r) { | ||
| 266 | r = radeon_object_kmap(robj, &fbptr); | ||
| 267 | } | ||
| 268 | if (!r) { | ||
| 269 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 270 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 271 | } | ||
| 272 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 273 | } | ||
| 274 | return r; | 259 | return r; |
| 275 | } | 260 | } |
| 276 | 261 | ||
| 277 | void radeon_object_unpin(struct radeon_object *robj) | 262 | void radeon_object_unpin(struct radeon_object *robj) |
| 278 | { | 263 | { |
| 279 | uint32_t flags; | 264 | uint32_t flags; |
| 280 | void *fbptr; | ||
| 281 | int r; | 265 | int r; |
| 282 | 266 | ||
| 283 | spin_lock(&robj->tobj.lock); | 267 | spin_lock(&robj->tobj.lock); |
| @@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
| 297 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); | 281 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); |
| 298 | return; | 282 | return; |
| 299 | } | 283 | } |
| 300 | if (robj->rdev->fbdev_robj == robj) { | ||
| 301 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 302 | radeon_object_kunmap(robj); | ||
| 303 | } | ||
| 304 | flags = robj->tobj.mem.placement; | 284 | flags = robj->tobj.mem.placement; |
| 305 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; | 285 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; |
| 306 | r = ttm_buffer_object_validate(&robj->tobj, | 286 | r = ttm_buffer_object_validate(&robj->tobj, |
| @@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
| 310 | DRM_ERROR("radeon: failed to unpin buffer.\n"); | 290 | DRM_ERROR("radeon: failed to unpin buffer.\n"); |
| 311 | } | 291 | } |
| 312 | radeon_object_unreserve(robj); | 292 | radeon_object_unreserve(robj); |
| 313 | if (robj->rdev->fbdev_robj == robj) { | ||
| 314 | if (!r) { | ||
| 315 | r = radeon_object_kmap(robj, &fbptr); | ||
| 316 | } | ||
| 317 | if (!r) { | ||
| 318 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 319 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 320 | } | ||
| 321 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 322 | } | ||
| 323 | } | 293 | } |
| 324 | 294 | ||
| 325 | int radeon_object_wait(struct radeon_object *robj) | 295 | int radeon_object_wait(struct radeon_object *robj) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 517c84559633..bdec583901eb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
| 35 | #include <linux/wait.h> | 35 | #include <linux/wait.h> |
| 36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
| 37 | #include <linux/version.h> | ||
| 38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 39 | 38 | ||
| 40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) | 39 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 27b146c54fbc..fe949a12fe40 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <ttm/ttm_bo_driver.h> | 32 | #include <ttm/ttm_bo_driver.h> |
| 33 | #include <ttm/ttm_placement.h> | 33 | #include <ttm/ttm_placement.h> |
| 34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
| 35 | #include <linux/version.h> | ||
| 36 | #include <linux/rbtree.h> | 35 | #include <linux/rbtree.h> |
| 37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 38 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
| @@ -328,7 +327,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, | |||
| 328 | goto out_unref; | 327 | goto out_unref; |
| 329 | 328 | ||
| 330 | kmap_offset = dev_offset - bo->vm_node->start; | 329 | kmap_offset = dev_offset - bo->vm_node->start; |
| 331 | if (unlikely(kmap_offset) >= bo->num_pages) { | 330 | if (unlikely(kmap_offset >= bo->num_pages)) { |
| 332 | ret = -EFBIG; | 331 | ret = -EFBIG; |
| 333 | goto out_unref; | 332 | goto out_unref; |
| 334 | } | 333 | } |
| @@ -402,7 +401,7 @@ ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf, | |||
| 402 | bool dummy; | 401 | bool dummy; |
| 403 | 402 | ||
| 404 | kmap_offset = (*f_pos >> PAGE_SHIFT); | 403 | kmap_offset = (*f_pos >> PAGE_SHIFT); |
| 405 | if (unlikely(kmap_offset) >= bo->num_pages) | 404 | if (unlikely(kmap_offset >= bo->num_pages)) |
| 406 | return -EFBIG; | 405 | return -EFBIG; |
| 407 | 406 | ||
| 408 | page_offset = *f_pos & ~PAGE_MASK; | 407 | page_offset = *f_pos & ~PAGE_MASK; |
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 0331fa74cd3f..75dc8bd24592 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <linux/version.h> | ||
| 32 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
| 33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 34 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index c248c1d37268..5935b8842e86 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c | |||
| @@ -183,7 +183,7 @@ int via_enable_vblank(struct drm_device *dev, int crtc) | |||
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | status = VIA_READ(VIA_REG_INTERRUPT); | 185 | status = VIA_READ(VIA_REG_INTERRUPT); |
| 186 | VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE); | 186 | VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); |
| 187 | 187 | ||
| 188 | VIA_WRITE8(0x83d4, 0x11); | 188 | VIA_WRITE8(0x83d4, 0x11); |
| 189 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); | 189 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); |
| @@ -194,6 +194,10 @@ int via_enable_vblank(struct drm_device *dev, int crtc) | |||
| 194 | void via_disable_vblank(struct drm_device *dev, int crtc) | 194 | void via_disable_vblank(struct drm_device *dev, int crtc) |
| 195 | { | 195 | { |
| 196 | drm_via_private_t *dev_priv = dev->dev_private; | 196 | drm_via_private_t *dev_priv = dev->dev_private; |
| 197 | u32 status; | ||
| 198 | |||
| 199 | status = VIA_READ(VIA_REG_INTERRUPT); | ||
| 200 | VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); | ||
| 197 | 201 | ||
| 198 | VIA_WRITE8(0x83d4, 0x11); | 202 | VIA_WRITE8(0x83d4, 0x11); |
| 199 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); | 203 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 76c4bbe9dccb..3c1fcb7640ab 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
| 23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
| 24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
| 25 | #include <linux/smp_lock.h> | ||
| 26 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
| 27 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
| 28 | #include <asm/byteorder.h> | 27 | #include <asm/byteorder.h> |
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index ad2b3431b725..7d3f15d32fdf 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c | |||
| @@ -357,7 +357,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
| 357 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, | 357 | { "AUX5 Fan", 39, 2, 60, 1, 0 }, |
| 358 | { NULL, 0, 0, 0, 0, 0 } } | 358 | { NULL, 0, 0, 0, 0, 0 } } |
| 359 | }, | 359 | }, |
| 360 | { 0x0014, NULL /* Abit AB9 Pro, need DMI string */, { | 360 | { 0x0014, "AB9", /* + AB9 Pro */ { |
| 361 | { "CPU Core", 0, 0, 10, 1, 0 }, | 361 | { "CPU Core", 0, 0, 10, 1, 0 }, |
| 362 | { "DDR", 1, 0, 10, 1, 0 }, | 362 | { "DDR", 1, 0, 10, 1, 0 }, |
| 363 | { "DDR VTT", 2, 0, 10, 1, 0 }, | 363 | { "DDR VTT", 2, 0, 10, 1, 0 }, |
| @@ -455,7 +455,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
| 455 | { "AUX3 FAN", 37, 2, 60, 1, 0 }, | 455 | { "AUX3 FAN", 37, 2, 60, 1, 0 }, |
| 456 | { NULL, 0, 0, 0, 0, 0 } } | 456 | { NULL, 0, 0, 0, 0, 0 } } |
| 457 | }, | 457 | }, |
| 458 | { 0x0018, NULL /* Unknown, need DMI string */, { | 458 | { 0x0018, "AB9 QuadGT", { |
| 459 | { "CPU Core", 0, 0, 10, 1, 0 }, | 459 | { "CPU Core", 0, 0, 10, 1, 0 }, |
| 460 | { "DDR2", 1, 0, 20, 1, 0 }, | 460 | { "DDR2", 1, 0, 20, 1, 0 }, |
| 461 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 461 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
| @@ -564,7 +564,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { | |||
| 564 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, | 564 | { "AUX3 Fan", 36, 2, 60, 1, 0 }, |
| 565 | { NULL, 0, 0, 0, 0, 0 } } | 565 | { NULL, 0, 0, 0, 0, 0 } } |
| 566 | }, | 566 | }, |
| 567 | { 0x001C, NULL /* Unknown, need DMI string */, { | 567 | { 0x001C, "IX38 QuadGT", { |
| 568 | { "CPU Core", 0, 0, 10, 1, 0 }, | 568 | { "CPU Core", 0, 0, 10, 1, 0 }, |
| 569 | { "DDR2", 1, 0, 20, 1, 0 }, | 569 | { "DDR2", 1, 0, 20, 1, 0 }, |
| 570 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, | 570 | { "DDR2 VTT", 2, 0, 10, 1, 0 }, |
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 86142a858238..58f66be61b1f 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c | |||
| @@ -418,6 +418,7 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr, | |||
| 418 | data->count = 3; | 418 | data->count = 3; |
| 419 | break; | 419 | break; |
| 420 | default: | 420 | default: |
| 421 | mutex_unlock(&data->update_lock); | ||
| 421 | dev_err(&client->dev, | 422 | dev_err(&client->dev, |
| 422 | "illegal value for fan divider (%d)\n", div); | 423 | "illegal value for fan divider (%d)\n", div); |
| 423 | return -EINVAL; | 424 | return -EINVAL; |
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 56cd6004da36..6290a259456e 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c | |||
| @@ -257,7 +257,7 @@ static inline int sht15_update_single_val(struct sht15_data *data, | |||
| 257 | (data->flag == SHT15_READING_NOTHING), | 257 | (data->flag == SHT15_READING_NOTHING), |
| 258 | msecs_to_jiffies(timeout_msecs)); | 258 | msecs_to_jiffies(timeout_msecs)); |
| 259 | if (ret == 0) {/* timeout occurred */ | 259 | if (ret == 0) {/* timeout occurred */ |
| 260 | disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));; | 260 | disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); |
| 261 | sht15_connection_reset(data); | 261 | sht15_connection_reset(data); |
| 262 | return -ETIME; | 262 | return -ETIME; |
| 263 | } | 263 | } |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 3c259ee7ddda..8206442fbabd 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -326,6 +326,16 @@ config I2C_DAVINCI | |||
| 326 | devices such as DaVinci NIC. | 326 | devices such as DaVinci NIC. |
| 327 | For details please see http://www.ti.com/davinci | 327 | For details please see http://www.ti.com/davinci |
| 328 | 328 | ||
| 329 | config I2C_DESIGNWARE | ||
| 330 | tristate "Synopsys DesignWare" | ||
| 331 | depends on HAVE_CLK | ||
| 332 | help | ||
| 333 | If you say yes to this option, support will be included for the | ||
| 334 | Synopsys DesignWare I2C adapter. Only master mode is supported. | ||
| 335 | |||
| 336 | This driver can also be built as a module. If so, the module | ||
| 337 | will be called i2c-designware. | ||
| 338 | |||
| 329 | config I2C_GPIO | 339 | config I2C_GPIO |
| 330 | tristate "GPIO-based bitbanging I2C" | 340 | tristate "GPIO-based bitbanging I2C" |
| 331 | depends on GENERIC_GPIO | 341 | depends on GENERIC_GPIO |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index edeabf003106..e654263bfc01 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
| @@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o | |||
| 30 | obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o | 30 | obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o |
| 31 | obj-$(CONFIG_I2C_CPM) += i2c-cpm.o | 31 | obj-$(CONFIG_I2C_CPM) += i2c-cpm.o |
| 32 | obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o | 32 | obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o |
| 33 | obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o | ||
| 33 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o | 34 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o |
| 34 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o | 35 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o |
| 35 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o | 36 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o |
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 3fae3a91ce5b..c89687a10835 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c | |||
| @@ -187,6 +187,11 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
| 187 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); | 187 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); |
| 188 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); | 188 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); |
| 189 | 189 | ||
| 190 | /* Respond at reserved "SMBus Host" slave address" (and zero); | ||
| 191 | * we seem to have no option to not respond... | ||
| 192 | */ | ||
| 193 | davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); | ||
| 194 | |||
| 190 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); | 195 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); |
| 191 | dev_dbg(dev->dev, "PSC = %d\n", | 196 | dev_dbg(dev->dev, "PSC = %d\n", |
| 192 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); | 197 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); |
| @@ -387,7 +392,7 @@ static void terminate_write(struct davinci_i2c_dev *dev) | |||
| 387 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | 392 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); |
| 388 | 393 | ||
| 389 | if (!dev->terminate) | 394 | if (!dev->terminate) |
| 390 | dev_err(dev->dev, "TDR IRQ while no data to send\n"); | 395 | dev_dbg(dev->dev, "TDR IRQ while no data to send\n"); |
| 391 | } | 396 | } |
| 392 | 397 | ||
| 393 | /* | 398 | /* |
| @@ -473,9 +478,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) | |||
| 473 | break; | 478 | break; |
| 474 | 479 | ||
| 475 | case DAVINCI_I2C_IVR_AAS: | 480 | case DAVINCI_I2C_IVR_AAS: |
| 476 | dev_warn(dev->dev, "Address as slave interrupt\n"); | 481 | dev_dbg(dev->dev, "Address as slave interrupt\n"); |
| 477 | }/* switch */ | 482 | break; |
| 478 | }/* while */ | 483 | |
| 484 | default: | ||
| 485 | dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat); | ||
| 486 | break; | ||
| 487 | } | ||
| 488 | } | ||
| 479 | 489 | ||
| 480 | return count ? IRQ_HANDLED : IRQ_NONE; | 490 | return count ? IRQ_HANDLED : IRQ_NONE; |
| 481 | } | 491 | } |
| @@ -505,7 +515,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
| 505 | return -ENODEV; | 515 | return -ENODEV; |
| 506 | } | 516 | } |
| 507 | 517 | ||
| 508 | ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1, | 518 | ioarea = request_mem_region(mem->start, resource_size(mem), |
| 509 | pdev->name); | 519 | pdev->name); |
| 510 | if (!ioarea) { | 520 | if (!ioarea) { |
| 511 | dev_err(&pdev->dev, "I2C region already claimed\n"); | 521 | dev_err(&pdev->dev, "I2C region already claimed\n"); |
| @@ -523,7 +533,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) | |||
| 523 | dev->irq = irq->start; | 533 | dev->irq = irq->start; |
| 524 | platform_set_drvdata(pdev, dev); | 534 | platform_set_drvdata(pdev, dev); |
| 525 | 535 | ||
| 526 | dev->clk = clk_get(&pdev->dev, "I2CCLK"); | 536 | dev->clk = clk_get(&pdev->dev, NULL); |
| 527 | if (IS_ERR(dev->clk)) { | 537 | if (IS_ERR(dev->clk)) { |
| 528 | r = -ENODEV; | 538 | r = -ENODEV; |
| 529 | goto err_free_mem; | 539 | goto err_free_mem; |
| @@ -568,7 +578,7 @@ err_free_mem: | |||
| 568 | put_device(&pdev->dev); | 578 | put_device(&pdev->dev); |
| 569 | kfree(dev); | 579 | kfree(dev); |
| 570 | err_release_region: | 580 | err_release_region: |
| 571 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 581 | release_mem_region(mem->start, resource_size(mem)); |
| 572 | 582 | ||
| 573 | return r; | 583 | return r; |
| 574 | } | 584 | } |
| @@ -591,7 +601,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) | |||
| 591 | kfree(dev); | 601 | kfree(dev); |
| 592 | 602 | ||
| 593 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 603 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 594 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 604 | release_mem_region(mem->start, resource_size(mem)); |
| 595 | return 0; | 605 | return 0; |
| 596 | } | 606 | } |
| 597 | 607 | ||
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c new file mode 100644 index 000000000000..b444762e9b9f --- /dev/null +++ b/drivers/i2c/busses/i2c-designware.c | |||
| @@ -0,0 +1,624 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys Designware I2C adapter driver (master only). | ||
| 3 | * | ||
| 4 | * Based on the TI DAVINCI I2C adapter driver. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2006 Texas Instruments. | ||
| 7 | * Copyright (C) 2007 MontaVista Software Inc. | ||
| 8 | * Copyright (C) 2009 Provigent Ltd. | ||
| 9 | * | ||
| 10 | * ---------------------------------------------------------------------------- | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2 of the License, or | ||
| 15 | * (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | * ---------------------------------------------------------------------------- | ||
| 26 | * | ||
| 27 | */ | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/i2c.h> | ||
| 32 | #include <linux/clk.h> | ||
| 33 | #include <linux/errno.h> | ||
| 34 | #include <linux/sched.h> | ||
| 35 | #include <linux/err.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/platform_device.h> | ||
| 38 | #include <linux/io.h> | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Registers offset | ||
| 42 | */ | ||
| 43 | #define DW_IC_CON 0x0 | ||
| 44 | #define DW_IC_TAR 0x4 | ||
| 45 | #define DW_IC_DATA_CMD 0x10 | ||
| 46 | #define DW_IC_SS_SCL_HCNT 0x14 | ||
| 47 | #define DW_IC_SS_SCL_LCNT 0x18 | ||
| 48 | #define DW_IC_FS_SCL_HCNT 0x1c | ||
| 49 | #define DW_IC_FS_SCL_LCNT 0x20 | ||
| 50 | #define DW_IC_INTR_STAT 0x2c | ||
| 51 | #define DW_IC_INTR_MASK 0x30 | ||
| 52 | #define DW_IC_CLR_INTR 0x40 | ||
| 53 | #define DW_IC_ENABLE 0x6c | ||
| 54 | #define DW_IC_STATUS 0x70 | ||
| 55 | #define DW_IC_TXFLR 0x74 | ||
| 56 | #define DW_IC_RXFLR 0x78 | ||
| 57 | #define DW_IC_COMP_PARAM_1 0xf4 | ||
| 58 | #define DW_IC_TX_ABRT_SOURCE 0x80 | ||
| 59 | |||
| 60 | #define DW_IC_CON_MASTER 0x1 | ||
| 61 | #define DW_IC_CON_SPEED_STD 0x2 | ||
| 62 | #define DW_IC_CON_SPEED_FAST 0x4 | ||
| 63 | #define DW_IC_CON_10BITADDR_MASTER 0x10 | ||
| 64 | #define DW_IC_CON_RESTART_EN 0x20 | ||
| 65 | #define DW_IC_CON_SLAVE_DISABLE 0x40 | ||
| 66 | |||
| 67 | #define DW_IC_INTR_TX_EMPTY 0x10 | ||
| 68 | #define DW_IC_INTR_TX_ABRT 0x40 | ||
| 69 | #define DW_IC_INTR_STOP_DET 0x200 | ||
| 70 | |||
| 71 | #define DW_IC_STATUS_ACTIVITY 0x1 | ||
| 72 | |||
| 73 | #define DW_IC_ERR_TX_ABRT 0x1 | ||
| 74 | |||
| 75 | /* | ||
| 76 | * status codes | ||
| 77 | */ | ||
| 78 | #define STATUS_IDLE 0x0 | ||
| 79 | #define STATUS_WRITE_IN_PROGRESS 0x1 | ||
| 80 | #define STATUS_READ_IN_PROGRESS 0x2 | ||
| 81 | |||
| 82 | #define TIMEOUT 20 /* ms */ | ||
| 83 | |||
| 84 | /* | ||
| 85 | * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register | ||
| 86 | * | ||
| 87 | * only expected abort codes are listed here | ||
| 88 | * refer to the datasheet for the full list | ||
| 89 | */ | ||
| 90 | #define ABRT_7B_ADDR_NOACK 0 | ||
| 91 | #define ABRT_10ADDR1_NOACK 1 | ||
| 92 | #define ABRT_10ADDR2_NOACK 2 | ||
| 93 | #define ABRT_TXDATA_NOACK 3 | ||
| 94 | #define ABRT_GCALL_NOACK 4 | ||
| 95 | #define ABRT_GCALL_READ 5 | ||
| 96 | #define ABRT_SBYTE_ACKDET 7 | ||
| 97 | #define ABRT_SBYTE_NORSTRT 9 | ||
| 98 | #define ABRT_10B_RD_NORSTRT 10 | ||
| 99 | #define ARB_MASTER_DIS 11 | ||
| 100 | #define ARB_LOST 12 | ||
| 101 | |||
| 102 | static char *abort_sources[] = { | ||
| 103 | [ABRT_7B_ADDR_NOACK] = | ||
| 104 | "slave address not acknowledged (7bit mode)", | ||
| 105 | [ABRT_10ADDR1_NOACK] = | ||
| 106 | "first address byte not acknowledged (10bit mode)", | ||
| 107 | [ABRT_10ADDR2_NOACK] = | ||
| 108 | "second address byte not acknowledged (10bit mode)", | ||
| 109 | [ABRT_TXDATA_NOACK] = | ||
| 110 | "data not acknowledged", | ||
| 111 | [ABRT_GCALL_NOACK] = | ||
| 112 | "no acknowledgement for a general call", | ||
| 113 | [ABRT_GCALL_READ] = | ||
| 114 | "read after general call", | ||
| 115 | [ABRT_SBYTE_ACKDET] = | ||
| 116 | "start byte acknowledged", | ||
| 117 | [ABRT_SBYTE_NORSTRT] = | ||
| 118 | "trying to send start byte when restart is disabled", | ||
| 119 | [ABRT_10B_RD_NORSTRT] = | ||
| 120 | "trying to read when restart is disabled (10bit mode)", | ||
| 121 | [ARB_MASTER_DIS] = | ||
| 122 | "trying to use disabled adapter", | ||
| 123 | [ARB_LOST] = | ||
| 124 | "lost arbitration", | ||
| 125 | }; | ||
| 126 | |||
| 127 | /** | ||
| 128 | * struct dw_i2c_dev - private i2c-designware data | ||
| 129 | * @dev: driver model device node | ||
| 130 | * @base: IO registers pointer | ||
| 131 | * @cmd_complete: tx completion indicator | ||
| 132 | * @pump_msg: continue in progress transfers | ||
| 133 | * @lock: protect this struct and IO registers | ||
| 134 | * @clk: input reference clock | ||
| 135 | * @cmd_err: run time hadware error code | ||
| 136 | * @msgs: points to an array of messages currently being transfered | ||
| 137 | * @msgs_num: the number of elements in msgs | ||
| 138 | * @msg_write_idx: the element index of the current tx message in the msgs | ||
| 139 | * array | ||
| 140 | * @tx_buf_len: the length of the current tx buffer | ||
| 141 | * @tx_buf: the current tx buffer | ||
| 142 | * @msg_read_idx: the element index of the current rx message in the msgs | ||
| 143 | * array | ||
| 144 | * @rx_buf_len: the length of the current rx buffer | ||
| 145 | * @rx_buf: the current rx buffer | ||
| 146 | * @msg_err: error status of the current transfer | ||
| 147 | * @status: i2c master status, one of STATUS_* | ||
| 148 | * @abort_source: copy of the TX_ABRT_SOURCE register | ||
| 149 | * @irq: interrupt number for the i2c master | ||
| 150 | * @adapter: i2c subsystem adapter node | ||
| 151 | * @tx_fifo_depth: depth of the hardware tx fifo | ||
| 152 | * @rx_fifo_depth: depth of the hardware rx fifo | ||
| 153 | */ | ||
| 154 | struct dw_i2c_dev { | ||
| 155 | struct device *dev; | ||
| 156 | void __iomem *base; | ||
| 157 | struct completion cmd_complete; | ||
| 158 | struct tasklet_struct pump_msg; | ||
| 159 | struct mutex lock; | ||
| 160 | struct clk *clk; | ||
| 161 | int cmd_err; | ||
| 162 | struct i2c_msg *msgs; | ||
| 163 | int msgs_num; | ||
| 164 | int msg_write_idx; | ||
| 165 | u16 tx_buf_len; | ||
| 166 | u8 *tx_buf; | ||
| 167 | int msg_read_idx; | ||
| 168 | u16 rx_buf_len; | ||
| 169 | u8 *rx_buf; | ||
| 170 | int msg_err; | ||
| 171 | unsigned int status; | ||
| 172 | u16 abort_source; | ||
| 173 | int irq; | ||
| 174 | struct i2c_adapter adapter; | ||
| 175 | unsigned int tx_fifo_depth; | ||
| 176 | unsigned int rx_fifo_depth; | ||
| 177 | }; | ||
| 178 | |||
| 179 | /** | ||
| 180 | * i2c_dw_init() - initialize the designware i2c master hardware | ||
| 181 | * @dev: device private data | ||
| 182 | * | ||
| 183 | * This functions configures and enables the I2C master. | ||
| 184 | * This function is called during I2C init function, and in case of timeout at | ||
| 185 | * run time. | ||
| 186 | */ | ||
| 187 | static void i2c_dw_init(struct dw_i2c_dev *dev) | ||
| 188 | { | ||
| 189 | u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; | ||
| 190 | u16 ic_con; | ||
| 191 | |||
| 192 | /* Disable the adapter */ | ||
| 193 | writeb(0, dev->base + DW_IC_ENABLE); | ||
| 194 | |||
| 195 | /* set standard and fast speed deviders for high/low periods */ | ||
| 196 | writew((input_clock_khz * 40 / 10000)+1, /* std speed high, 4us */ | ||
| 197 | dev->base + DW_IC_SS_SCL_HCNT); | ||
| 198 | writew((input_clock_khz * 47 / 10000)+1, /* std speed low, 4.7us */ | ||
| 199 | dev->base + DW_IC_SS_SCL_LCNT); | ||
| 200 | writew((input_clock_khz * 6 / 10000)+1, /* fast speed high, 0.6us */ | ||
| 201 | dev->base + DW_IC_FS_SCL_HCNT); | ||
| 202 | writew((input_clock_khz * 13 / 10000)+1, /* fast speed low, 1.3us */ | ||
| 203 | dev->base + DW_IC_FS_SCL_LCNT); | ||
| 204 | |||
| 205 | /* configure the i2c master */ | ||
| 206 | ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | | ||
| 207 | DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; | ||
| 208 | writew(ic_con, dev->base + DW_IC_CON); | ||
| 209 | } | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Waiting for bus not busy | ||
| 213 | */ | ||
| 214 | static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) | ||
| 215 | { | ||
| 216 | int timeout = TIMEOUT; | ||
| 217 | |||
| 218 | while (readb(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { | ||
| 219 | if (timeout <= 0) { | ||
| 220 | dev_warn(dev->dev, "timeout waiting for bus ready\n"); | ||
| 221 | return -ETIMEDOUT; | ||
| 222 | } | ||
| 223 | timeout--; | ||
| 224 | mdelay(1); | ||
| 225 | } | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Initiate low level master read/write transaction. | ||
| 232 | * This function is called from i2c_dw_xfer when starting a transfer. | ||
| 233 | * This function is also called from dw_i2c_pump_msg to continue a transfer | ||
| 234 | * that is longer than the size of the TX FIFO. | ||
| 235 | */ | ||
| 236 | static void | ||
| 237 | i2c_dw_xfer_msg(struct i2c_adapter *adap) | ||
| 238 | { | ||
| 239 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | ||
| 240 | struct i2c_msg *msgs = dev->msgs; | ||
| 241 | int num = dev->msgs_num; | ||
| 242 | u16 ic_con, intr_mask; | ||
| 243 | int tx_limit = dev->tx_fifo_depth - readb(dev->base + DW_IC_TXFLR); | ||
| 244 | int rx_limit = dev->rx_fifo_depth - readb(dev->base + DW_IC_RXFLR); | ||
| 245 | u16 addr = msgs[dev->msg_write_idx].addr; | ||
| 246 | u16 buf_len = dev->tx_buf_len; | ||
| 247 | |||
| 248 | if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { | ||
| 249 | /* Disable the adapter */ | ||
| 250 | writeb(0, dev->base + DW_IC_ENABLE); | ||
| 251 | |||
| 252 | /* set the slave (target) address */ | ||
| 253 | writew(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR); | ||
| 254 | |||
| 255 | /* if the slave address is ten bit address, enable 10BITADDR */ | ||
| 256 | ic_con = readw(dev->base + DW_IC_CON); | ||
| 257 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) | ||
| 258 | ic_con |= DW_IC_CON_10BITADDR_MASTER; | ||
| 259 | else | ||
| 260 | ic_con &= ~DW_IC_CON_10BITADDR_MASTER; | ||
| 261 | writew(ic_con, dev->base + DW_IC_CON); | ||
| 262 | |||
| 263 | /* Enable the adapter */ | ||
| 264 | writeb(1, dev->base + DW_IC_ENABLE); | ||
| 265 | } | ||
| 266 | |||
| 267 | for (; dev->msg_write_idx < num; dev->msg_write_idx++) { | ||
| 268 | /* if target address has changed, we need to | ||
| 269 | * reprogram the target address in the i2c | ||
| 270 | * adapter when we are done with this transfer | ||
| 271 | */ | ||
| 272 | if (msgs[dev->msg_write_idx].addr != addr) | ||
| 273 | return; | ||
| 274 | |||
| 275 | if (msgs[dev->msg_write_idx].len == 0) { | ||
| 276 | dev_err(dev->dev, | ||
| 277 | "%s: invalid message length\n", __func__); | ||
| 278 | dev->msg_err = -EINVAL; | ||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { | ||
| 283 | /* new i2c_msg */ | ||
| 284 | dev->tx_buf = msgs[dev->msg_write_idx].buf; | ||
| 285 | buf_len = msgs[dev->msg_write_idx].len; | ||
| 286 | } | ||
| 287 | |||
| 288 | while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { | ||
| 289 | if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { | ||
| 290 | writew(0x100, dev->base + DW_IC_DATA_CMD); | ||
| 291 | rx_limit--; | ||
| 292 | } else | ||
| 293 | writew(*(dev->tx_buf++), | ||
| 294 | dev->base + DW_IC_DATA_CMD); | ||
| 295 | tx_limit--; buf_len--; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; | ||
| 300 | if (buf_len > 0) { /* more bytes to be written */ | ||
| 301 | intr_mask |= DW_IC_INTR_TX_EMPTY; | ||
| 302 | dev->status |= STATUS_WRITE_IN_PROGRESS; | ||
| 303 | } else | ||
| 304 | dev->status &= ~STATUS_WRITE_IN_PROGRESS; | ||
| 305 | writew(intr_mask, dev->base + DW_IC_INTR_MASK); | ||
| 306 | |||
| 307 | dev->tx_buf_len = buf_len; | ||
| 308 | } | ||
| 309 | |||
| 310 | static void | ||
| 311 | i2c_dw_read(struct i2c_adapter *adap) | ||
| 312 | { | ||
| 313 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | ||
| 314 | struct i2c_msg *msgs = dev->msgs; | ||
| 315 | int num = dev->msgs_num; | ||
| 316 | u16 addr = msgs[dev->msg_read_idx].addr; | ||
| 317 | int rx_valid = readw(dev->base + DW_IC_RXFLR); | ||
| 318 | |||
| 319 | for (; dev->msg_read_idx < num; dev->msg_read_idx++) { | ||
| 320 | u16 len; | ||
| 321 | u8 *buf; | ||
| 322 | |||
| 323 | if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) | ||
| 324 | continue; | ||
| 325 | |||
| 326 | /* different i2c client, reprogram the i2c adapter */ | ||
| 327 | if (msgs[dev->msg_read_idx].addr != addr) | ||
| 328 | return; | ||
| 329 | |||
| 330 | if (!(dev->status & STATUS_READ_IN_PROGRESS)) { | ||
| 331 | len = msgs[dev->msg_read_idx].len; | ||
| 332 | buf = msgs[dev->msg_read_idx].buf; | ||
| 333 | } else { | ||
| 334 | len = dev->rx_buf_len; | ||
| 335 | buf = dev->rx_buf; | ||
| 336 | } | ||
| 337 | |||
| 338 | for (; len > 0 && rx_valid > 0; len--, rx_valid--) | ||
| 339 | *buf++ = readb(dev->base + DW_IC_DATA_CMD); | ||
| 340 | |||
| 341 | if (len > 0) { | ||
| 342 | dev->status |= STATUS_READ_IN_PROGRESS; | ||
| 343 | dev->rx_buf_len = len; | ||
| 344 | dev->rx_buf = buf; | ||
| 345 | return; | ||
| 346 | } else | ||
| 347 | dev->status &= ~STATUS_READ_IN_PROGRESS; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | /* | ||
| 352 | * Prepare controller for a transaction and call i2c_dw_xfer_msg | ||
| 353 | */ | ||
| 354 | static int | ||
| 355 | i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | ||
| 356 | { | ||
| 357 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | ||
| 358 | int ret; | ||
| 359 | |||
| 360 | dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); | ||
| 361 | |||
| 362 | mutex_lock(&dev->lock); | ||
| 363 | |||
| 364 | INIT_COMPLETION(dev->cmd_complete); | ||
| 365 | dev->msgs = msgs; | ||
| 366 | dev->msgs_num = num; | ||
| 367 | dev->cmd_err = 0; | ||
| 368 | dev->msg_write_idx = 0; | ||
| 369 | dev->msg_read_idx = 0; | ||
| 370 | dev->msg_err = 0; | ||
| 371 | dev->status = STATUS_IDLE; | ||
| 372 | |||
| 373 | ret = i2c_dw_wait_bus_not_busy(dev); | ||
| 374 | if (ret < 0) | ||
| 375 | goto done; | ||
| 376 | |||
| 377 | /* start the transfers */ | ||
| 378 | i2c_dw_xfer_msg(adap); | ||
| 379 | |||
| 380 | /* wait for tx to complete */ | ||
| 381 | ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); | ||
| 382 | if (ret == 0) { | ||
| 383 | dev_err(dev->dev, "controller timed out\n"); | ||
| 384 | i2c_dw_init(dev); | ||
| 385 | ret = -ETIMEDOUT; | ||
| 386 | goto done; | ||
| 387 | } else if (ret < 0) | ||
| 388 | goto done; | ||
| 389 | |||
| 390 | if (dev->msg_err) { | ||
| 391 | ret = dev->msg_err; | ||
| 392 | goto done; | ||
| 393 | } | ||
| 394 | |||
| 395 | /* no error */ | ||
| 396 | if (likely(!dev->cmd_err)) { | ||
| 397 | /* read rx fifo, and disable the adapter */ | ||
| 398 | do { | ||
| 399 | i2c_dw_read(adap); | ||
| 400 | } while (dev->status & STATUS_READ_IN_PROGRESS); | ||
| 401 | writeb(0, dev->base + DW_IC_ENABLE); | ||
| 402 | ret = num; | ||
| 403 | goto done; | ||
| 404 | } | ||
| 405 | |||
| 406 | /* We have an error */ | ||
| 407 | if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { | ||
| 408 | unsigned long abort_source = dev->abort_source; | ||
| 409 | int i; | ||
| 410 | |||
| 411 | for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) { | ||
| 412 | dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | ret = -EIO; | ||
| 416 | |||
| 417 | done: | ||
| 418 | mutex_unlock(&dev->lock); | ||
| 419 | |||
| 420 | return ret; | ||
| 421 | } | ||
| 422 | |||
| 423 | static u32 i2c_dw_func(struct i2c_adapter *adap) | ||
| 424 | { | ||
| 425 | return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; | ||
| 426 | } | ||
| 427 | |||
| 428 | static void dw_i2c_pump_msg(unsigned long data) | ||
| 429 | { | ||
| 430 | struct dw_i2c_dev *dev = (struct dw_i2c_dev *) data; | ||
| 431 | u16 intr_mask; | ||
| 432 | |||
| 433 | i2c_dw_read(&dev->adapter); | ||
| 434 | i2c_dw_xfer_msg(&dev->adapter); | ||
| 435 | |||
| 436 | intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; | ||
| 437 | if (dev->status & STATUS_WRITE_IN_PROGRESS) | ||
| 438 | intr_mask |= DW_IC_INTR_TX_EMPTY; | ||
| 439 | writew(intr_mask, dev->base + DW_IC_INTR_MASK); | ||
| 440 | } | ||
| 441 | |||
| 442 | /* | ||
| 443 | * Interrupt service routine. This gets called whenever an I2C interrupt | ||
| 444 | * occurs. | ||
| 445 | */ | ||
| 446 | static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) | ||
| 447 | { | ||
| 448 | struct dw_i2c_dev *dev = dev_id; | ||
| 449 | u16 stat; | ||
| 450 | |||
| 451 | stat = readw(dev->base + DW_IC_INTR_STAT); | ||
| 452 | dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); | ||
| 453 | if (stat & DW_IC_INTR_TX_ABRT) { | ||
| 454 | dev->abort_source = readw(dev->base + DW_IC_TX_ABRT_SOURCE); | ||
| 455 | dev->cmd_err |= DW_IC_ERR_TX_ABRT; | ||
| 456 | dev->status = STATUS_IDLE; | ||
| 457 | } else if (stat & DW_IC_INTR_TX_EMPTY) | ||
| 458 | tasklet_schedule(&dev->pump_msg); | ||
| 459 | |||
| 460 | readb(dev->base + DW_IC_CLR_INTR); /* clear interrupts */ | ||
| 461 | writew(0, dev->base + DW_IC_INTR_MASK); /* disable interrupts */ | ||
| 462 | if (stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) | ||
| 463 | complete(&dev->cmd_complete); | ||
| 464 | |||
| 465 | return IRQ_HANDLED; | ||
| 466 | } | ||
| 467 | |||
| 468 | static struct i2c_algorithm i2c_dw_algo = { | ||
| 469 | .master_xfer = i2c_dw_xfer, | ||
| 470 | .functionality = i2c_dw_func, | ||
| 471 | }; | ||
| 472 | |||
| 473 | static int __devinit dw_i2c_probe(struct platform_device *pdev) | ||
| 474 | { | ||
| 475 | struct dw_i2c_dev *dev; | ||
| 476 | struct i2c_adapter *adap; | ||
| 477 | struct resource *mem, *irq, *ioarea; | ||
| 478 | int r; | ||
| 479 | |||
| 480 | /* NOTE: driver uses the static register mapping */ | ||
| 481 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 482 | if (!mem) { | ||
| 483 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
| 484 | return -EINVAL; | ||
| 485 | } | ||
| 486 | |||
| 487 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 488 | if (!irq) { | ||
| 489 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
| 490 | return -EINVAL; | ||
| 491 | } | ||
| 492 | |||
| 493 | ioarea = request_mem_region(mem->start, resource_size(mem), | ||
| 494 | pdev->name); | ||
| 495 | if (!ioarea) { | ||
| 496 | dev_err(&pdev->dev, "I2C region already claimed\n"); | ||
| 497 | return -EBUSY; | ||
| 498 | } | ||
| 499 | |||
| 500 | dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); | ||
| 501 | if (!dev) { | ||
| 502 | r = -ENOMEM; | ||
| 503 | goto err_release_region; | ||
| 504 | } | ||
| 505 | |||
| 506 | init_completion(&dev->cmd_complete); | ||
| 507 | tasklet_init(&dev->pump_msg, dw_i2c_pump_msg, (unsigned long) dev); | ||
| 508 | mutex_init(&dev->lock); | ||
| 509 | dev->dev = get_device(&pdev->dev); | ||
| 510 | dev->irq = irq->start; | ||
| 511 | platform_set_drvdata(pdev, dev); | ||
| 512 | |||
| 513 | dev->clk = clk_get(&pdev->dev, NULL); | ||
| 514 | if (IS_ERR(dev->clk)) { | ||
| 515 | r = -ENODEV; | ||
| 516 | goto err_free_mem; | ||
| 517 | } | ||
| 518 | clk_enable(dev->clk); | ||
| 519 | |||
| 520 | dev->base = ioremap(mem->start, resource_size(mem)); | ||
| 521 | if (dev->base == NULL) { | ||
| 522 | dev_err(&pdev->dev, "failure mapping io resources\n"); | ||
| 523 | r = -EBUSY; | ||
| 524 | goto err_unuse_clocks; | ||
| 525 | } | ||
| 526 | { | ||
| 527 | u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1); | ||
| 528 | |||
| 529 | dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; | ||
| 530 | dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; | ||
| 531 | } | ||
| 532 | i2c_dw_init(dev); | ||
| 533 | |||
| 534 | writew(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */ | ||
| 535 | r = request_irq(dev->irq, i2c_dw_isr, 0, pdev->name, dev); | ||
| 536 | if (r) { | ||
| 537 | dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); | ||
| 538 | goto err_iounmap; | ||
| 539 | } | ||
| 540 | |||
| 541 | adap = &dev->adapter; | ||
| 542 | i2c_set_adapdata(adap, dev); | ||
| 543 | adap->owner = THIS_MODULE; | ||
| 544 | adap->class = I2C_CLASS_HWMON; | ||
| 545 | strlcpy(adap->name, "Synopsys DesignWare I2C adapter", | ||
| 546 | sizeof(adap->name)); | ||
| 547 | adap->algo = &i2c_dw_algo; | ||
| 548 | adap->dev.parent = &pdev->dev; | ||
| 549 | |||
| 550 | adap->nr = pdev->id; | ||
| 551 | r = i2c_add_numbered_adapter(adap); | ||
| 552 | if (r) { | ||
| 553 | dev_err(&pdev->dev, "failure adding adapter\n"); | ||
| 554 | goto err_free_irq; | ||
| 555 | } | ||
| 556 | |||
| 557 | return 0; | ||
| 558 | |||
| 559 | err_free_irq: | ||
| 560 | free_irq(dev->irq, dev); | ||
| 561 | err_iounmap: | ||
| 562 | iounmap(dev->base); | ||
| 563 | err_unuse_clocks: | ||
| 564 | clk_disable(dev->clk); | ||
| 565 | clk_put(dev->clk); | ||
| 566 | dev->clk = NULL; | ||
| 567 | err_free_mem: | ||
| 568 | platform_set_drvdata(pdev, NULL); | ||
| 569 | put_device(&pdev->dev); | ||
| 570 | kfree(dev); | ||
| 571 | err_release_region: | ||
| 572 | release_mem_region(mem->start, resource_size(mem)); | ||
| 573 | |||
| 574 | return r; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int __devexit dw_i2c_remove(struct platform_device *pdev) | ||
| 578 | { | ||
| 579 | struct dw_i2c_dev *dev = platform_get_drvdata(pdev); | ||
| 580 | struct resource *mem; | ||
| 581 | |||
| 582 | platform_set_drvdata(pdev, NULL); | ||
| 583 | i2c_del_adapter(&dev->adapter); | ||
| 584 | put_device(&pdev->dev); | ||
| 585 | |||
| 586 | clk_disable(dev->clk); | ||
| 587 | clk_put(dev->clk); | ||
| 588 | dev->clk = NULL; | ||
| 589 | |||
| 590 | writeb(0, dev->base + DW_IC_ENABLE); | ||
| 591 | free_irq(dev->irq, dev); | ||
| 592 | kfree(dev); | ||
| 593 | |||
| 594 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 595 | release_mem_region(mem->start, resource_size(mem)); | ||
| 596 | return 0; | ||
| 597 | } | ||
| 598 | |||
| 599 | /* work with hotplug and coldplug */ | ||
| 600 | MODULE_ALIAS("platform:i2c_designware"); | ||
| 601 | |||
| 602 | static struct platform_driver dw_i2c_driver = { | ||
| 603 | .remove = __devexit_p(dw_i2c_remove), | ||
| 604 | .driver = { | ||
| 605 | .name = "i2c_designware", | ||
| 606 | .owner = THIS_MODULE, | ||
| 607 | }, | ||
| 608 | }; | ||
| 609 | |||
| 610 | static int __init dw_i2c_init_driver(void) | ||
| 611 | { | ||
| 612 | return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); | ||
| 613 | } | ||
| 614 | module_init(dw_i2c_init_driver); | ||
| 615 | |||
| 616 | static void __exit dw_i2c_exit_driver(void) | ||
| 617 | { | ||
| 618 | platform_driver_unregister(&dw_i2c_driver); | ||
| 619 | } | ||
| 620 | module_exit(dw_i2c_exit_driver); | ||
| 621 | |||
| 622 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
| 623 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); | ||
| 624 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index e4476743f203..b1bc6e277d2a 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
| @@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) | |||
| 85 | { | 85 | { |
| 86 | volatile struct iic_regs __iomem *iic = dev->vaddr; | 86 | volatile struct iic_regs __iomem *iic = dev->vaddr; |
| 87 | printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); | 87 | printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); |
| 88 | printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" | 88 | printk(KERN_DEBUG |
| 89 | KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" | 89 | " cntl = 0x%02x, mdcntl = 0x%02x\n" |
| 90 | KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" | 90 | " sts = 0x%02x, extsts = 0x%02x\n" |
| 91 | KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", | 91 | " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" |
| 92 | " xtcntlss = 0x%02x, directcntl = 0x%02x\n", | ||
| 92 | in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), | 93 | in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), |
| 93 | in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), | 94 | in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), |
| 94 | in_8(&iic->xtcntlss), in_8(&iic->directcntl)); | 95 | in_8(&iic->xtcntlss), in_8(&iic->directcntl)); |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index ad8d2010c921..fdd83277c8a8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -806,7 +806,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 806 | return -ENODEV; | 806 | return -ENODEV; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1, | 809 | ioarea = request_mem_region(mem->start, resource_size(mem), |
| 810 | pdev->name); | 810 | pdev->name); |
| 811 | if (!ioarea) { | 811 | if (!ioarea) { |
| 812 | dev_err(&pdev->dev, "I2C region already claimed\n"); | 812 | dev_err(&pdev->dev, "I2C region already claimed\n"); |
| @@ -905,7 +905,7 @@ err_free_mem: | |||
| 905 | platform_set_drvdata(pdev, NULL); | 905 | platform_set_drvdata(pdev, NULL); |
| 906 | kfree(dev); | 906 | kfree(dev); |
| 907 | err_release_region: | 907 | err_release_region: |
| 908 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 908 | release_mem_region(mem->start, resource_size(mem)); |
| 909 | 909 | ||
| 910 | return r; | 910 | return r; |
| 911 | } | 911 | } |
| @@ -925,7 +925,7 @@ omap_i2c_remove(struct platform_device *pdev) | |||
| 925 | iounmap(dev->base); | 925 | iounmap(dev->base); |
| 926 | kfree(dev); | 926 | kfree(dev); |
| 927 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 927 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 928 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 928 | release_mem_region(mem->start, resource_size(mem)); |
| 929 | return 0; | 929 | return 0; |
| 930 | } | 930 | } |
| 931 | 931 | ||
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 1c01083b01b5..4f3d99cd1692 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
| @@ -563,7 +563,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
| 563 | goto err_irq; | 563 | goto err_irq; |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | size = (res->end - res->start) + 1; | 566 | size = resource_size(res); |
| 567 | 567 | ||
| 568 | pd->reg = ioremap(res->start, size); | 568 | pd->reg = ioremap(res->start, size); |
| 569 | if (pd->reg == NULL) { | 569 | if (pd->reg == NULL) { |
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 042fda295f3a..6407f47bda82 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c | |||
| @@ -92,7 +92,7 @@ static int simtec_i2c_probe(struct platform_device *dev) | |||
| 92 | goto err; | 92 | goto err; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | size = (res->end-res->start)+1; | 95 | size = resource_size(res); |
| 96 | 96 | ||
| 97 | pd->ioarea = request_mem_region(res->start, size, dev->name); | 97 | pd->ioarea = request_mem_region(res->start, size, dev->name); |
| 98 | if (pd->ioarea == NULL) { | 98 | if (pd->ioarea == NULL) { |
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index bd066bb9d611..09f98ed0731f 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c | |||
| @@ -135,6 +135,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic | |||
| 135 | 135 | ||
| 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); | 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); |
| 137 | hw[0].irq = 14; | 137 | hw[0].irq = 14; |
| 138 | hw[1].irq = 15; | ||
| 138 | 139 | ||
| 139 | return ide_host_add(d, hws, 2, NULL); | 140 | return ide_host_add(d, hws, 2, NULL); |
| 140 | } | 141 | } |
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 77f79d26b264..c509c9916464 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
| @@ -92,6 +92,11 @@ int ide_acpi_init(void) | |||
| 92 | return 0; | 92 | return 0; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | bool ide_port_acpi(ide_hwif_t *hwif) | ||
| 96 | { | ||
| 97 | return ide_noacpi == 0 && hwif->acpidata; | ||
| 98 | } | ||
| 99 | |||
| 95 | /** | 100 | /** |
| 96 | * ide_get_dev_handle - finds acpi_handle and PCI device.function | 101 | * ide_get_dev_handle - finds acpi_handle and PCI device.function |
| 97 | * @dev: device to locate | 102 | * @dev: device to locate |
| @@ -352,9 +357,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive) | |||
| 352 | unsigned long gtf_address; | 357 | unsigned long gtf_address; |
| 353 | unsigned long obj_loc; | 358 | unsigned long obj_loc; |
| 354 | 359 | ||
| 355 | if (ide_noacpi) | ||
| 356 | return 0; | ||
| 357 | |||
| 358 | DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); | 360 | DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); |
| 359 | 361 | ||
| 360 | ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); | 362 | ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); |
| @@ -389,16 +391,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) | |||
| 389 | struct acpi_buffer output; | 391 | struct acpi_buffer output; |
| 390 | union acpi_object *out_obj; | 392 | union acpi_object *out_obj; |
| 391 | 393 | ||
| 392 | if (ide_noacpi) | ||
| 393 | return; | ||
| 394 | |||
| 395 | DEBPRINT("ENTER:\n"); | ||
| 396 | |||
| 397 | if (!hwif->acpidata) { | ||
| 398 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* Setting up output buffer for _GTM */ | 394 | /* Setting up output buffer for _GTM */ |
| 403 | output.length = ACPI_ALLOCATE_BUFFER; | 395 | output.length = ACPI_ALLOCATE_BUFFER; |
| 404 | output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ | 396 | output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ |
| @@ -479,16 +471,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) | |||
| 479 | struct ide_acpi_drive_link *master = &hwif->acpidata->master; | 471 | struct ide_acpi_drive_link *master = &hwif->acpidata->master; |
| 480 | struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; | 472 | struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; |
| 481 | 473 | ||
| 482 | if (ide_noacpi) | ||
| 483 | return; | ||
| 484 | |||
| 485 | DEBPRINT("ENTER:\n"); | ||
| 486 | |||
| 487 | if (!hwif->acpidata) { | ||
| 488 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
| 489 | return; | ||
| 490 | } | ||
| 491 | |||
| 492 | /* Give the GTM buffer + drive Identify data to the channel via the | 474 | /* Give the GTM buffer + drive Identify data to the channel via the |
| 493 | * _STM method: */ | 475 | * _STM method: */ |
| 494 | /* setup input parameters buffer for _STM */ | 476 | /* setup input parameters buffer for _STM */ |
| @@ -527,16 +509,11 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) | |||
| 527 | ide_drive_t *drive; | 509 | ide_drive_t *drive; |
| 528 | int i; | 510 | int i; |
| 529 | 511 | ||
| 530 | if (ide_noacpi || ide_noacpi_psx) | 512 | if (ide_noacpi_psx) |
| 531 | return; | 513 | return; |
| 532 | 514 | ||
| 533 | DEBPRINT("ENTER:\n"); | 515 | DEBPRINT("ENTER:\n"); |
| 534 | 516 | ||
| 535 | if (!hwif->acpidata) { | ||
| 536 | DEBPRINT("no ACPI data for %s\n", hwif->name); | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | |||
| 540 | /* channel first and then drives for power on and verse versa for power off */ | 517 | /* channel first and then drives for power on and verse versa for power off */ |
| 541 | if (on) | 518 | if (on) |
| 542 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); | 519 | acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); |
| @@ -616,7 +593,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) | |||
| 616 | drive->name, err); | 593 | drive->name, err); |
| 617 | } | 594 | } |
| 618 | 595 | ||
| 619 | if (!ide_acpionboot) { | 596 | if (ide_noacpi || ide_acpionboot == 0) { |
| 620 | DEBPRINT("ACPI methods disabled on boot\n"); | 597 | DEBPRINT("ACPI methods disabled on boot\n"); |
| 621 | return; | 598 | return; |
| 622 | } | 599 | } |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4a19686fcfe9..6a9a769bffc1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -592,9 +592,19 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
| 592 | } | 592 | } |
| 593 | } else if (!blk_pc_request(rq)) { | 593 | } else if (!blk_pc_request(rq)) { |
| 594 | ide_cd_request_sense_fixup(drive, cmd); | 594 | ide_cd_request_sense_fixup(drive, cmd); |
| 595 | /* complain if we still have data left to transfer */ | 595 | |
| 596 | uptodate = cmd->nleft ? 0 : 1; | 596 | uptodate = cmd->nleft ? 0 : 1; |
| 597 | if (uptodate == 0) | 597 | |
| 598 | /* | ||
| 599 | * suck out the remaining bytes from the drive in an | ||
| 600 | * attempt to complete the data xfer. (see BZ#13399) | ||
| 601 | */ | ||
| 602 | if (!(stat & ATA_ERR) && !uptodate && thislen) { | ||
| 603 | ide_pio_bytes(drive, cmd, write, thislen); | ||
| 604 | uptodate = cmd->nleft ? 0 : 1; | ||
| 605 | } | ||
| 606 | |||
| 607 | if (!uptodate) | ||
| 598 | rq->cmd_flags |= REQ_FAILED; | 608 | rq->cmd_flags |= REQ_FAILED; |
| 599 | } | 609 | } |
| 600 | goto out_end; | 610 | goto out_end; |
| @@ -876,9 +886,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 876 | return stat; | 886 | return stat; |
| 877 | 887 | ||
| 878 | /* | 888 | /* |
| 879 | * Sanity check the given block size | 889 | * Sanity check the given block size, in so far as making |
| 890 | * sure the sectors_per_frame we give to the caller won't | ||
| 891 | * end up being bogus. | ||
| 880 | */ | 892 | */ |
| 881 | blocklen = be32_to_cpu(capbuf.blocklen); | 893 | blocklen = be32_to_cpu(capbuf.blocklen); |
| 894 | blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS; | ||
| 882 | switch (blocklen) { | 895 | switch (blocklen) { |
| 883 | case 512: | 896 | case 512: |
| 884 | case 1024: | 897 | case 1024: |
| @@ -886,10 +899,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 886 | case 4096: | 899 | case 4096: |
| 887 | break; | 900 | break; |
| 888 | default: | 901 | default: |
| 889 | printk(KERN_ERR PFX "%s: weird block size %u\n", | 902 | printk_once(KERN_ERR PFX "%s: weird block size %u; " |
| 903 | "setting default block size to 2048\n", | ||
| 890 | drive->name, blocklen); | 904 | drive->name, blocklen); |
| 891 | printk(KERN_ERR PFX "%s: default to 2kb block size\n", | ||
| 892 | drive->name); | ||
| 893 | blocklen = 2048; | 905 | blocklen = 2048; |
| 894 | break; | 906 | break; |
| 895 | } | 907 | } |
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c index 5bf958e5b1d5..1099bf7cf968 100644 --- a/drivers/ide/ide-devsets.c +++ b/drivers/ide/ide-devsets.c | |||
| @@ -183,6 +183,6 @@ ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) | |||
| 183 | err = setfunc(drive, *(int *)&rq->cmd[1]); | 183 | err = setfunc(drive, *(int *)&rq->cmd[1]); |
| 184 | if (err) | 184 | if (err) |
| 185 | rq->errors = err; | 185 | rq->errors = err; |
| 186 | ide_complete_rq(drive, err, ide_rq_bytes(rq)); | 186 | ide_complete_rq(drive, err, blk_rq_bytes(rq)); |
| 187 | return ide_stopped; | 187 | return ide_stopped; |
| 188 | } | 188 | } |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 219e6fb78dc6..ee58c88dee5a 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
| @@ -361,9 +361,6 @@ static int ide_tune_dma(ide_drive_t *drive) | |||
| 361 | if (__ide_dma_bad_drive(drive)) | 361 | if (__ide_dma_bad_drive(drive)) |
| 362 | return 0; | 362 | return 0; |
| 363 | 363 | ||
| 364 | if (ide_id_dma_bug(drive)) | ||
| 365 | return 0; | ||
| 366 | |||
| 367 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) | 364 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) |
| 368 | return config_drive_for_dma(drive); | 365 | return config_drive_for_dma(drive); |
| 369 | 366 | ||
| @@ -394,24 +391,6 @@ static int ide_dma_check(ide_drive_t *drive) | |||
| 394 | return -1; | 391 | return -1; |
| 395 | } | 392 | } |
| 396 | 393 | ||
| 397 | int ide_id_dma_bug(ide_drive_t *drive) | ||
| 398 | { | ||
| 399 | u16 *id = drive->id; | ||
| 400 | |||
| 401 | if (id[ATA_ID_FIELD_VALID] & 4) { | ||
| 402 | if ((id[ATA_ID_UDMA_MODES] >> 8) && | ||
| 403 | (id[ATA_ID_MWDMA_MODES] >> 8)) | ||
| 404 | goto err_out; | ||
| 405 | } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && | ||
| 406 | (id[ATA_ID_SWDMA_MODES] >> 8)) | ||
| 407 | goto err_out; | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | err_out: | ||
| 411 | printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); | ||
| 412 | return 1; | ||
| 413 | } | ||
| 414 | |||
| 415 | int ide_set_dma(ide_drive_t *drive) | 394 | int ide_set_dma(ide_drive_t *drive) |
| 416 | { | 395 | { |
| 417 | int rc; | 396 | int rc; |
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 2b9141979613..e9abf2c3c335 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c | |||
| @@ -149,7 +149,7 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) | |||
| 149 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { | 149 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { |
| 150 | if (err <= 0 && rq->errors == 0) | 150 | if (err <= 0 && rq->errors == 0) |
| 151 | rq->errors = -EIO; | 151 | rq->errors = -EIO; |
| 152 | ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq)); | 152 | ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq)); |
| 153 | } | 153 | } |
| 154 | } | 154 | } |
| 155 | 155 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 8b3f204f7d73..fefbdfc8db06 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
| @@ -293,7 +293,7 @@ out_end: | |||
| 293 | drive->failed_pc = NULL; | 293 | drive->failed_pc = NULL; |
| 294 | if (blk_fs_request(rq) == 0 && rq->errors == 0) | 294 | if (blk_fs_request(rq) == 0 && rq->errors == 0) |
| 295 | rq->errors = -EIO; | 295 | rq->errors = -EIO; |
| 296 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | 296 | ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); |
| 297 | return ide_stopped; | 297 | return ide_stopped; |
| 298 | } | 298 | } |
| 299 | 299 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1059f809b809..db96138fefcd 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -112,16 +112,6 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
| 112 | } | 112 | } |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | /* obsolete, blk_rq_bytes() should be used instead */ | ||
| 116 | unsigned int ide_rq_bytes(struct request *rq) | ||
| 117 | { | ||
| 118 | if (blk_pc_request(rq)) | ||
| 119 | return blk_rq_bytes(rq); | ||
| 120 | else | ||
| 121 | return blk_rq_cur_sectors(rq) << 9; | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); | ||
| 124 | |||
| 125 | int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) | 115 | int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) |
| 126 | { | 116 | { |
| 127 | ide_hwif_t *hwif = drive->hwif; | 117 | ide_hwif_t *hwif = drive->hwif; |
| @@ -152,14 +142,14 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) | |||
| 152 | 142 | ||
| 153 | if ((media == ide_floppy || media == ide_tape) && drv_req) { | 143 | if ((media == ide_floppy || media == ide_tape) && drv_req) { |
| 154 | rq->errors = 0; | 144 | rq->errors = 0; |
| 155 | ide_complete_rq(drive, 0, blk_rq_bytes(rq)); | ||
| 156 | } else { | 145 | } else { |
| 157 | if (media == ide_tape) | 146 | if (media == ide_tape) |
| 158 | rq->errors = IDE_DRV_ERROR_GENERAL; | 147 | rq->errors = IDE_DRV_ERROR_GENERAL; |
| 159 | else if (blk_fs_request(rq) == 0 && rq->errors == 0) | 148 | else if (blk_fs_request(rq) == 0 && rq->errors == 0) |
| 160 | rq->errors = -EIO; | 149 | rq->errors = -EIO; |
| 161 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | ||
| 162 | } | 150 | } |
| 151 | |||
| 152 | ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); | ||
| 163 | } | 153 | } |
| 164 | 154 | ||
| 165 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | 155 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 82f252c3ee6e..e246d3d3fbcc 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
| @@ -64,7 +64,8 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, | |||
| 64 | goto out; | 64 | goto out; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | id = kmalloc(size, GFP_KERNEL); | 67 | /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */ |
| 68 | id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL); | ||
| 68 | if (id == NULL) { | 69 | if (id == NULL) { |
| 69 | rc = -ENOMEM; | 70 | rc = -ENOMEM; |
| 70 | goto out; | 71 | goto out; |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index fa047150a1c6..2892b242bbe1 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
| @@ -210,6 +210,7 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); | |||
| 210 | */ | 210 | */ |
| 211 | static const struct drive_list_entry ivb_list[] = { | 211 | static const struct drive_list_entry ivb_list[] = { |
| 212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, | 212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, |
| 213 | { "QUANTUM FIREBALLlct20 30" , "APL.0900" }, | ||
| 213 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, | 214 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, |
| 214 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, | 215 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, |
| 215 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, | 216 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, |
| @@ -329,9 +330,6 @@ int ide_driveid_update(ide_drive_t *drive) | |||
| 329 | 330 | ||
| 330 | kfree(id); | 331 | kfree(id); |
| 331 | 332 | ||
| 332 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) | ||
| 333 | ide_dma_off(drive); | ||
| 334 | |||
| 335 | return 1; | 333 | return 1; |
| 336 | out_err: | 334 | out_err: |
| 337 | if (rc == 2) | 335 | if (rc == 2) |
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index c14ca144cffe..ad7be2669dcb 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c | |||
| @@ -10,9 +10,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
| 10 | struct request_pm_state rqpm; | 10 | struct request_pm_state rqpm; |
| 11 | int ret; | 11 | int ret; |
| 12 | 12 | ||
| 13 | /* call ACPI _GTM only once */ | 13 | if (ide_port_acpi(hwif)) { |
| 14 | if ((drive->dn & 1) == 0 || pair == NULL) | 14 | /* call ACPI _GTM only once */ |
| 15 | ide_acpi_get_timing(hwif); | 15 | if ((drive->dn & 1) == 0 || pair == NULL) |
| 16 | ide_acpi_get_timing(hwif); | ||
| 17 | } | ||
| 16 | 18 | ||
| 17 | memset(&rqpm, 0, sizeof(rqpm)); | 19 | memset(&rqpm, 0, sizeof(rqpm)); |
| 18 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 20 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| @@ -26,9 +28,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
| 26 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); | 28 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); |
| 27 | blk_put_request(rq); | 29 | blk_put_request(rq); |
| 28 | 30 | ||
| 29 | /* call ACPI _PS3 only after both devices are suspended */ | 31 | if (ret == 0 && ide_port_acpi(hwif)) { |
| 30 | if (ret == 0 && ((drive->dn & 1) || pair == NULL)) | 32 | /* call ACPI _PS3 only after both devices are suspended */ |
| 31 | ide_acpi_set_state(hwif, 0); | 33 | if ((drive->dn & 1) || pair == NULL) |
| 34 | ide_acpi_set_state(hwif, 0); | ||
| 35 | } | ||
| 32 | 36 | ||
| 33 | return ret; | 37 | return ret; |
| 34 | } | 38 | } |
| @@ -42,13 +46,15 @@ int generic_ide_resume(struct device *dev) | |||
| 42 | struct request_pm_state rqpm; | 46 | struct request_pm_state rqpm; |
| 43 | int err; | 47 | int err; |
| 44 | 48 | ||
| 45 | /* call ACPI _PS0 / _STM only once */ | 49 | if (ide_port_acpi(hwif)) { |
| 46 | if ((drive->dn & 1) == 0 || pair == NULL) { | 50 | /* call ACPI _PS0 / _STM only once */ |
| 47 | ide_acpi_set_state(hwif, 1); | 51 | if ((drive->dn & 1) == 0 || pair == NULL) { |
| 48 | ide_acpi_push_timing(hwif); | 52 | ide_acpi_set_state(hwif, 1); |
| 49 | } | 53 | ide_acpi_push_timing(hwif); |
| 54 | } | ||
| 50 | 55 | ||
| 51 | ide_acpi_exec_tfs(drive); | 56 | ide_acpi_exec_tfs(drive); |
| 57 | } | ||
| 52 | 58 | ||
| 53 | memset(&rqpm, 0, sizeof(rqpm)); | 59 | memset(&rqpm, 0, sizeof(rqpm)); |
| 54 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 60 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 51af4eea0d36..1bb106f6221a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -818,6 +818,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
| 818 | return j; | 818 | return j; |
| 819 | } | 819 | } |
| 820 | 820 | ||
| 821 | static void ide_host_enable_irqs(struct ide_host *host) | ||
| 822 | { | ||
| 823 | ide_hwif_t *hwif; | ||
| 824 | int i; | ||
| 825 | |||
| 826 | ide_host_for_each_port(i, hwif, host) { | ||
| 827 | if (hwif == NULL) | ||
| 828 | continue; | ||
| 829 | |||
| 830 | /* clear any pending IRQs */ | ||
| 831 | hwif->tp_ops->read_status(hwif); | ||
| 832 | |||
| 833 | /* unmask IRQs */ | ||
| 834 | if (hwif->io_ports.ctl_addr) | ||
| 835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 821 | /* | 839 | /* |
| 822 | * This routine sets up the IRQ for an IDE interface. | 840 | * This routine sets up the IRQ for an IDE interface. |
| 823 | */ | 841 | */ |
| @@ -831,9 +849,6 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 831 | if (irq_handler == NULL) | 849 | if (irq_handler == NULL) |
| 832 | irq_handler = ide_intr; | 850 | irq_handler = ide_intr; |
| 833 | 851 | ||
| 834 | if (io_ports->ctl_addr) | ||
| 835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
| 836 | |||
| 837 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) | 852 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) |
| 838 | goto out_up; | 853 | goto out_up; |
| 839 | 854 | ||
| @@ -1404,6 +1419,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
| 1404 | ide_port_tune_devices(hwif); | 1419 | ide_port_tune_devices(hwif); |
| 1405 | } | 1420 | } |
| 1406 | 1421 | ||
| 1422 | ide_host_enable_irqs(host); | ||
| 1423 | |||
| 1407 | ide_host_for_each_port(i, hwif, host) { | 1424 | ide_host_for_each_port(i, hwif, host) { |
| 1408 | if (hwif == NULL) | 1425 | if (hwif == NULL) |
| 1409 | continue; | 1426 | continue; |
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 83b734aec923..52b25f8b111d 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
| @@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) | |||
| 880 | } | 880 | } |
| 881 | 881 | ||
| 882 | shost->hostdata[0] = (unsigned long)lu; | 882 | shost->hostdata[0] = (unsigned long)lu; |
| 883 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
| 883 | 884 | ||
| 884 | if (!scsi_add_host(shost, &ud->device)) { | 885 | if (!scsi_add_host(shost, &ud->device)) { |
| 885 | lu->shost = shost; | 886 | lu->shost = shost; |
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index c5036f1cc5b0..64a3a66a8a39 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
| @@ -25,6 +25,12 @@ | |||
| 25 | #define SBP2_DEVICE_NAME "sbp2" | 25 | #define SBP2_DEVICE_NAME "sbp2" |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * There is no transport protocol limit to the CDB length, but we implement | ||
| 29 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
| 30 | */ | ||
| 31 | #define SBP2_MAX_CDB_SIZE 16 | ||
| 32 | |||
| 33 | /* | ||
| 28 | * SBP-2 specific definitions | 34 | * SBP-2 specific definitions |
| 29 | */ | 35 | */ |
| 30 | 36 | ||
| @@ -51,7 +57,7 @@ struct sbp2_command_orb { | |||
| 51 | u32 data_descriptor_hi; | 57 | u32 data_descriptor_hi; |
| 52 | u32 data_descriptor_lo; | 58 | u32 data_descriptor_lo; |
| 53 | u32 misc; | 59 | u32 misc; |
| 54 | u8 cdb[12]; | 60 | u8 cdb[SBP2_MAX_CDB_SIZE]; |
| 55 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
| 56 | 62 | ||
| 57 | #define SBP2_LOGIN_REQUEST 0x0 | 63 | #define SBP2_LOGIN_REQUEST 0x0 |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9d8f796c6745..a6b989a9dc07 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD | |||
| 12 | 12 | ||
| 13 | if INPUT_KEYBOARD | 13 | if INPUT_KEYBOARD |
| 14 | 14 | ||
| 15 | config KEYBOARD_AAED2000 | ||
| 16 | tristate "AAED-2000 keyboard" | ||
| 17 | depends on MACH_AAED2000 | ||
| 18 | select INPUT_POLLDEV | ||
| 19 | default y | ||
| 20 | help | ||
| 21 | Say Y here to enable the keyboard on the Agilent AAED-2000 | ||
| 22 | development board. | ||
| 23 | |||
| 24 | To compile this driver as a module, choose M here: the | ||
| 25 | module will be called aaed2000_kbd. | ||
| 26 | |||
| 27 | config KEYBOARD_AMIGA | ||
| 28 | tristate "Amiga keyboard" | ||
| 29 | depends on AMIGA | ||
| 30 | help | ||
| 31 | Say Y here if you are running Linux on any AMIGA and have a keyboard | ||
| 32 | attached. | ||
| 33 | |||
| 34 | To compile this driver as a module, choose M here: the | ||
| 35 | module will be called amikbd. | ||
| 36 | |||
| 37 | config ATARI_KBD_CORE | ||
| 38 | bool | ||
| 39 | |||
| 40 | config KEYBOARD_ATARI | ||
| 41 | tristate "Atari keyboard" | ||
| 42 | depends on ATARI | ||
| 43 | select ATARI_KBD_CORE | ||
| 44 | help | ||
| 45 | Say Y here if you are running Linux on any Atari and have a keyboard | ||
| 46 | attached. | ||
| 47 | |||
| 48 | To compile this driver as a module, choose M here: the | ||
| 49 | module will be called atakbd. | ||
| 50 | |||
| 15 | config KEYBOARD_ATKBD | 51 | config KEYBOARD_ATKBD |
| 16 | tristate "AT keyboard" if EMBEDDED || !X86 | 52 | tristate "AT keyboard" if EMBEDDED || !X86 |
| 17 | default y | 53 | default y |
| @@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES | |||
| 68 | right-hand column will be interpreted as the key shown in the | 104 | right-hand column will be interpreted as the key shown in the |
| 69 | left-hand column. | 105 | left-hand column. |
| 70 | 106 | ||
| 71 | config KEYBOARD_SUNKBD | 107 | config KEYBOARD_BFIN |
| 72 | tristate "Sun Type 4 and Type 5 keyboard" | 108 | tristate "Blackfin BF54x keypad support" |
| 73 | select SERIO | 109 | depends on (BF54x && !BF544) |
| 74 | help | ||
| 75 | Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, | ||
| 76 | connected either to the Sun keyboard connector or to an serial | ||
| 77 | (RS-232) port via a simple adapter. | ||
| 78 | |||
| 79 | To compile this driver as a module, choose M here: the | ||
| 80 | module will be called sunkbd. | ||
| 81 | |||
| 82 | config KEYBOARD_LKKBD | ||
| 83 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | ||
| 84 | select SERIO | ||
| 85 | help | ||
| 86 | Say Y here if you want to use a LK201 or LK401 style serial | ||
| 87 | keyboard. This keyboard is also useable on PCs if you attach | ||
| 88 | it with the inputattach program. The connector pinout is | ||
| 89 | described within lkkbd.c. | ||
| 90 | |||
| 91 | To compile this driver as a module, choose M here: the | ||
| 92 | module will be called lkkbd. | ||
| 93 | |||
| 94 | config KEYBOARD_LOCOMO | ||
| 95 | tristate "LoCoMo Keyboard Support" | ||
| 96 | depends on SHARP_LOCOMO && INPUT_KEYBOARD | ||
| 97 | help | ||
| 98 | Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA | ||
| 99 | |||
| 100 | To compile this driver as a module, choose M here: the | ||
| 101 | module will be called locomokbd. | ||
| 102 | |||
| 103 | config KEYBOARD_XTKBD | ||
| 104 | tristate "XT keyboard" | ||
| 105 | select SERIO | ||
| 106 | help | ||
| 107 | Say Y here if you want to use the old IBM PC/XT keyboard (or | ||
| 108 | compatible) on your system. This is only possible with a | ||
| 109 | parallel port keyboard adapter, you cannot connect it to the | ||
| 110 | keyboard port on a PC that runs Linux. | ||
| 111 | |||
| 112 | To compile this driver as a module, choose M here: the | ||
| 113 | module will be called xtkbd. | ||
| 114 | |||
| 115 | config KEYBOARD_NEWTON | ||
| 116 | tristate "Newton keyboard" | ||
| 117 | select SERIO | ||
| 118 | help | ||
| 119 | Say Y here if you have a Newton keyboard on a serial port. | ||
| 120 | |||
| 121 | To compile this driver as a module, choose M here: the | ||
| 122 | module will be called newtonkbd. | ||
| 123 | |||
| 124 | config KEYBOARD_STOWAWAY | ||
| 125 | tristate "Stowaway keyboard" | ||
| 126 | select SERIO | ||
| 127 | help | 110 | help |
| 128 | Say Y here if you have a Stowaway keyboard on a serial port. | 111 | Say Y here if you want to use the BF54x keypad. |
| 129 | Stowaway compatible keyboards like Dicota Input-PDA keyboard | ||
| 130 | are also supported by this driver. | ||
| 131 | 112 | ||
| 132 | To compile this driver as a module, choose M here: the | 113 | To compile this driver as a module, choose M here: the |
| 133 | module will be called stowaway. | 114 | module will be called bf54x-keys. |
| 134 | 115 | ||
| 135 | config KEYBOARD_CORGI | 116 | config KEYBOARD_CORGI |
| 136 | tristate "Corgi keyboard" | 117 | tristate "Corgi keyboard" |
| @@ -143,61 +124,50 @@ config KEYBOARD_CORGI | |||
| 143 | To compile this driver as a module, choose M here: the | 124 | To compile this driver as a module, choose M here: the |
| 144 | module will be called corgikbd. | 125 | module will be called corgikbd. |
| 145 | 126 | ||
| 146 | config KEYBOARD_SPITZ | 127 | config KEYBOARD_LKKBD |
| 147 | tristate "Spitz keyboard" | 128 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
| 148 | depends on PXA_SHARPSL | 129 | select SERIO |
| 149 | default y | ||
| 150 | help | 130 | help |
| 151 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | 131 | Say Y here if you want to use a LK201 or LK401 style serial |
| 152 | SL-C3000 and Sl-C3100 series of PDAs. | 132 | keyboard. This keyboard is also useable on PCs if you attach |
| 133 | it with the inputattach program. The connector pinout is | ||
| 134 | described within lkkbd.c. | ||
| 153 | 135 | ||
| 154 | To compile this driver as a module, choose M here: the | 136 | To compile this driver as a module, choose M here: the |
| 155 | module will be called spitzkbd. | 137 | module will be called lkkbd. |
| 156 | 138 | ||
| 157 | config KEYBOARD_TOSA | 139 | config KEYBOARD_EP93XX |
| 158 | tristate "Tosa keyboard" | 140 | tristate "EP93xx Matrix Keypad support" |
| 159 | depends on MACH_TOSA | 141 | depends on ARCH_EP93XX |
| 160 | default y | ||
| 161 | help | 142 | help |
| 162 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | 143 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. |
| 163 | 144 | ||
| 164 | To compile this driver as a module, choose M here: the | 145 | To compile this driver as a module, choose M here: the |
| 165 | module will be called tosakbd. | 146 | module will be called ep93xx_keypad. |
| 166 | 147 | ||
| 167 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | 148 | config KEYBOARD_GPIO |
| 168 | bool "Tosa keyboard: use extended keycodes" | 149 | tristate "GPIO Buttons" |
| 169 | depends on KEYBOARD_TOSA | 150 | depends on GENERIC_GPIO |
| 170 | default n | ||
| 171 | help | 151 | help |
| 172 | Say Y here to enable the tosa keyboard driver to generate extended | 152 | This driver implements support for buttons connected |
| 173 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | 153 | to GPIO pins of various CPUs (and some other chips). |
| 174 | by either console keyboard driver or by Kdrive keybd driver. | ||
| 175 | |||
| 176 | Say Y only if you know, what you are doing! | ||
| 177 | 154 | ||
| 178 | config KEYBOARD_AMIGA | 155 | Say Y here if your device has buttons connected |
| 179 | tristate "Amiga keyboard" | 156 | directly to such GPIO pins. Your board-specific |
| 180 | depends on AMIGA | 157 | setup logic must also provide a platform device, |
| 181 | help | 158 | with configuration data saying which GPIOs are used. |
| 182 | Say Y here if you are running Linux on any AMIGA and have a keyboard | ||
| 183 | attached. | ||
| 184 | 159 | ||
| 185 | To compile this driver as a module, choose M here: the | 160 | To compile this driver as a module, choose M here: the |
| 186 | module will be called amikbd. | 161 | module will be called gpio_keys. |
| 187 | 162 | ||
| 188 | config ATARI_KBD_CORE | 163 | config KEYBOARD_MATRIX |
| 189 | bool | 164 | tristate "GPIO driven matrix keypad support" |
| 190 | 165 | depends on GENERIC_GPIO | |
| 191 | config KEYBOARD_ATARI | ||
| 192 | tristate "Atari keyboard" | ||
| 193 | depends on ATARI | ||
| 194 | select ATARI_KBD_CORE | ||
| 195 | help | 166 | help |
| 196 | Say Y here if you are running Linux on any Atari and have a keyboard | 167 | Enable support for GPIO driven matrix keypad. |
| 197 | attached. | ||
| 198 | 168 | ||
| 199 | To compile this driver as a module, choose M here: the | 169 | To compile this driver as a module, choose M here: the |
| 200 | module will be called atakbd. | 170 | module will be called matrix_keypad. |
| 201 | 171 | ||
| 202 | config KEYBOARD_HIL_OLD | 172 | config KEYBOARD_HIL_OLD |
| 203 | tristate "HP HIL keyboard support (simple driver)" | 173 | tristate "HP HIL keyboard support (simple driver)" |
| @@ -261,20 +231,39 @@ config KEYBOARD_LM8323 | |||
| 261 | To compile this driver as a module, choose M here: the | 231 | To compile this driver as a module, choose M here: the |
| 262 | module will be called lm8323. | 232 | module will be called lm8323. |
| 263 | 233 | ||
| 264 | config KEYBOARD_OMAP | 234 | config KEYBOARD_LOCOMO |
| 265 | tristate "TI OMAP keypad support" | 235 | tristate "LoCoMo Keyboard Support" |
| 266 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 236 | depends on SHARP_LOCOMO |
| 267 | help | 237 | help |
| 268 | Say Y here if you want to use the OMAP keypad. | 238 | Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA |
| 269 | 239 | ||
| 270 | To compile this driver as a module, choose M here: the | 240 | To compile this driver as a module, choose M here: the |
| 271 | module will be called omap-keypad. | 241 | module will be called locomokbd. |
| 242 | |||
| 243 | config KEYBOARD_MAPLE | ||
| 244 | tristate "Maple bus keyboard" | ||
| 245 | depends on SH_DREAMCAST && MAPLE | ||
| 246 | help | ||
| 247 | Say Y here if you have a Dreamcast console running Linux and have | ||
| 248 | a keyboard attached to its Maple bus. | ||
| 249 | |||
| 250 | To compile this driver as a module, choose M here: the | ||
| 251 | module will be called maple_keyb. | ||
| 252 | |||
| 253 | config KEYBOARD_NEWTON | ||
| 254 | tristate "Newton keyboard" | ||
| 255 | select SERIO | ||
| 256 | help | ||
| 257 | Say Y here if you have a Newton keyboard on a serial port. | ||
| 258 | |||
| 259 | To compile this driver as a module, choose M here: the | ||
| 260 | module will be called newtonkbd. | ||
| 272 | 261 | ||
| 273 | config KEYBOARD_PXA27x | 262 | config KEYBOARD_PXA27x |
| 274 | tristate "PXA27x/PXA3xx keypad support" | 263 | tristate "PXA27x/PXA3xx keypad support" |
| 275 | depends on PXA27x || PXA3xx | 264 | depends on PXA27x || PXA3xx |
| 276 | help | 265 | help |
| 277 | Enable support for PXA27x/PXA3xx keypad controller | 266 | Enable support for PXA27x/PXA3xx keypad controller. |
| 278 | 267 | ||
| 279 | To compile this driver as a module, choose M here: the | 268 | To compile this driver as a module, choose M here: the |
| 280 | module will be called pxa27x_keypad. | 269 | module will be called pxa27x_keypad. |
| @@ -288,51 +277,38 @@ config KEYBOARD_PXA930_ROTARY | |||
| 288 | To compile this driver as a module, choose M here: the | 277 | To compile this driver as a module, choose M here: the |
| 289 | module will be called pxa930_rotary. | 278 | module will be called pxa930_rotary. |
| 290 | 279 | ||
| 291 | config KEYBOARD_AAED2000 | 280 | config KEYBOARD_SPITZ |
| 292 | tristate "AAED-2000 keyboard" | 281 | tristate "Spitz keyboard" |
| 293 | depends on MACH_AAED2000 | 282 | depends on PXA_SHARPSL |
| 294 | select INPUT_POLLDEV | ||
| 295 | default y | 283 | default y |
| 296 | help | 284 | help |
| 297 | Say Y here to enable the keyboard on the Agilent AAED-2000 | 285 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, |
| 298 | development board. | 286 | SL-C3000 and Sl-C3100 series of PDAs. |
| 299 | |||
| 300 | To compile this driver as a module, choose M here: the | ||
| 301 | module will be called aaed2000_kbd. | ||
| 302 | |||
| 303 | config KEYBOARD_GPIO | ||
| 304 | tristate "GPIO Buttons" | ||
| 305 | depends on GENERIC_GPIO | ||
| 306 | help | ||
| 307 | This driver implements support for buttons connected | ||
| 308 | to GPIO pins of various CPUs (and some other chips). | ||
| 309 | |||
| 310 | Say Y here if your device has buttons connected | ||
| 311 | directly to such GPIO pins. Your board-specific | ||
| 312 | setup logic must also provide a platform device, | ||
| 313 | with configuration data saying which GPIOs are used. | ||
| 314 | 287 | ||
| 315 | To compile this driver as a module, choose M here: the | 288 | To compile this driver as a module, choose M here: the |
| 316 | module will be called gpio-keys. | 289 | module will be called spitzkbd. |
| 317 | 290 | ||
| 318 | config KEYBOARD_MAPLE | 291 | config KEYBOARD_STOWAWAY |
| 319 | tristate "Maple bus keyboard" | 292 | tristate "Stowaway keyboard" |
| 320 | depends on SH_DREAMCAST && MAPLE | 293 | select SERIO |
| 321 | help | 294 | help |
| 322 | Say Y here if you have a Dreamcast console running Linux and have | 295 | Say Y here if you have a Stowaway keyboard on a serial port. |
| 323 | a keyboard attached to its Maple bus. | 296 | Stowaway compatible keyboards like Dicota Input-PDA keyboard |
| 297 | are also supported by this driver. | ||
| 324 | 298 | ||
| 325 | To compile this driver as a module, choose M here: the | 299 | To compile this driver as a module, choose M here: the |
| 326 | module will be called maple_keyb. | 300 | module will be called stowaway. |
| 327 | 301 | ||
| 328 | config KEYBOARD_BFIN | 302 | config KEYBOARD_SUNKBD |
| 329 | tristate "Blackfin BF54x keypad support" | 303 | tristate "Sun Type 4 and Type 5 keyboard" |
| 330 | depends on (BF54x && !BF544) | 304 | select SERIO |
| 331 | help | 305 | help |
| 332 | Say Y here if you want to use the BF54x keypad. | 306 | Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, |
| 307 | connected either to the Sun keyboard connector or to an serial | ||
| 308 | (RS-232) port via a simple adapter. | ||
| 333 | 309 | ||
| 334 | To compile this driver as a module, choose M here: the | 310 | To compile this driver as a module, choose M here: the |
| 335 | module will be called bf54x-keys. | 311 | module will be called sunkbd. |
| 336 | 312 | ||
| 337 | config KEYBOARD_SH_KEYSC | 313 | config KEYBOARD_SH_KEYSC |
| 338 | tristate "SuperH KEYSC keypad support" | 314 | tristate "SuperH KEYSC keypad support" |
| @@ -344,13 +320,45 @@ config KEYBOARD_SH_KEYSC | |||
| 344 | To compile this driver as a module, choose M here: the | 320 | To compile this driver as a module, choose M here: the |
| 345 | module will be called sh_keysc. | 321 | module will be called sh_keysc. |
| 346 | 322 | ||
| 347 | config KEYBOARD_EP93XX | 323 | config KEYBOARD_OMAP |
| 348 | tristate "EP93xx Matrix Keypad support" | 324 | tristate "TI OMAP keypad support" |
| 349 | depends on ARCH_EP93XX | 325 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
| 350 | help | 326 | help |
| 351 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. | 327 | Say Y here if you want to use the OMAP keypad. |
| 352 | 328 | ||
| 353 | To compile this driver as a module, choose M here: the | 329 | To compile this driver as a module, choose M here: the |
| 354 | module will be called ep93xx_keypad. | 330 | module will be called omap-keypad. |
| 331 | |||
| 332 | config KEYBOARD_TOSA | ||
| 333 | tristate "Tosa keyboard" | ||
| 334 | depends on MACH_TOSA | ||
| 335 | default y | ||
| 336 | help | ||
| 337 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
| 338 | |||
| 339 | To compile this driver as a module, choose M here: the | ||
| 340 | module will be called tosakbd. | ||
| 341 | |||
| 342 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
| 343 | bool "Tosa keyboard: use extended keycodes" | ||
| 344 | depends on KEYBOARD_TOSA | ||
| 345 | help | ||
| 346 | Say Y here to enable the tosa keyboard driver to generate extended | ||
| 347 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
| 348 | by either console keyboard driver or by Kdrive keybd driver. | ||
| 349 | |||
| 350 | Say Y only if you know, what you are doing! | ||
| 351 | |||
| 352 | config KEYBOARD_XTKBD | ||
| 353 | tristate "XT keyboard" | ||
| 354 | select SERIO | ||
| 355 | help | ||
| 356 | Say Y here if you want to use the old IBM PC/XT keyboard (or | ||
| 357 | compatible) on your system. This is only possible with a | ||
| 358 | parallel port keyboard adapter, you cannot connect it to the | ||
| 359 | keyboard port on a PC that runs Linux. | ||
| 360 | |||
| 361 | To compile this driver as a module, choose M here: the | ||
| 362 | module will be called xtkbd. | ||
| 355 | 363 | ||
| 356 | endif | 364 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 156b647a259b..b5b5eae9724f 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -4,29 +4,30 @@ | |||
| 4 | 4 | ||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
| 8 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | ||
| 9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | ||
| 10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | ||
| 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 8 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
| 12 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 9 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
| 13 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 10 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
| 14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 11 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
| 15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | ||
| 16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 12 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
| 17 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 13 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
| 18 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 14 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
| 19 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 15 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
| 20 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 16 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
| 17 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | ||
| 18 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
| 19 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | ||
| 21 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | 20 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o |
| 21 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | ||
| 22 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
| 23 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o | ||
| 24 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | ||
| 22 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 25 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
| 23 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 26 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
| 24 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 27 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
| 25 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | ||
| 26 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | ||
| 27 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | ||
| 28 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
| 29 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
| 30 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
| 31 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 28 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
| 32 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 29 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
| 30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | ||
| 31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | ||
| 32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
| 33 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2157cd7de00c..efed0c9e242e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
| @@ -29,7 +29,8 @@ | |||
| 29 | struct gpio_button_data { | 29 | struct gpio_button_data { |
| 30 | struct gpio_keys_button *button; | 30 | struct gpio_keys_button *button; |
| 31 | struct input_dev *input; | 31 | struct input_dev *input; |
| 32 | struct delayed_work work; | 32 | struct timer_list timer; |
| 33 | struct work_struct work; | ||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | struct gpio_keys_drvdata { | 36 | struct gpio_keys_drvdata { |
| @@ -40,7 +41,7 @@ struct gpio_keys_drvdata { | |||
| 40 | static void gpio_keys_report_event(struct work_struct *work) | 41 | static void gpio_keys_report_event(struct work_struct *work) |
| 41 | { | 42 | { |
| 42 | struct gpio_button_data *bdata = | 43 | struct gpio_button_data *bdata = |
| 43 | container_of(work, struct gpio_button_data, work.work); | 44 | container_of(work, struct gpio_button_data, work); |
| 44 | struct gpio_keys_button *button = bdata->button; | 45 | struct gpio_keys_button *button = bdata->button; |
| 45 | struct input_dev *input = bdata->input; | 46 | struct input_dev *input = bdata->input; |
| 46 | unsigned int type = button->type ?: EV_KEY; | 47 | unsigned int type = button->type ?: EV_KEY; |
| @@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work) | |||
| 50 | input_sync(input); | 51 | input_sync(input); |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 54 | static void gpio_keys_timer(unsigned long _data) | ||
| 55 | { | ||
| 56 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | ||
| 57 | |||
| 58 | schedule_work(&data->work); | ||
| 59 | } | ||
| 60 | |||
| 53 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 61 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
| 54 | { | 62 | { |
| 55 | struct gpio_button_data *bdata = dev_id; | 63 | struct gpio_button_data *bdata = dev_id; |
| 56 | struct gpio_keys_button *button = bdata->button; | 64 | struct gpio_keys_button *button = bdata->button; |
| 57 | unsigned long delay; | ||
| 58 | 65 | ||
| 59 | BUG_ON(irq != gpio_to_irq(button->gpio)); | 66 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
| 60 | 67 | ||
| 61 | delay = button->debounce_interval ? | 68 | if (button->debounce_interval) |
| 62 | msecs_to_jiffies(button->debounce_interval) : 0; | 69 | mod_timer(&bdata->timer, |
| 63 | schedule_delayed_work(&bdata->work, delay); | 70 | jiffies + msecs_to_jiffies(button->debounce_interval)); |
| 71 | else | ||
| 72 | schedule_work(&bdata->work); | ||
| 64 | 73 | ||
| 65 | return IRQ_HANDLED; | 74 | return IRQ_HANDLED; |
| 66 | } | 75 | } |
| @@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 107 | 116 | ||
| 108 | bdata->input = input; | 117 | bdata->input = input; |
| 109 | bdata->button = button; | 118 | bdata->button = button; |
| 110 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); | 119 | setup_timer(&bdata->timer, |
| 120 | gpio_keys_timer, (unsigned long)bdata); | ||
| 121 | INIT_WORK(&bdata->work, gpio_keys_report_event); | ||
| 111 | 122 | ||
| 112 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); | 123 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); |
| 113 | if (error < 0) { | 124 | if (error < 0) { |
| @@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 166 | fail2: | 177 | fail2: |
| 167 | while (--i >= 0) { | 178 | while (--i >= 0) { |
| 168 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 179 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
| 169 | cancel_delayed_work_sync(&ddata->data[i].work); | 180 | if (pdata->buttons[i].debounce_interval) |
| 181 | del_timer_sync(&ddata->data[i].timer); | ||
| 182 | cancel_work_sync(&ddata->data[i].work); | ||
| 170 | gpio_free(pdata->buttons[i].gpio); | 183 | gpio_free(pdata->buttons[i].gpio); |
| 171 | } | 184 | } |
| 172 | 185 | ||
| @@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
| 190 | for (i = 0; i < pdata->nbuttons; i++) { | 203 | for (i = 0; i < pdata->nbuttons; i++) { |
| 191 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 204 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
| 192 | free_irq(irq, &ddata->data[i]); | 205 | free_irq(irq, &ddata->data[i]); |
| 193 | cancel_delayed_work_sync(&ddata->data[i].work); | 206 | if (pdata->buttons[i].debounce_interval) |
| 207 | del_timer_sync(&ddata->data[i].timer); | ||
| 208 | cancel_work_sync(&ddata->data[i].work); | ||
| 194 | gpio_free(pdata->buttons[i].gpio); | 209 | gpio_free(pdata->buttons[i].gpio); |
| 195 | } | 210 | } |
| 196 | 211 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c new file mode 100644 index 000000000000..e9b2e7cb05be --- /dev/null +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -0,0 +1,453 @@ | |||
| 1 | /* | ||
| 2 | * GPIO driven matrix keyboard driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com> | ||
| 5 | * | ||
| 6 | * Based on corgikbd.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/irq.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/jiffies.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/gpio.h> | ||
| 24 | #include <linux/input/matrix_keypad.h> | ||
| 25 | |||
| 26 | struct matrix_keypad { | ||
| 27 | const struct matrix_keypad_platform_data *pdata; | ||
| 28 | struct input_dev *input_dev; | ||
| 29 | unsigned short *keycodes; | ||
| 30 | |||
| 31 | uint32_t last_key_state[MATRIX_MAX_COLS]; | ||
| 32 | struct delayed_work work; | ||
| 33 | bool scan_pending; | ||
| 34 | bool stopped; | ||
| 35 | spinlock_t lock; | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* | ||
| 39 | * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause | ||
| 40 | * minmal side effect when scanning other columns, here it is configured to | ||
| 41 | * be input, and it should work on most platforms. | ||
| 42 | */ | ||
| 43 | static void __activate_col(const struct matrix_keypad_platform_data *pdata, | ||
| 44 | int col, bool on) | ||
| 45 | { | ||
| 46 | bool level_on = !pdata->active_low; | ||
| 47 | |||
| 48 | if (on) { | ||
| 49 | gpio_direction_output(pdata->col_gpios[col], level_on); | ||
| 50 | } else { | ||
| 51 | gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); | ||
| 52 | gpio_direction_input(pdata->col_gpios[col]); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | static void activate_col(const struct matrix_keypad_platform_data *pdata, | ||
| 57 | int col, bool on) | ||
| 58 | { | ||
| 59 | __activate_col(pdata, col, on); | ||
| 60 | |||
| 61 | if (on && pdata->col_scan_delay_us) | ||
| 62 | udelay(pdata->col_scan_delay_us); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, | ||
| 66 | bool on) | ||
| 67 | { | ||
| 68 | int col; | ||
| 69 | |||
| 70 | for (col = 0; col < pdata->num_col_gpios; col++) | ||
| 71 | __activate_col(pdata, col, on); | ||
| 72 | } | ||
| 73 | |||
| 74 | static bool row_asserted(const struct matrix_keypad_platform_data *pdata, | ||
| 75 | int row) | ||
| 76 | { | ||
| 77 | return gpio_get_value_cansleep(pdata->row_gpios[row]) ? | ||
| 78 | !pdata->active_low : pdata->active_low; | ||
| 79 | } | ||
| 80 | |||
| 81 | static void enable_row_irqs(struct matrix_keypad *keypad) | ||
| 82 | { | ||
| 83 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 84 | int i; | ||
| 85 | |||
| 86 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 87 | enable_irq(gpio_to_irq(pdata->row_gpios[i])); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void disable_row_irqs(struct matrix_keypad *keypad) | ||
| 91 | { | ||
| 92 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 93 | int i; | ||
| 94 | |||
| 95 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 96 | disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* | ||
| 100 | * This gets the keys from keyboard and reports it to input subsystem | ||
| 101 | */ | ||
| 102 | static void matrix_keypad_scan(struct work_struct *work) | ||
| 103 | { | ||
| 104 | struct matrix_keypad *keypad = | ||
| 105 | container_of(work, struct matrix_keypad, work.work); | ||
| 106 | struct input_dev *input_dev = keypad->input_dev; | ||
| 107 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 108 | uint32_t new_state[MATRIX_MAX_COLS]; | ||
| 109 | int row, col, code; | ||
| 110 | |||
| 111 | /* de-activate all columns for scanning */ | ||
| 112 | activate_all_cols(pdata, false); | ||
| 113 | |||
| 114 | memset(new_state, 0, sizeof(new_state)); | ||
| 115 | |||
| 116 | /* assert each column and read the row status out */ | ||
| 117 | for (col = 0; col < pdata->num_col_gpios; col++) { | ||
| 118 | |||
| 119 | activate_col(pdata, col, true); | ||
| 120 | |||
| 121 | for (row = 0; row < pdata->num_row_gpios; row++) | ||
| 122 | new_state[col] |= | ||
| 123 | row_asserted(pdata, row) ? (1 << row) : 0; | ||
| 124 | |||
| 125 | activate_col(pdata, col, false); | ||
| 126 | } | ||
| 127 | |||
| 128 | for (col = 0; col < pdata->num_col_gpios; col++) { | ||
| 129 | uint32_t bits_changed; | ||
| 130 | |||
| 131 | bits_changed = keypad->last_key_state[col] ^ new_state[col]; | ||
| 132 | if (bits_changed == 0) | ||
| 133 | continue; | ||
| 134 | |||
| 135 | for (row = 0; row < pdata->num_row_gpios; row++) { | ||
| 136 | if ((bits_changed & (1 << row)) == 0) | ||
| 137 | continue; | ||
| 138 | |||
| 139 | code = (row << 4) + col; | ||
| 140 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
| 141 | input_report_key(input_dev, | ||
| 142 | keypad->keycodes[code], | ||
| 143 | new_state[col] & (1 << row)); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | input_sync(input_dev); | ||
| 147 | |||
| 148 | memcpy(keypad->last_key_state, new_state, sizeof(new_state)); | ||
| 149 | |||
| 150 | activate_all_cols(pdata, true); | ||
| 151 | |||
| 152 | /* Enable IRQs again */ | ||
| 153 | spin_lock_irq(&keypad->lock); | ||
| 154 | keypad->scan_pending = false; | ||
| 155 | enable_row_irqs(keypad); | ||
| 156 | spin_unlock_irq(&keypad->lock); | ||
| 157 | } | ||
| 158 | |||
| 159 | static irqreturn_t matrix_keypad_interrupt(int irq, void *id) | ||
| 160 | { | ||
| 161 | struct matrix_keypad *keypad = id; | ||
| 162 | unsigned long flags; | ||
| 163 | |||
| 164 | spin_lock_irqsave(&keypad->lock, flags); | ||
| 165 | |||
| 166 | /* | ||
| 167 | * See if another IRQ beaten us to it and scheduled the | ||
| 168 | * scan already. In that case we should not try to | ||
| 169 | * disable IRQs again. | ||
| 170 | */ | ||
| 171 | if (unlikely(keypad->scan_pending || keypad->stopped)) | ||
| 172 | goto out; | ||
| 173 | |||
| 174 | disable_row_irqs(keypad); | ||
| 175 | keypad->scan_pending = true; | ||
| 176 | schedule_delayed_work(&keypad->work, | ||
| 177 | msecs_to_jiffies(keypad->pdata->debounce_ms)); | ||
| 178 | |||
| 179 | out: | ||
| 180 | spin_unlock_irqrestore(&keypad->lock, flags); | ||
| 181 | return IRQ_HANDLED; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int matrix_keypad_start(struct input_dev *dev) | ||
| 185 | { | ||
| 186 | struct matrix_keypad *keypad = input_get_drvdata(dev); | ||
| 187 | |||
| 188 | keypad->stopped = false; | ||
| 189 | mb(); | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Schedule an immediate key scan to capture current key state; | ||
| 193 | * columns will be activated and IRQs be enabled after the scan. | ||
| 194 | */ | ||
| 195 | schedule_delayed_work(&keypad->work, 0); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static void matrix_keypad_stop(struct input_dev *dev) | ||
| 201 | { | ||
| 202 | struct matrix_keypad *keypad = input_get_drvdata(dev); | ||
| 203 | |||
| 204 | keypad->stopped = true; | ||
| 205 | mb(); | ||
| 206 | flush_work(&keypad->work.work); | ||
| 207 | /* | ||
| 208 | * matrix_keypad_scan() will leave IRQs enabled; | ||
| 209 | * we should disable them now. | ||
| 210 | */ | ||
| 211 | disable_row_irqs(keypad); | ||
| 212 | } | ||
| 213 | |||
| 214 | #ifdef CONFIG_PM | ||
| 215 | static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 216 | { | ||
| 217 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
| 218 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 219 | int i; | ||
| 220 | |||
| 221 | matrix_keypad_stop(keypad->input_dev); | ||
| 222 | |||
| 223 | if (device_may_wakeup(&pdev->dev)) | ||
| 224 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 225 | enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int matrix_keypad_resume(struct platform_device *pdev) | ||
| 231 | { | ||
| 232 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
| 233 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 234 | int i; | ||
| 235 | |||
| 236 | if (device_may_wakeup(&pdev->dev)) | ||
| 237 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 238 | disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | ||
| 239 | |||
| 240 | matrix_keypad_start(keypad->input_dev); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | #else | ||
| 245 | #define matrix_keypad_suspend NULL | ||
| 246 | #define matrix_keypad_resume NULL | ||
| 247 | #endif | ||
| 248 | |||
| 249 | static int __devinit init_matrix_gpio(struct platform_device *pdev, | ||
| 250 | struct matrix_keypad *keypad) | ||
| 251 | { | ||
| 252 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 253 | int i, err = -EINVAL; | ||
| 254 | |||
| 255 | /* initialized strobe lines as outputs, activated */ | ||
| 256 | for (i = 0; i < pdata->num_col_gpios; i++) { | ||
| 257 | err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col"); | ||
| 258 | if (err) { | ||
| 259 | dev_err(&pdev->dev, | ||
| 260 | "failed to request GPIO%d for COL%d\n", | ||
| 261 | pdata->col_gpios[i], i); | ||
| 262 | goto err_free_cols; | ||
| 263 | } | ||
| 264 | |||
| 265 | gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); | ||
| 266 | } | ||
| 267 | |||
| 268 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
| 269 | err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row"); | ||
| 270 | if (err) { | ||
| 271 | dev_err(&pdev->dev, | ||
| 272 | "failed to request GPIO%d for ROW%d\n", | ||
| 273 | pdata->row_gpios[i], i); | ||
| 274 | goto err_free_rows; | ||
| 275 | } | ||
| 276 | |||
| 277 | gpio_direction_input(pdata->row_gpios[i]); | ||
| 278 | } | ||
| 279 | |||
| 280 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
| 281 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | ||
| 282 | matrix_keypad_interrupt, | ||
| 283 | IRQF_DISABLED | | ||
| 284 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 285 | "matrix-keypad", keypad); | ||
| 286 | if (err) { | ||
| 287 | dev_err(&pdev->dev, | ||
| 288 | "Unable to acquire interrupt for GPIO line %i\n", | ||
| 289 | pdata->row_gpios[i]); | ||
| 290 | goto err_free_irqs; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | /* initialized as disabled - enabled by input->open */ | ||
| 295 | disable_row_irqs(keypad); | ||
| 296 | return 0; | ||
| 297 | |||
| 298 | err_free_irqs: | ||
| 299 | while (--i >= 0) | ||
| 300 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 301 | i = pdata->num_row_gpios; | ||
| 302 | err_free_rows: | ||
| 303 | while (--i >= 0) | ||
| 304 | gpio_free(pdata->row_gpios[i]); | ||
| 305 | i = pdata->num_col_gpios; | ||
| 306 | err_free_cols: | ||
| 307 | while (--i >= 0) | ||
| 308 | gpio_free(pdata->col_gpios[i]); | ||
| 309 | |||
| 310 | return err; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) | ||
| 314 | { | ||
| 315 | const struct matrix_keypad_platform_data *pdata; | ||
| 316 | const struct matrix_keymap_data *keymap_data; | ||
| 317 | struct matrix_keypad *keypad; | ||
| 318 | struct input_dev *input_dev; | ||
| 319 | unsigned short *keycodes; | ||
| 320 | int i; | ||
| 321 | int err; | ||
| 322 | |||
| 323 | pdata = pdev->dev.platform_data; | ||
| 324 | if (!pdata) { | ||
| 325 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
| 326 | return -EINVAL; | ||
| 327 | } | ||
| 328 | |||
| 329 | keymap_data = pdata->keymap_data; | ||
| 330 | if (!keymap_data) { | ||
| 331 | dev_err(&pdev->dev, "no keymap data defined\n"); | ||
| 332 | return -EINVAL; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (!keymap_data->max_keymap_size) { | ||
| 336 | dev_err(&pdev->dev, "invalid keymap data supplied\n"); | ||
| 337 | return -EINVAL; | ||
| 338 | } | ||
| 339 | |||
| 340 | keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); | ||
| 341 | keycodes = kzalloc(keymap_data->max_keymap_size * | ||
| 342 | sizeof(keypad->keycodes), | ||
| 343 | GFP_KERNEL); | ||
| 344 | input_dev = input_allocate_device(); | ||
| 345 | if (!keypad || !keycodes || !input_dev) { | ||
| 346 | err = -ENOMEM; | ||
| 347 | goto err_free_mem; | ||
| 348 | } | ||
| 349 | |||
| 350 | keypad->input_dev = input_dev; | ||
| 351 | keypad->pdata = pdata; | ||
| 352 | keypad->keycodes = keycodes; | ||
| 353 | keypad->stopped = true; | ||
| 354 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); | ||
| 355 | spin_lock_init(&keypad->lock); | ||
| 356 | |||
| 357 | input_dev->name = pdev->name; | ||
| 358 | input_dev->id.bustype = BUS_HOST; | ||
| 359 | input_dev->dev.parent = &pdev->dev; | ||
| 360 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 361 | input_dev->open = matrix_keypad_start; | ||
| 362 | input_dev->close = matrix_keypad_stop; | ||
| 363 | |||
| 364 | input_dev->keycode = keycodes; | ||
| 365 | input_dev->keycodesize = sizeof(*keycodes); | ||
| 366 | input_dev->keycodemax = keymap_data->max_keymap_size; | ||
| 367 | |||
| 368 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
| 369 | unsigned int key = keymap_data->keymap[i]; | ||
| 370 | unsigned int row = KEY_ROW(key); | ||
| 371 | unsigned int col = KEY_COL(key); | ||
| 372 | unsigned short code = KEY_VAL(key); | ||
| 373 | |||
| 374 | keycodes[(row << 4) + col] = code; | ||
| 375 | __set_bit(code, input_dev->keybit); | ||
| 376 | } | ||
| 377 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 378 | |||
| 379 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 380 | input_set_drvdata(input_dev, keypad); | ||
| 381 | |||
| 382 | err = init_matrix_gpio(pdev, keypad); | ||
| 383 | if (err) | ||
| 384 | goto err_free_mem; | ||
| 385 | |||
| 386 | err = input_register_device(keypad->input_dev); | ||
| 387 | if (err) | ||
| 388 | goto err_free_mem; | ||
| 389 | |||
| 390 | device_init_wakeup(&pdev->dev, pdata->wakeup); | ||
| 391 | platform_set_drvdata(pdev, keypad); | ||
| 392 | |||
| 393 | return 0; | ||
| 394 | |||
| 395 | err_free_mem: | ||
| 396 | input_free_device(input_dev); | ||
| 397 | kfree(keycodes); | ||
| 398 | kfree(keypad); | ||
| 399 | return err; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) | ||
| 403 | { | ||
| 404 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
| 405 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 406 | int i; | ||
| 407 | |||
| 408 | device_init_wakeup(&pdev->dev, 0); | ||
| 409 | |||
| 410 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
| 411 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 412 | gpio_free(pdata->row_gpios[i]); | ||
| 413 | } | ||
| 414 | |||
| 415 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
| 416 | gpio_free(pdata->col_gpios[i]); | ||
| 417 | |||
| 418 | input_unregister_device(keypad->input_dev); | ||
| 419 | platform_set_drvdata(pdev, NULL); | ||
| 420 | kfree(keypad->keycodes); | ||
| 421 | kfree(keypad); | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static struct platform_driver matrix_keypad_driver = { | ||
| 427 | .probe = matrix_keypad_probe, | ||
| 428 | .remove = __devexit_p(matrix_keypad_remove), | ||
| 429 | .suspend = matrix_keypad_suspend, | ||
| 430 | .resume = matrix_keypad_resume, | ||
| 431 | .driver = { | ||
| 432 | .name = "matrix-keypad", | ||
| 433 | .owner = THIS_MODULE, | ||
| 434 | }, | ||
| 435 | }; | ||
| 436 | |||
| 437 | static int __init matrix_keypad_init(void) | ||
| 438 | { | ||
| 439 | return platform_driver_register(&matrix_keypad_driver); | ||
| 440 | } | ||
| 441 | |||
| 442 | static void __exit matrix_keypad_exit(void) | ||
| 443 | { | ||
| 444 | platform_driver_unregister(&matrix_keypad_driver); | ||
| 445 | } | ||
| 446 | |||
| 447 | module_init(matrix_keypad_init); | ||
| 448 | module_exit(matrix_keypad_exit); | ||
| 449 | |||
| 450 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
| 451 | MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver"); | ||
| 452 | MODULE_LICENSE("GPL v2"); | ||
| 453 | MODULE_ALIAS("platform:matrix-keypad"); | ||
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265da..d114d3a9e1e9 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Cobalt button interface driver. | 2 | * Cobalt button interface driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) | |||
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 151 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
| 152 | MODULE_DESCRIPTION("Cobalt button interface driver"); | 152 | MODULE_DESCRIPTION("Cobalt button interface driver"); |
| 153 | MODULE_LICENSE("GPL"); | 153 | MODULE_LICENSE("GPL"); |
| 154 | /* work with hotplug and coldplug */ | 154 | /* work with hotplug and coldplug */ |
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 5e5eb88d8d1e..7b6ce178f1b6 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c | |||
| @@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) | |||
| 46 | input_sync(input); | 46 | input_sync(input); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static int __init gpio_mouse_probe(struct platform_device *pdev) | 49 | static int __devinit gpio_mouse_probe(struct platform_device *pdev) |
| 50 | { | 50 | { |
| 51 | struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; | 51 | struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; |
| 52 | struct input_polled_dev *input_poll; | 52 | struct input_polled_dev *input_poll; |
| @@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) | |||
| 170 | return 0; | 170 | return 0; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /* work with hotplug and coldplug */ | ||
| 174 | MODULE_ALIAS("platform:gpio_mouse"); | ||
| 175 | |||
| 176 | static struct platform_driver gpio_mouse_device_driver = { | 173 | static struct platform_driver gpio_mouse_device_driver = { |
| 174 | .probe = gpio_mouse_probe, | ||
| 177 | .remove = __devexit_p(gpio_mouse_remove), | 175 | .remove = __devexit_p(gpio_mouse_remove), |
| 178 | .driver = { | 176 | .driver = { |
| 179 | .name = "gpio_mouse", | 177 | .name = "gpio_mouse", |
| @@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = { | |||
| 183 | 181 | ||
| 184 | static int __init gpio_mouse_init(void) | 182 | static int __init gpio_mouse_init(void) |
| 185 | { | 183 | { |
| 186 | return platform_driver_probe(&gpio_mouse_device_driver, | 184 | return platform_driver_register(&gpio_mouse_device_driver); |
| 187 | gpio_mouse_probe); | ||
| 188 | } | 185 | } |
| 189 | module_init(gpio_mouse_init); | 186 | module_init(gpio_mouse_init); |
| 190 | 187 | ||
| @@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit); | |||
| 197 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); | 194 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); |
| 198 | MODULE_DESCRIPTION("GPIO mouse driver"); | 195 | MODULE_DESCRIPTION("GPIO mouse driver"); |
| 199 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
| 197 | MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ | ||
| 198 | |||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index fb8a3cd3ffd0..924e8ed7f2cf 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
| @@ -392,6 +392,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | |||
| 392 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), | 392 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), |
| 393 | }, | 393 | }, |
| 394 | }, | 394 | }, |
| 395 | { | ||
| 396 | .ident = "Acer Aspire One 150", | ||
| 397 | .matches = { | ||
| 398 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
| 399 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), | ||
| 400 | }, | ||
| 401 | }, | ||
| 402 | { | ||
| 403 | .ident = "Advent 4211", | ||
| 404 | .matches = { | ||
| 405 | DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), | ||
| 406 | DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), | ||
| 407 | }, | ||
| 408 | }, | ||
| 409 | { | ||
| 410 | .ident = "Medion Akoya Mini E1210", | ||
| 411 | .matches = { | ||
| 412 | DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), | ||
| 413 | DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), | ||
| 414 | }, | ||
| 415 | }, | ||
| 416 | { | ||
| 417 | .ident = "Mivvy M310", | ||
| 418 | .matches = { | ||
| 419 | DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), | ||
| 420 | DMI_MATCH(DMI_PRODUCT_NAME, "N10"), | ||
| 421 | }, | ||
| 422 | }, | ||
| 395 | { } | 423 | { } |
| 396 | }; | 424 | }; |
| 397 | 425 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f919bf57293c..582245c497eb 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -934,10 +934,11 @@ static bool i8042_suspended; | |||
| 934 | 934 | ||
| 935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) |
| 936 | { | 936 | { |
| 937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { | 937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) |
| 938 | i8042_controller_reset(); | 938 | i8042_controller_reset(); |
| 939 | i8042_suspended = true; | 939 | |
| 940 | } | 940 | i8042_suspended = state.event == PM_EVENT_SUSPEND || |
| 941 | state.event == PM_EVENT_FREEZE; | ||
| 941 | 942 | ||
| 942 | return 0; | 943 | return 0; |
| 943 | } | 944 | } |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index fb17573f8f2d..d66f4944f2a0 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state) | |||
| 935 | { | 935 | { |
| 936 | struct serio *serio = to_serio_port(dev); | 936 | struct serio *serio = to_serio_port(dev); |
| 937 | 937 | ||
| 938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { | 938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) |
| 939 | serio_cleanup(serio); | 939 | serio_cleanup(serio); |
| 940 | serio->suspended = true; | 940 | |
| 941 | } | 941 | serio->suspended = state.event == PM_EVENT_SUSPEND || |
| 942 | state.event == PM_EVENT_FREEZE; | ||
| 942 | 943 | ||
| 943 | return 0; | 944 | return 0; |
| 944 | } | 945 | } |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 38bf86384aeb..c896d6a21b7e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
| 384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
| 385 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 385 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
| 386 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 386 | wacom_report_abs(wcombo, ABS_WHEEL, 0); |
| 387 | if (wacom->features->type >= INTUOS3S) | ||
| 388 | wacom_report_abs(wcombo, ABS_Z, 0); | ||
| 387 | } | 389 | } |
| 388 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 390 | wacom_report_key(wcombo, wacom->tool[idx], 0); |
| 389 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 391 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ |
| @@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = { | |||
| 836 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, | 838 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, |
| 837 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | 839 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, |
| 838 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | 840 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, |
| 841 | { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, | ||
| 839 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | 842 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, |
| 840 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 843 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, |
| 841 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 844 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
| @@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = { | |||
| 897 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | 900 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, |
| 898 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | 901 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, |
| 899 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | 902 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, |
| 900 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
| 901 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | 903 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, |
| 904 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
| 905 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, | ||
| 902 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | 906 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, |
| 903 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | 907 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, |
| 904 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | 908 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, |
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index ec5169604a6a..2d91049571a4 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
| @@ -294,32 +294,33 @@ struct reply_t gigaset_tab_cid[] = | |||
| 294 | {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, | 294 | {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, |
| 295 | {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 295 | {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, |
| 296 | {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 296 | {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, |
| 297 | {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ | 297 | {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, |
| 298 | {RSP_OK, 607,607, -1, 608,-1}, | 298 | {RSP_OK, 607,607, -1, 608,-1}, |
| 299 | //{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE | ||
| 300 | {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, | 299 | {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, |
| 301 | {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, | 300 | {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, |
| 302 | 301 | ||
| 303 | {RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}}, | ||
| 304 | {RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}}, | ||
| 305 | {RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}}, | ||
| 306 | {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 302 | {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, |
| 307 | {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 303 | {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, |
| 308 | 304 | ||
| 309 | /* dialing */ | 305 | /* optional dialing responses */ |
| 310 | {RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}}, | 306 | {EV_BC_OPEN, 650,650, -1, 651,-1}, |
| 311 | {RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}}, | 307 | {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, |
| 312 | {RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */ | 308 | {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, |
| 313 | 309 | {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, | |
| 314 | /* connection established */ | 310 | {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, |
| 315 | {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 | 311 | |
| 316 | {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 | 312 | /* connect */ |
| 317 | 313 | {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | |
| 318 | {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout | 314 | {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, |
| 315 | ACT_NOTIFY_BC_UP}}, | ||
| 316 | {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | ||
| 317 | {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, | ||
| 318 | ACT_NOTIFY_BC_UP}}, | ||
| 319 | {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, | ||
| 319 | 320 | ||
| 320 | /* remote hangup */ | 321 | /* remote hangup */ |
| 321 | {RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, | 322 | {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, |
| 322 | {RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 323 | {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, |
| 323 | {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 324 | {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, |
| 324 | 325 | ||
| 325 | /* hangup */ | 326 | /* hangup */ |
| @@ -358,7 +359,8 @@ struct reply_t gigaset_tab_cid[] = | |||
| 358 | {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, | 359 | {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, |
| 359 | {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, | 360 | {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, |
| 360 | 361 | ||
| 361 | {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, | 362 | {EV_BC_OPEN, 750,750, -1, 751,-1}, |
| 363 | {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, | ||
| 362 | 364 | ||
| 363 | /* B channel closed (general case) */ | 365 | /* B channel closed (general case) */ |
| 364 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | 366 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME |
| @@ -876,12 +878,6 @@ static void bchannel_down(struct bc_state *bcs) | |||
| 876 | 878 | ||
| 877 | static void bchannel_up(struct bc_state *bcs) | 879 | static void bchannel_up(struct bc_state *bcs) |
| 878 | { | 880 | { |
| 879 | if (!(bcs->chstate & CHS_D_UP)) { | ||
| 880 | dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__); | ||
| 881 | bcs->chstate |= CHS_D_UP; | ||
| 882 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | ||
| 883 | } | ||
| 884 | |||
| 885 | if (bcs->chstate & CHS_B_UP) { | 881 | if (bcs->chstate & CHS_B_UP) { |
| 886 | dev_notice(bcs->cs->dev, "%s: B channel already up\n", | 882 | dev_notice(bcs->cs->dev, "%s: B channel already up\n", |
| 887 | __func__); | 883 | __func__); |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index db3a1e4cd489..bed38fcc432b 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
| @@ -174,12 +174,6 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
| 174 | pr_err("invalid size %d\n", size); | 174 | pr_err("invalid size %d\n", size); |
| 175 | return -EINVAL; | 175 | return -EINVAL; |
| 176 | } | 176 | } |
| 177 | src = iwb->read; | ||
| 178 | if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD || | ||
| 179 | (read < src && limit >= src))) { | ||
| 180 | pr_err("isoc write buffer frame reservation violated\n"); | ||
| 181 | return -EFAULT; | ||
| 182 | } | ||
| 183 | #endif | 177 | #endif |
| 184 | 178 | ||
| 185 | if (read < write) { | 179 | if (read < write) { |
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index 8df889b0c1a9..9de54202c90c 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
| 38 | #include <linux/usb.h> | 38 | #include <linux/usb.h> |
| 39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
| 40 | #include <linux/smp_lock.h> | ||
| 41 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
| 42 | #include <linux/moduleparam.h> | 41 | #include <linux/moduleparam.h> |
| 43 | #include "hisax.h" | 42 | #include "hisax.h" |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index b4d4522e5071..2881a66c1aa9 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/isdn.h> | 14 | #include <linux/isdn.h> |
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 16 | #include "isdn_common.h" | 17 | #include "isdn_common.h" |
| 17 | #include "isdn_tty.h" | 18 | #include "isdn_tty.h" |
| 18 | #ifdef CONFIG_ISDN_AUDIO | 19 | #ifdef CONFIG_ISDN_AUDIO |
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index e2f45019ebf0..3e1532a180ff 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/mISDNif.h> | 18 | #include <linux/mISDNif.h> |
| 19 | #include <linux/kthread.h> | 19 | #include <linux/kthread.h> |
| 20 | #include <linux/smp_lock.h> | ||
| 20 | #include "core.h" | 21 | #include "core.h" |
| 21 | 22 | ||
| 22 | static u_int *debug; | 23 | static u_int *debug; |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9b60b6b684d9..7c8e7122aaa9 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -75,6 +75,7 @@ config LEDS_ALIX2 | |||
| 75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL | 75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL |
| 76 | help | 76 | help |
| 77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. | 77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. |
| 78 | You have to set leds-alix2.force=1 for boards with Award BIOS. | ||
| 78 | 79 | ||
| 79 | config LEDS_H1940 | 80 | config LEDS_H1940 |
| 80 | tristate "LED Support for iPAQ H1940 device" | 81 | tristate "LED Support for iPAQ H1940 device" |
| @@ -145,15 +146,16 @@ config LEDS_GPIO_OF | |||
| 145 | of_platform devices. For instance, LEDs which are listed in a "dts" | 146 | of_platform devices. For instance, LEDs which are listed in a "dts" |
| 146 | file. | 147 | file. |
| 147 | 148 | ||
| 148 | config LEDS_LP5521 | 149 | config LEDS_LP3944 |
| 149 | tristate "LED Support for the LP5521 LEDs" | 150 | tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" |
| 150 | depends on LEDS_CLASS && I2C | 151 | depends on LEDS_CLASS && I2C |
| 151 | help | 152 | help |
| 152 | If you say 'Y' here you get support for the National Semiconductor | 153 | This option enables support for LEDs connected to the National |
| 153 | LP5521 LED driver used in n8x0 boards. | 154 | Semiconductor LP3944 Lighting Management Unit (LMU) also known as |
| 155 | Fun Light Chip. | ||
| 154 | 156 | ||
| 155 | This driver can be built as a module by choosing 'M'. The module | 157 | To compile this driver as a module, choose M here: the |
| 156 | will be called leds-lp5521. | 158 | module will be called leds-lp3944. |
| 157 | 159 | ||
| 158 | config LEDS_CLEVO_MAIL | 160 | config LEDS_CLEVO_MAIL |
| 159 | tristate "Mail LED on Clevo notebook" | 161 | tristate "Mail LED on Clevo notebook" |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 2d41c4dcf92f..e8cdcf77a4c3 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
| @@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | |||
| 20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o | 20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o |
| 21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o | 21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o |
| 22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
| 23 | obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o | ||
| 23 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 24 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
| 24 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | 25 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o |
| 25 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 26 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c index ddbd7730dfc8..731d4eef3425 100644 --- a/drivers/leds/leds-alix2.c +++ b/drivers/leds/leds-alix2.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | static int force = 0; | 15 | static int force = 0; |
| 16 | module_param(force, bool, 0444); | 16 | module_param(force, bool, 0444); |
| 17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs"); | 17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs"); |
| 18 | 18 | ||
| 19 | struct alix_led { | 19 | struct alix_led { |
| 20 | struct led_classdev cdev; | 20 | struct led_classdev cdev; |
| @@ -155,6 +155,11 @@ static int __init alix_led_init(void) | |||
| 155 | goto out; | 155 | goto out; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | /* enable output on GPIO for LED 1,2,3 */ | ||
| 159 | outl(1 << 6, 0x6104); | ||
| 160 | outl(1 << 9, 0x6184); | ||
| 161 | outl(1 << 11, 0x6184); | ||
| 162 | |||
| 158 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); | 163 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); |
| 159 | if (!IS_ERR(pdev)) { | 164 | if (!IS_ERR(pdev)) { |
| 160 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); | 165 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 4149ecb3a9b2..779d7f262c04 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
| @@ -97,6 +97,10 @@ struct bd2802_led { | |||
| 97 | enum led_ids led_id; | 97 | enum led_ids led_id; |
| 98 | enum led_colors color; | 98 | enum led_colors color; |
| 99 | enum led_bits state; | 99 | enum led_bits state; |
| 100 | |||
| 101 | /* General attributes of RGB LEDs */ | ||
| 102 | int wave_pattern; | ||
| 103 | int rgb_current; | ||
| 100 | }; | 104 | }; |
| 101 | 105 | ||
| 102 | 106 | ||
| @@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id, | |||
| 254 | bd2802_reset_cancel(led); | 258 | bd2802_reset_cancel(led); |
| 255 | 259 | ||
| 256 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
| 257 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 261 | bd2802_write_byte(led->client, reg, led->rgb_current); |
| 258 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 262 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
| 259 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 263 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
| 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 264 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
| @@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id, | |||
| 275 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
| 276 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 280 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
| 277 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 281 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
| 278 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 282 | bd2802_write_byte(led->client, reg, led->rgb_current); |
| 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 283 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
| 280 | bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF); | 284 | bd2802_write_byte(led->client, reg, led->wave_pattern); |
| 281 | 285 | ||
| 282 | bd2802_enable(led, id); | 286 | bd2802_enable(led, id); |
| 283 | bd2802_update_state(led, id, color, BD2802_BLINK); | 287 | bd2802_update_state(led, id, color, BD2802_BLINK); |
| @@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led) | |||
| 406 | ret = device_create_file(&led->client->dev, | 410 | ret = device_create_file(&led->client->dev, |
| 407 | bd2802_addr_attributes[i]); | 411 | bd2802_addr_attributes[i]); |
| 408 | if (ret) { | 412 | if (ret) { |
| 409 | dev_err(&led->client->dev, "failed to sysfs file %s\n", | 413 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
| 410 | bd2802_addr_attributes[i]->attr.name); | 414 | bd2802_addr_attributes[i]->attr.name); |
| 411 | goto failed_remove_files; | 415 | goto failed_remove_files; |
| 412 | } | 416 | } |
| @@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = { | |||
| 483 | .store = bd2802_store_adv_conf, | 487 | .store = bd2802_store_adv_conf, |
| 484 | }; | 488 | }; |
| 485 | 489 | ||
| 490 | #define BD2802_CONTROL_ATTR(attr_name, name_str) \ | ||
| 491 | static ssize_t bd2802_show_##attr_name(struct device *dev, \ | ||
| 492 | struct device_attribute *attr, char *buf) \ | ||
| 493 | { \ | ||
| 494 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
| 495 | ssize_t ret; \ | ||
| 496 | down_read(&led->rwsem); \ | ||
| 497 | ret = sprintf(buf, "0x%02x\n", led->attr_name); \ | ||
| 498 | up_read(&led->rwsem); \ | ||
| 499 | return ret; \ | ||
| 500 | } \ | ||
| 501 | static ssize_t bd2802_store_##attr_name(struct device *dev, \ | ||
| 502 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 503 | { \ | ||
| 504 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
| 505 | unsigned long val; \ | ||
| 506 | int ret; \ | ||
| 507 | if (!count) \ | ||
| 508 | return -EINVAL; \ | ||
| 509 | ret = strict_strtoul(buf, 16, &val); \ | ||
| 510 | if (ret) \ | ||
| 511 | return ret; \ | ||
| 512 | down_write(&led->rwsem); \ | ||
| 513 | led->attr_name = val; \ | ||
| 514 | up_write(&led->rwsem); \ | ||
| 515 | return count; \ | ||
| 516 | } \ | ||
| 517 | static struct device_attribute bd2802_##attr_name##_attr = { \ | ||
| 518 | .attr = { \ | ||
| 519 | .name = name_str, \ | ||
| 520 | .mode = 0644, \ | ||
| 521 | .owner = THIS_MODULE \ | ||
| 522 | }, \ | ||
| 523 | .show = bd2802_show_##attr_name, \ | ||
| 524 | .store = bd2802_store_##attr_name, \ | ||
| 525 | }; | ||
| 526 | |||
| 527 | BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern"); | ||
| 528 | BD2802_CONTROL_ATTR(rgb_current, "rgb_current"); | ||
| 529 | |||
| 530 | static struct device_attribute *bd2802_attributes[] = { | ||
| 531 | &bd2802_adv_conf_attr, | ||
| 532 | &bd2802_wave_pattern_attr, | ||
| 533 | &bd2802_rgb_current_attr, | ||
| 534 | }; | ||
| 535 | |||
| 486 | static void bd2802_led_work(struct work_struct *work) | 536 | static void bd2802_led_work(struct work_struct *work) |
| 487 | { | 537 | { |
| 488 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); | 538 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); |
| @@ -538,7 +588,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 538 | led->cdev_led1r.brightness = LED_OFF; | 588 | led->cdev_led1r.brightness = LED_OFF; |
| 539 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; | 589 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; |
| 540 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; | 590 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; |
| 541 | led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME; | ||
| 542 | 591 | ||
| 543 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); | 592 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); |
| 544 | if (ret < 0) { | 593 | if (ret < 0) { |
| @@ -551,7 +600,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 551 | led->cdev_led1g.brightness = LED_OFF; | 600 | led->cdev_led1g.brightness = LED_OFF; |
| 552 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; | 601 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; |
| 553 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; | 602 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; |
| 554 | led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME; | ||
| 555 | 603 | ||
| 556 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); | 604 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); |
| 557 | if (ret < 0) { | 605 | if (ret < 0) { |
| @@ -564,7 +612,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 564 | led->cdev_led1b.brightness = LED_OFF; | 612 | led->cdev_led1b.brightness = LED_OFF; |
| 565 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; | 613 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; |
| 566 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; | 614 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; |
| 567 | led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME; | ||
| 568 | 615 | ||
| 569 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); | 616 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); |
| 570 | if (ret < 0) { | 617 | if (ret < 0) { |
| @@ -577,7 +624,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 577 | led->cdev_led2r.brightness = LED_OFF; | 624 | led->cdev_led2r.brightness = LED_OFF; |
| 578 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; | 625 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; |
| 579 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; | 626 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; |
| 580 | led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME; | ||
| 581 | 627 | ||
| 582 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); | 628 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); |
| 583 | if (ret < 0) { | 629 | if (ret < 0) { |
| @@ -590,7 +636,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 590 | led->cdev_led2g.brightness = LED_OFF; | 636 | led->cdev_led2g.brightness = LED_OFF; |
| 591 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; | 637 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; |
| 592 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; | 638 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; |
| 593 | led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME; | ||
| 594 | 639 | ||
| 595 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); | 640 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); |
| 596 | if (ret < 0) { | 641 | if (ret < 0) { |
| @@ -640,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 640 | { | 685 | { |
| 641 | struct bd2802_led *led; | 686 | struct bd2802_led *led; |
| 642 | struct bd2802_led_platform_data *pdata; | 687 | struct bd2802_led_platform_data *pdata; |
| 643 | int ret; | 688 | int ret, i; |
| 644 | 689 | ||
| 645 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); | 690 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); |
| 646 | if (!led) { | 691 | if (!led) { |
| @@ -670,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 670 | /* To save the power, reset BD2802 after detecting */ | 715 | /* To save the power, reset BD2802 after detecting */ |
| 671 | gpio_set_value(led->pdata->reset_gpio, 0); | 716 | gpio_set_value(led->pdata->reset_gpio, 0); |
| 672 | 717 | ||
| 718 | /* Default attributes */ | ||
| 719 | led->wave_pattern = BD2802_PATTERN_HALF; | ||
| 720 | led->rgb_current = BD2802_CURRENT_032; | ||
| 721 | |||
| 673 | init_rwsem(&led->rwsem); | 722 | init_rwsem(&led->rwsem); |
| 674 | 723 | ||
| 675 | ret = device_create_file(&client->dev, &bd2802_adv_conf_attr); | 724 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) { |
| 676 | if (ret) { | 725 | ret = device_create_file(&led->client->dev, |
| 677 | dev_err(&client->dev, "failed to create sysfs file %s\n", | 726 | bd2802_attributes[i]); |
| 678 | bd2802_adv_conf_attr.attr.name); | 727 | if (ret) { |
| 679 | goto failed_free; | 728 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
| 729 | bd2802_attributes[i]->attr.name); | ||
| 730 | goto failed_unregister_dev_file; | ||
| 731 | } | ||
| 680 | } | 732 | } |
| 681 | 733 | ||
| 682 | ret = bd2802_register_led_classdev(led); | 734 | ret = bd2802_register_led_classdev(led); |
| @@ -686,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 686 | return 0; | 738 | return 0; |
| 687 | 739 | ||
| 688 | failed_unregister_dev_file: | 740 | failed_unregister_dev_file: |
| 689 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 741 | for (i--; i >= 0; i--) |
| 742 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
| 690 | failed_free: | 743 | failed_free: |
| 691 | i2c_set_clientdata(client, NULL); | 744 | i2c_set_clientdata(client, NULL); |
| 692 | kfree(led); | 745 | kfree(led); |
| @@ -697,12 +750,14 @@ failed_free: | |||
| 697 | static int __exit bd2802_remove(struct i2c_client *client) | 750 | static int __exit bd2802_remove(struct i2c_client *client) |
| 698 | { | 751 | { |
| 699 | struct bd2802_led *led = i2c_get_clientdata(client); | 752 | struct bd2802_led *led = i2c_get_clientdata(client); |
| 753 | int i; | ||
| 700 | 754 | ||
| 701 | bd2802_unregister_led_classdev(led); | ||
| 702 | gpio_set_value(led->pdata->reset_gpio, 0); | 755 | gpio_set_value(led->pdata->reset_gpio, 0); |
| 756 | bd2802_unregister_led_classdev(led); | ||
| 703 | if (led->adf_on) | 757 | if (led->adf_on) |
| 704 | bd2802_disable_adv_conf(led); | 758 | bd2802_disable_adv_conf(led); |
| 705 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 759 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) |
| 760 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
| 706 | i2c_set_clientdata(client, NULL); | 761 | i2c_set_clientdata(client, NULL); |
| 707 | kfree(led); | 762 | kfree(led); |
| 708 | 763 | ||
| @@ -723,8 +778,7 @@ static int bd2802_resume(struct i2c_client *client) | |||
| 723 | struct bd2802_led *led = i2c_get_clientdata(client); | 778 | struct bd2802_led *led = i2c_get_clientdata(client); |
| 724 | 779 | ||
| 725 | if (!bd2802_is_all_off(led) || led->adf_on) { | 780 | if (!bd2802_is_all_off(led) || led->adf_on) { |
| 726 | gpio_set_value(led->pdata->reset_gpio, 1); | 781 | bd2802_reset_cancel(led); |
| 727 | udelay(100); | ||
| 728 | bd2802_restore_state(led); | 782 | bd2802_restore_state(led); |
| 729 | } | 783 | } |
| 730 | 784 | ||
| @@ -762,4 +816,4 @@ module_exit(bd2802_exit); | |||
| 762 | 816 | ||
| 763 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | 817 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); |
| 764 | MODULE_DESCRIPTION("BD2802 LED driver"); | 818 | MODULE_DESCRIPTION("BD2802 LED driver"); |
| 765 | MODULE_LICENSE("GPL"); | 819 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c index ff0e8c3fbf9b..5f1ce810815f 100644 --- a/drivers/leds/leds-cobalt-raq.c +++ b/drivers/leds/leds-cobalt-raq.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * LEDs driver for the Cobalt Raq series. | 2 | * LEDs driver for the Cobalt Raq series. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index d2109054de85..6b06638eb5b4 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
| @@ -76,7 +76,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
| 76 | struct gpio_led_data *led_dat, struct device *parent, | 76 | struct gpio_led_data *led_dat, struct device *parent, |
| 77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) | 77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) |
| 78 | { | 78 | { |
| 79 | int ret; | 79 | int ret, state; |
| 80 | 80 | ||
| 81 | /* skip leds that aren't available */ | 81 | /* skip leds that aren't available */ |
| 82 | if (!gpio_is_valid(template->gpio)) { | 82 | if (!gpio_is_valid(template->gpio)) { |
| @@ -99,11 +99,15 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
| 99 | led_dat->cdev.blink_set = gpio_blink_set; | 99 | led_dat->cdev.blink_set = gpio_blink_set; |
| 100 | } | 100 | } |
| 101 | led_dat->cdev.brightness_set = gpio_led_set; | 101 | led_dat->cdev.brightness_set = gpio_led_set; |
| 102 | led_dat->cdev.brightness = LED_OFF; | 102 | if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) |
| 103 | state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low; | ||
| 104 | else | ||
| 105 | state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); | ||
| 106 | led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; | ||
| 103 | if (!template->retain_state_suspended) | 107 | if (!template->retain_state_suspended) |
| 104 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | 108 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; |
| 105 | 109 | ||
| 106 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low); | 110 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); |
| 107 | if (ret < 0) | 111 | if (ret < 0) |
| 108 | goto err; | 112 | goto err; |
| 109 | 113 | ||
| @@ -129,7 +133,7 @@ static void delete_gpio_led(struct gpio_led_data *led) | |||
| 129 | } | 133 | } |
| 130 | 134 | ||
| 131 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | 135 | #ifdef CONFIG_LEDS_GPIO_PLATFORM |
| 132 | static int gpio_led_probe(struct platform_device *pdev) | 136 | static int __devinit gpio_led_probe(struct platform_device *pdev) |
| 133 | { | 137 | { |
| 134 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 138 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; |
| 135 | struct gpio_led_data *leds_data; | 139 | struct gpio_led_data *leds_data; |
| @@ -223,12 +227,22 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | |||
| 223 | memset(&led, 0, sizeof(led)); | 227 | memset(&led, 0, sizeof(led)); |
| 224 | for_each_child_of_node(np, child) { | 228 | for_each_child_of_node(np, child) { |
| 225 | enum of_gpio_flags flags; | 229 | enum of_gpio_flags flags; |
| 230 | const char *state; | ||
| 226 | 231 | ||
| 227 | led.gpio = of_get_gpio_flags(child, 0, &flags); | 232 | led.gpio = of_get_gpio_flags(child, 0, &flags); |
| 228 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; | 233 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; |
| 229 | led.name = of_get_property(child, "label", NULL) ? : child->name; | 234 | led.name = of_get_property(child, "label", NULL) ? : child->name; |
| 230 | led.default_trigger = | 235 | led.default_trigger = |
| 231 | of_get_property(child, "linux,default-trigger", NULL); | 236 | of_get_property(child, "linux,default-trigger", NULL); |
| 237 | state = of_get_property(child, "default-state", NULL); | ||
| 238 | if (state) { | ||
| 239 | if (!strcmp(state, "keep")) | ||
| 240 | led.default_state = LEDS_GPIO_DEFSTATE_KEEP; | ||
| 241 | else if(!strcmp(state, "on")) | ||
| 242 | led.default_state = LEDS_GPIO_DEFSTATE_ON; | ||
| 243 | else | ||
| 244 | led.default_state = LEDS_GPIO_DEFSTATE_OFF; | ||
| 245 | } | ||
| 232 | 246 | ||
| 233 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], | 247 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], |
| 234 | &ofdev->dev, NULL); | 248 | &ofdev->dev, NULL); |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c new file mode 100644 index 000000000000..5946208ba26e --- /dev/null +++ b/drivers/leds/leds-lp3944.c | |||
| @@ -0,0 +1,466 @@ | |||
| 1 | /* | ||
| 2 | * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> | ||
| 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 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* | ||
| 13 | * I2C driver for National Semiconductor LP3944 Funlight Chip | ||
| 14 | * http://www.national.com/pf/LP/LP3944.html | ||
| 15 | * | ||
| 16 | * This helper chip can drive up to 8 leds, with two programmable DIM modes; | ||
| 17 | * it could even be used as a gpio expander but this driver assumes it is used | ||
| 18 | * as a led controller. | ||
| 19 | * | ||
| 20 | * The DIM modes are used to set _blink_ patterns for leds, the pattern is | ||
| 21 | * specified supplying two parameters: | ||
| 22 | * - period: from 0s to 1.6s | ||
| 23 | * - duty cycle: percentage of the period the led is on, from 0 to 100 | ||
| 24 | * | ||
| 25 | * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb | ||
| 26 | * leds, the camera flash light and the displays backlights. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include <linux/leds.h> | ||
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/workqueue.h> | ||
| 34 | #include <linux/leds-lp3944.h> | ||
| 35 | |||
| 36 | /* Read Only Registers */ | ||
| 37 | #define LP3944_REG_INPUT1 0x00 /* LEDs 0-7 InputRegister (Read Only) */ | ||
| 38 | #define LP3944_REG_REGISTER1 0x01 /* None (Read Only) */ | ||
| 39 | |||
| 40 | #define LP3944_REG_PSC0 0x02 /* Frequency Prescaler 0 (R/W) */ | ||
| 41 | #define LP3944_REG_PWM0 0x03 /* PWM Register 0 (R/W) */ | ||
| 42 | #define LP3944_REG_PSC1 0x04 /* Frequency Prescaler 1 (R/W) */ | ||
| 43 | #define LP3944_REG_PWM1 0x05 /* PWM Register 1 (R/W) */ | ||
| 44 | #define LP3944_REG_LS0 0x06 /* LEDs 0-3 Selector (R/W) */ | ||
| 45 | #define LP3944_REG_LS1 0x07 /* LEDs 4-7 Selector (R/W) */ | ||
| 46 | |||
| 47 | /* These registers are not used to control leds in LP3944, they can store | ||
| 48 | * arbitrary values which the chip will ignore. | ||
| 49 | */ | ||
| 50 | #define LP3944_REG_REGISTER8 0x08 | ||
| 51 | #define LP3944_REG_REGISTER9 0x09 | ||
| 52 | |||
| 53 | #define LP3944_DIM0 0 | ||
| 54 | #define LP3944_DIM1 1 | ||
| 55 | |||
| 56 | /* period in ms */ | ||
| 57 | #define LP3944_PERIOD_MIN 0 | ||
| 58 | #define LP3944_PERIOD_MAX 1600 | ||
| 59 | |||
| 60 | /* duty cycle is a percentage */ | ||
| 61 | #define LP3944_DUTY_CYCLE_MIN 0 | ||
| 62 | #define LP3944_DUTY_CYCLE_MAX 100 | ||
| 63 | |||
| 64 | #define ldev_to_led(c) container_of(c, struct lp3944_led_data, ldev) | ||
| 65 | |||
| 66 | /* Saved data */ | ||
| 67 | struct lp3944_led_data { | ||
| 68 | u8 id; | ||
| 69 | enum lp3944_type type; | ||
| 70 | enum lp3944_status status; | ||
| 71 | struct led_classdev ldev; | ||
| 72 | struct i2c_client *client; | ||
| 73 | struct work_struct work; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct lp3944_data { | ||
| 77 | struct mutex lock; | ||
| 78 | struct i2c_client *client; | ||
| 79 | struct lp3944_led_data leds[LP3944_LEDS_MAX]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value) | ||
| 83 | { | ||
| 84 | int tmp; | ||
| 85 | |||
| 86 | tmp = i2c_smbus_read_byte_data(client, reg); | ||
| 87 | if (tmp < 0) | ||
| 88 | return -EINVAL; | ||
| 89 | |||
| 90 | *value = tmp; | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value) | ||
| 96 | { | ||
| 97 | return i2c_smbus_write_byte_data(client, reg, value); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Set the period for DIM status | ||
| 102 | * | ||
| 103 | * @client: the i2c client | ||
| 104 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
| 105 | * @period: period of a blink, that is a on/off cycle, expressed in ms. | ||
| 106 | */ | ||
| 107 | static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period) | ||
| 108 | { | ||
| 109 | u8 psc_reg; | ||
| 110 | u8 psc_value; | ||
| 111 | int err; | ||
| 112 | |||
| 113 | if (dim == LP3944_DIM0) | ||
| 114 | psc_reg = LP3944_REG_PSC0; | ||
| 115 | else if (dim == LP3944_DIM1) | ||
| 116 | psc_reg = LP3944_REG_PSC1; | ||
| 117 | else | ||
| 118 | return -EINVAL; | ||
| 119 | |||
| 120 | /* Convert period to Prescaler value */ | ||
| 121 | if (period > LP3944_PERIOD_MAX) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | psc_value = (period * 255) / LP3944_PERIOD_MAX; | ||
| 125 | |||
| 126 | err = lp3944_reg_write(client, psc_reg, psc_value); | ||
| 127 | |||
| 128 | return err; | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Set the duty cycle for DIM status | ||
| 133 | * | ||
| 134 | * @client: the i2c client | ||
| 135 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
| 136 | * @duty_cycle: percentage of a period during which a led is ON | ||
| 137 | */ | ||
| 138 | static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim, | ||
| 139 | u8 duty_cycle) | ||
| 140 | { | ||
| 141 | u8 pwm_reg; | ||
| 142 | u8 pwm_value; | ||
| 143 | int err; | ||
| 144 | |||
| 145 | if (dim == LP3944_DIM0) | ||
| 146 | pwm_reg = LP3944_REG_PWM0; | ||
| 147 | else if (dim == LP3944_DIM1) | ||
| 148 | pwm_reg = LP3944_REG_PWM1; | ||
| 149 | else | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | /* Convert duty cycle to PWM value */ | ||
| 153 | if (duty_cycle > LP3944_DUTY_CYCLE_MAX) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX; | ||
| 157 | |||
| 158 | err = lp3944_reg_write(client, pwm_reg, pwm_value); | ||
| 159 | |||
| 160 | return err; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Set the led status | ||
| 165 | * | ||
| 166 | * @led: a lp3944_led_data structure | ||
| 167 | * @status: one of LP3944_LED_STATUS_OFF | ||
| 168 | * LP3944_LED_STATUS_ON | ||
| 169 | * LP3944_LED_STATUS_DIM0 | ||
| 170 | * LP3944_LED_STATUS_DIM1 | ||
| 171 | */ | ||
| 172 | static int lp3944_led_set(struct lp3944_led_data *led, u8 status) | ||
| 173 | { | ||
| 174 | struct lp3944_data *data = i2c_get_clientdata(led->client); | ||
| 175 | u8 id = led->id; | ||
| 176 | u8 reg; | ||
| 177 | u8 val = 0; | ||
| 178 | int err; | ||
| 179 | |||
| 180 | dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n", | ||
| 181 | __func__, led->ldev.name, status); | ||
| 182 | |||
| 183 | switch (id) { | ||
| 184 | case LP3944_LED0: | ||
| 185 | case LP3944_LED1: | ||
| 186 | case LP3944_LED2: | ||
| 187 | case LP3944_LED3: | ||
| 188 | reg = LP3944_REG_LS0; | ||
| 189 | break; | ||
| 190 | case LP3944_LED4: | ||
| 191 | case LP3944_LED5: | ||
| 192 | case LP3944_LED6: | ||
| 193 | case LP3944_LED7: | ||
| 194 | id -= LP3944_LED4; | ||
| 195 | reg = LP3944_REG_LS1; | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (status > LP3944_LED_STATUS_DIM1) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | /* invert only 0 and 1, leave unchanged the other values, | ||
| 205 | * remember we are abusing status to set blink patterns | ||
| 206 | */ | ||
| 207 | if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2) | ||
| 208 | status = 1 - status; | ||
| 209 | |||
| 210 | mutex_lock(&data->lock); | ||
| 211 | lp3944_reg_read(led->client, reg, &val); | ||
| 212 | |||
| 213 | val &= ~(LP3944_LED_STATUS_MASK << (id << 1)); | ||
| 214 | val |= (status << (id << 1)); | ||
| 215 | |||
| 216 | dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n", | ||
| 217 | __func__, led->ldev.name, reg, id, status, val); | ||
| 218 | |||
| 219 | /* set led status */ | ||
| 220 | err = lp3944_reg_write(led->client, reg, val); | ||
| 221 | mutex_unlock(&data->lock); | ||
| 222 | |||
| 223 | return err; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int lp3944_led_set_blink(struct led_classdev *led_cdev, | ||
| 227 | unsigned long *delay_on, | ||
| 228 | unsigned long *delay_off) | ||
| 229 | { | ||
| 230 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
| 231 | u16 period; | ||
| 232 | u8 duty_cycle; | ||
| 233 | int err; | ||
| 234 | |||
| 235 | /* units are in ms */ | ||
| 236 | if (*delay_on + *delay_off > LP3944_PERIOD_MAX) | ||
| 237 | return -EINVAL; | ||
| 238 | |||
| 239 | if (*delay_on == 0 && *delay_off == 0) { | ||
| 240 | /* Special case: the leds subsystem requires a default user | ||
| 241 | * friendly blink pattern for the LED. Let's blink the led | ||
| 242 | * slowly (1Hz). | ||
| 243 | */ | ||
| 244 | *delay_on = 500; | ||
| 245 | *delay_off = 500; | ||
| 246 | } | ||
| 247 | |||
| 248 | period = (*delay_on) + (*delay_off); | ||
| 249 | |||
| 250 | /* duty_cycle is the percentage of period during which the led is ON */ | ||
| 251 | duty_cycle = 100 * (*delay_on) / period; | ||
| 252 | |||
| 253 | /* invert duty cycle for inverted leds, this has the same effect of | ||
| 254 | * swapping delay_on and delay_off | ||
| 255 | */ | ||
| 256 | if (led->type == LP3944_LED_TYPE_LED_INVERTED) | ||
| 257 | duty_cycle = 100 - duty_cycle; | ||
| 258 | |||
| 259 | /* NOTE: using always the first DIM mode, this means that all leds | ||
| 260 | * will have the same blinking pattern. | ||
| 261 | * | ||
| 262 | * We could find a way later to have two leds blinking in hardware | ||
| 263 | * with different patterns at the same time, falling back to software | ||
| 264 | * control for the other ones. | ||
| 265 | */ | ||
| 266 | err = lp3944_dim_set_period(led->client, LP3944_DIM0, period); | ||
| 267 | if (err) | ||
| 268 | return err; | ||
| 269 | |||
| 270 | err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle); | ||
| 271 | if (err) | ||
| 272 | return err; | ||
| 273 | |||
| 274 | dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n", | ||
| 275 | __func__); | ||
| 276 | |||
| 277 | led->status = LP3944_LED_STATUS_DIM0; | ||
| 278 | schedule_work(&led->work); | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 283 | static void lp3944_led_set_brightness(struct led_classdev *led_cdev, | ||
| 284 | enum led_brightness brightness) | ||
| 285 | { | ||
| 286 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
| 287 | |||
| 288 | dev_dbg(&led->client->dev, "%s: %s, %d\n", | ||
| 289 | __func__, led_cdev->name, brightness); | ||
| 290 | |||
| 291 | led->status = brightness; | ||
| 292 | schedule_work(&led->work); | ||
| 293 | } | ||
| 294 | |||
| 295 | static void lp3944_led_work(struct work_struct *work) | ||
| 296 | { | ||
| 297 | struct lp3944_led_data *led; | ||
| 298 | |||
| 299 | led = container_of(work, struct lp3944_led_data, work); | ||
| 300 | lp3944_led_set(led, led->status); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int lp3944_configure(struct i2c_client *client, | ||
| 304 | struct lp3944_data *data, | ||
| 305 | struct lp3944_platform_data *pdata) | ||
| 306 | { | ||
| 307 | int i, err = 0; | ||
| 308 | |||
| 309 | for (i = 0; i < pdata->leds_size; i++) { | ||
| 310 | struct lp3944_led *pled = &pdata->leds[i]; | ||
| 311 | struct lp3944_led_data *led = &data->leds[i]; | ||
| 312 | led->client = client; | ||
| 313 | led->id = i; | ||
| 314 | |||
| 315 | switch (pled->type) { | ||
| 316 | |||
| 317 | case LP3944_LED_TYPE_LED: | ||
| 318 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 319 | led->type = pled->type; | ||
| 320 | led->status = pled->status; | ||
| 321 | led->ldev.name = pled->name; | ||
| 322 | led->ldev.max_brightness = 1; | ||
| 323 | led->ldev.brightness_set = lp3944_led_set_brightness; | ||
| 324 | led->ldev.blink_set = lp3944_led_set_blink; | ||
| 325 | led->ldev.flags = LED_CORE_SUSPENDRESUME; | ||
| 326 | |||
| 327 | INIT_WORK(&led->work, lp3944_led_work); | ||
| 328 | err = led_classdev_register(&client->dev, &led->ldev); | ||
| 329 | if (err < 0) { | ||
| 330 | dev_err(&client->dev, | ||
| 331 | "couldn't register LED %s\n", | ||
| 332 | led->ldev.name); | ||
| 333 | goto exit; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* to expose the default value to userspace */ | ||
| 337 | led->ldev.brightness = led->status; | ||
| 338 | |||
| 339 | /* Set the default led status */ | ||
| 340 | err = lp3944_led_set(led, led->status); | ||
| 341 | if (err < 0) { | ||
| 342 | dev_err(&client->dev, | ||
| 343 | "%s couldn't set STATUS %d\n", | ||
| 344 | led->ldev.name, led->status); | ||
| 345 | goto exit; | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | |||
| 349 | case LP3944_LED_TYPE_NONE: | ||
| 350 | default: | ||
| 351 | break; | ||
| 352 | |||
| 353 | } | ||
| 354 | } | ||
| 355 | return 0; | ||
| 356 | |||
| 357 | exit: | ||
| 358 | if (i > 0) | ||
| 359 | for (i = i - 1; i >= 0; i--) | ||
| 360 | switch (pdata->leds[i].type) { | ||
| 361 | |||
| 362 | case LP3944_LED_TYPE_LED: | ||
| 363 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 364 | led_classdev_unregister(&data->leds[i].ldev); | ||
| 365 | cancel_work_sync(&data->leds[i].work); | ||
| 366 | break; | ||
| 367 | |||
| 368 | case LP3944_LED_TYPE_NONE: | ||
| 369 | default: | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | |||
| 373 | return err; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int __devinit lp3944_probe(struct i2c_client *client, | ||
| 377 | const struct i2c_device_id *id) | ||
| 378 | { | ||
| 379 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; | ||
| 380 | struct lp3944_data *data; | ||
| 381 | |||
| 382 | if (lp3944_pdata == NULL) { | ||
| 383 | dev_err(&client->dev, "no platform data\n"); | ||
| 384 | return -EINVAL; | ||
| 385 | } | ||
| 386 | |||
| 387 | /* Let's see whether this adapter can support what we need. */ | ||
| 388 | if (!i2c_check_functionality(client->adapter, | ||
| 389 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
| 390 | dev_err(&client->dev, "insufficient functionality!\n"); | ||
| 391 | return -ENODEV; | ||
| 392 | } | ||
| 393 | |||
| 394 | data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL); | ||
| 395 | if (!data) | ||
| 396 | return -ENOMEM; | ||
| 397 | |||
| 398 | data->client = client; | ||
| 399 | i2c_set_clientdata(client, data); | ||
| 400 | |||
| 401 | mutex_init(&data->lock); | ||
| 402 | |||
| 403 | dev_info(&client->dev, "lp3944 enabled\n"); | ||
| 404 | |||
| 405 | lp3944_configure(client, data, lp3944_pdata); | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int __devexit lp3944_remove(struct i2c_client *client) | ||
| 410 | { | ||
| 411 | struct lp3944_platform_data *pdata = client->dev.platform_data; | ||
| 412 | struct lp3944_data *data = i2c_get_clientdata(client); | ||
| 413 | int i; | ||
| 414 | |||
| 415 | for (i = 0; i < pdata->leds_size; i++) | ||
| 416 | switch (data->leds[i].type) { | ||
| 417 | case LP3944_LED_TYPE_LED: | ||
| 418 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 419 | led_classdev_unregister(&data->leds[i].ldev); | ||
| 420 | cancel_work_sync(&data->leds[i].work); | ||
| 421 | break; | ||
| 422 | |||
| 423 | case LP3944_LED_TYPE_NONE: | ||
| 424 | default: | ||
| 425 | break; | ||
| 426 | } | ||
| 427 | |||
| 428 | kfree(data); | ||
| 429 | i2c_set_clientdata(client, NULL); | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* lp3944 i2c driver struct */ | ||
| 435 | static const struct i2c_device_id lp3944_id[] = { | ||
| 436 | {"lp3944", 0}, | ||
| 437 | {} | ||
| 438 | }; | ||
| 439 | |||
| 440 | MODULE_DEVICE_TABLE(i2c, lp3944_id); | ||
| 441 | |||
| 442 | static struct i2c_driver lp3944_driver = { | ||
| 443 | .driver = { | ||
| 444 | .name = "lp3944", | ||
| 445 | }, | ||
| 446 | .probe = lp3944_probe, | ||
| 447 | .remove = __devexit_p(lp3944_remove), | ||
| 448 | .id_table = lp3944_id, | ||
| 449 | }; | ||
| 450 | |||
| 451 | static int __init lp3944_module_init(void) | ||
| 452 | { | ||
| 453 | return i2c_add_driver(&lp3944_driver); | ||
| 454 | } | ||
| 455 | |||
| 456 | static void __exit lp3944_module_exit(void) | ||
| 457 | { | ||
| 458 | i2c_del_driver(&lp3944_driver); | ||
| 459 | } | ||
| 460 | |||
| 461 | module_init(lp3944_module_init); | ||
| 462 | module_exit(lp3944_module_exit); | ||
| 463 | |||
| 464 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
| 465 | MODULE_DESCRIPTION("LP3944 Fun Light Chip"); | ||
| 466 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 3937244fdcab..dba8921240f2 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
| @@ -35,7 +35,7 @@ struct pca9532_data { | |||
| 35 | struct pca9532_led leds[16]; | 35 | struct pca9532_led leds[16]; |
| 36 | struct mutex update_lock; | 36 | struct mutex update_lock; |
| 37 | struct input_dev *idev; | 37 | struct input_dev *idev; |
| 38 | struct work_struct work; | 38 | struct work_struct work; |
| 39 | u8 pwm[2]; | 39 | u8 pwm[2]; |
| 40 | u8 psc[2]; | 40 | u8 psc[2]; |
| 41 | }; | 41 | }; |
| @@ -87,14 +87,14 @@ static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink, | |||
| 87 | if (b > 0xFF) | 87 | if (b > 0xFF) |
| 88 | return -EINVAL; | 88 | return -EINVAL; |
| 89 | data->pwm[pwm] = b; | 89 | data->pwm[pwm] = b; |
| 90 | data->psc[pwm] = blink; | 90 | data->psc[pwm] = blink; |
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) | 94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) |
| 95 | { | 95 | { |
| 96 | struct pca9532_data *data = i2c_get_clientdata(client); | 96 | struct pca9532_data *data = i2c_get_clientdata(client); |
| 97 | mutex_lock(&data->update_lock); | 97 | mutex_lock(&data->update_lock); |
| 98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), | 98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), |
| 99 | data->pwm[pwm]); | 99 | data->pwm[pwm]); |
| 100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), | 100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), |
| @@ -132,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev, | |||
| 132 | led->state = PCA9532_ON; | 132 | led->state = PCA9532_ON; |
| 133 | else { | 133 | else { |
| 134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ | 134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ |
| 135 | err = pca9532_calcpwm(led->client, 0, 0, value); | 135 | err = pca9532_calcpwm(led->client, 0, 0, value); |
| 136 | if (err) | 136 | if (err) |
| 137 | return; /* XXX: led api doesn't allow error code? */ | 137 | return; /* XXX: led api doesn't allow error code? */ |
| 138 | } | 138 | } |
| 139 | schedule_work(&led->work); | 139 | schedule_work(&led->work); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static int pca9532_set_blink(struct led_classdev *led_cdev, | 142 | static int pca9532_set_blink(struct led_classdev *led_cdev, |
| @@ -145,7 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
| 145 | struct pca9532_led *led = ldev_to_led(led_cdev); | 145 | struct pca9532_led *led = ldev_to_led(led_cdev); |
| 146 | struct i2c_client *client = led->client; | 146 | struct i2c_client *client = led->client; |
| 147 | int psc; | 147 | int psc; |
| 148 | int err = 0; | 148 | int err = 0; |
| 149 | 149 | ||
| 150 | if (*delay_on == 0 && *delay_off == 0) { | 150 | if (*delay_on == 0 && *delay_off == 0) { |
| 151 | /* led subsystem ask us for a blink rate */ | 151 | /* led subsystem ask us for a blink rate */ |
| @@ -157,11 +157,11 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
| 157 | 157 | ||
| 158 | /* Thecus specific: only use PSC/PWM 0 */ | 158 | /* Thecus specific: only use PSC/PWM 0 */ |
| 159 | psc = (*delay_on * 152-1)/1000; | 159 | psc = (*delay_on * 152-1)/1000; |
| 160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); | 160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); |
| 161 | if (err) | 161 | if (err) |
| 162 | return err; | 162 | return err; |
| 163 | schedule_work(&led->work); | 163 | schedule_work(&led->work); |
| 164 | return 0; | 164 | return 0; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static int pca9532_event(struct input_dev *dev, unsigned int type, | 167 | static int pca9532_event(struct input_dev *dev, unsigned int type, |
| @@ -178,15 +178,15 @@ static int pca9532_event(struct input_dev *dev, unsigned int type, | |||
| 178 | else | 178 | else |
| 179 | data->pwm[1] = 0; | 179 | data->pwm[1] = 0; |
| 180 | 180 | ||
| 181 | schedule_work(&data->work); | 181 | schedule_work(&data->work); |
| 182 | 182 | ||
| 183 | return 0; | 183 | return 0; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static void pca9532_input_work(struct work_struct *work) | 186 | static void pca9532_input_work(struct work_struct *work) |
| 187 | { | 187 | { |
| 188 | struct pca9532_data *data; | 188 | struct pca9532_data *data; |
| 189 | data = container_of(work, struct pca9532_data, work); | 189 | data = container_of(work, struct pca9532_data, work); |
| 190 | mutex_lock(&data->update_lock); | 190 | mutex_lock(&data->update_lock); |
| 191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), | 191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), |
| 192 | data->pwm[1]); | 192 | data->pwm[1]); |
| @@ -195,11 +195,11 @@ static void pca9532_input_work(struct work_struct *work) | |||
| 195 | 195 | ||
| 196 | static void pca9532_led_work(struct work_struct *work) | 196 | static void pca9532_led_work(struct work_struct *work) |
| 197 | { | 197 | { |
| 198 | struct pca9532_led *led; | 198 | struct pca9532_led *led; |
| 199 | led = container_of(work, struct pca9532_led, work); | 199 | led = container_of(work, struct pca9532_led, work); |
| 200 | if (led->state == PCA9532_PWM0) | 200 | if (led->state == PCA9532_PWM0) |
| 201 | pca9532_setpwm(led->client, 0); | 201 | pca9532_setpwm(led->client, 0); |
| 202 | pca9532_setled(led); | 202 | pca9532_setled(led); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static int pca9532_configure(struct i2c_client *client, | 205 | static int pca9532_configure(struct i2c_client *client, |
| @@ -232,7 +232,7 @@ static int pca9532_configure(struct i2c_client *client, | |||
| 232 | led->ldev.brightness = LED_OFF; | 232 | led->ldev.brightness = LED_OFF; |
| 233 | led->ldev.brightness_set = pca9532_set_brightness; | 233 | led->ldev.brightness_set = pca9532_set_brightness; |
| 234 | led->ldev.blink_set = pca9532_set_blink; | 234 | led->ldev.blink_set = pca9532_set_blink; |
| 235 | INIT_WORK(&led->work, pca9532_led_work); | 235 | INIT_WORK(&led->work, pca9532_led_work); |
| 236 | err = led_classdev_register(&client->dev, &led->ldev); | 236 | err = led_classdev_register(&client->dev, &led->ldev); |
| 237 | if (err < 0) { | 237 | if (err < 0) { |
| 238 | dev_err(&client->dev, | 238 | dev_err(&client->dev, |
| @@ -262,11 +262,11 @@ static int pca9532_configure(struct i2c_client *client, | |||
| 262 | BIT_MASK(SND_TONE); | 262 | BIT_MASK(SND_TONE); |
| 263 | data->idev->event = pca9532_event; | 263 | data->idev->event = pca9532_event; |
| 264 | input_set_drvdata(data->idev, data); | 264 | input_set_drvdata(data->idev, data); |
| 265 | INIT_WORK(&data->work, pca9532_input_work); | 265 | INIT_WORK(&data->work, pca9532_input_work); |
| 266 | err = input_register_device(data->idev); | 266 | err = input_register_device(data->idev); |
| 267 | if (err) { | 267 | if (err) { |
| 268 | input_free_device(data->idev); | 268 | input_free_device(data->idev); |
| 269 | cancel_work_sync(&data->work); | 269 | cancel_work_sync(&data->work); |
| 270 | data->idev = NULL; | 270 | data->idev = NULL; |
| 271 | goto exit; | 271 | goto exit; |
| 272 | } | 272 | } |
| @@ -283,13 +283,13 @@ exit: | |||
| 283 | break; | 283 | break; |
| 284 | case PCA9532_TYPE_LED: | 284 | case PCA9532_TYPE_LED: |
| 285 | led_classdev_unregister(&data->leds[i].ldev); | 285 | led_classdev_unregister(&data->leds[i].ldev); |
| 286 | cancel_work_sync(&data->leds[i].work); | 286 | cancel_work_sync(&data->leds[i].work); |
| 287 | break; | 287 | break; |
| 288 | case PCA9532_TYPE_N2100_BEEP: | 288 | case PCA9532_TYPE_N2100_BEEP: |
| 289 | if (data->idev != NULL) { | 289 | if (data->idev != NULL) { |
| 290 | input_unregister_device(data->idev); | 290 | input_unregister_device(data->idev); |
| 291 | input_free_device(data->idev); | 291 | input_free_device(data->idev); |
| 292 | cancel_work_sync(&data->work); | 292 | cancel_work_sync(&data->work); |
| 293 | data->idev = NULL; | 293 | data->idev = NULL; |
| 294 | } | 294 | } |
| 295 | break; | 295 | break; |
| @@ -340,13 +340,13 @@ static int pca9532_remove(struct i2c_client *client) | |||
| 340 | break; | 340 | break; |
| 341 | case PCA9532_TYPE_LED: | 341 | case PCA9532_TYPE_LED: |
| 342 | led_classdev_unregister(&data->leds[i].ldev); | 342 | led_classdev_unregister(&data->leds[i].ldev); |
| 343 | cancel_work_sync(&data->leds[i].work); | 343 | cancel_work_sync(&data->leds[i].work); |
| 344 | break; | 344 | break; |
| 345 | case PCA9532_TYPE_N2100_BEEP: | 345 | case PCA9532_TYPE_N2100_BEEP: |
| 346 | if (data->idev != NULL) { | 346 | if (data->idev != NULL) { |
| 347 | input_unregister_device(data->idev); | 347 | input_unregister_device(data->idev); |
| 348 | input_free_device(data->idev); | 348 | input_free_device(data->idev); |
| 349 | cancel_work_sync(&data->work); | 349 | cancel_work_sync(&data->work); |
| 350 | data->idev = NULL; | 350 | data->idev = NULL; |
| 351 | } | 351 | } |
| 352 | break; | 352 | break; |
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index d4e8979735cb..01c591923793 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
| @@ -38,8 +38,6 @@ struct lguest_pages | |||
| 38 | #define CHANGED_GDT_TLS 4 /* Actually a subset of CHANGED_GDT */ | 38 | #define CHANGED_GDT_TLS 4 /* Actually a subset of CHANGED_GDT */ |
| 39 | #define CHANGED_ALL 3 | 39 | #define CHANGED_ALL 3 |
| 40 | 40 | ||
| 41 | struct lguest; | ||
| 42 | |||
| 43 | struct lg_cpu { | 41 | struct lg_cpu { |
| 44 | unsigned int id; | 42 | unsigned int id; |
| 45 | struct lguest *lg; | 43 | struct lguest *lg; |
| @@ -82,7 +80,7 @@ struct lg_cpu { | |||
| 82 | 80 | ||
| 83 | struct lg_eventfd { | 81 | struct lg_eventfd { |
| 84 | unsigned long addr; | 82 | unsigned long addr; |
| 85 | struct file *event; | 83 | struct eventfd_ctx *event; |
| 86 | }; | 84 | }; |
| 87 | 85 | ||
| 88 | struct lg_eventfd_map { | 86 | struct lg_eventfd_map { |
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 32e297121058..9f9a2953b383 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
| @@ -50,7 +50,7 @@ static int add_eventfd(struct lguest *lg, unsigned long addr, int fd) | |||
| 50 | 50 | ||
| 51 | /* Now append new entry. */ | 51 | /* Now append new entry. */ |
| 52 | new->map[new->num].addr = addr; | 52 | new->map[new->num].addr = addr; |
| 53 | new->map[new->num].event = eventfd_fget(fd); | 53 | new->map[new->num].event = eventfd_ctx_fdget(fd); |
| 54 | if (IS_ERR(new->map[new->num].event)) { | 54 | if (IS_ERR(new->map[new->num].event)) { |
| 55 | kfree(new); | 55 | kfree(new); |
| 56 | return PTR_ERR(new->map[new->num].event); | 56 | return PTR_ERR(new->map[new->num].event); |
| @@ -357,7 +357,7 @@ static int close(struct inode *inode, struct file *file) | |||
| 357 | 357 | ||
| 358 | /* Release any eventfds they registered. */ | 358 | /* Release any eventfds they registered. */ |
| 359 | for (i = 0; i < lg->eventfds->num; i++) | 359 | for (i = 0; i < lg->eventfds->num; i++) |
| 360 | fput(lg->eventfds->map[i].event); | 360 | eventfd_ctx_put(lg->eventfds->map[i].event); |
| 361 | kfree(lg->eventfds); | 361 | kfree(lg->eventfds); |
| 362 | 362 | ||
| 363 | /* If lg->dead doesn't contain an error code it will be NULL or a | 363 | /* If lg->dead doesn't contain an error code it will be NULL or a |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 6e149f4a1fff..a0f68386c12f 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
| @@ -378,6 +378,17 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
| 378 | dev->ofdev.dev.bus = &macio_bus_type; | 378 | dev->ofdev.dev.bus = &macio_bus_type; |
| 379 | dev->ofdev.dev.release = macio_release_dev; | 379 | dev->ofdev.dev.release = macio_release_dev; |
| 380 | 380 | ||
| 381 | #ifdef CONFIG_PCI | ||
| 382 | /* Set the DMA ops to the ones from the PCI device, this could be | ||
| 383 | * fishy if we didn't know that on PowerMac it's always direct ops | ||
| 384 | * or iommu ops that will work fine | ||
| 385 | */ | ||
| 386 | dev->ofdev.dev.archdata.dma_ops = | ||
| 387 | chip->lbus.pdev->dev.archdata.dma_ops; | ||
| 388 | dev->ofdev.dev.archdata.dma_data = | ||
| 389 | chip->lbus.pdev->dev.archdata.dma_data; | ||
| 390 | #endif /* CONFIG_PCI */ | ||
| 391 | |||
| 381 | #ifdef DEBUG | 392 | #ifdef DEBUG |
| 382 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", | 393 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", |
| 383 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); | 394 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); |
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 36e0675be9f7..020f9573fd82 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
| @@ -231,6 +231,17 @@ config DM_MIRROR | |||
| 231 | Allow volume managers to mirror logical volumes, also | 231 | Allow volume managers to mirror logical volumes, also |
| 232 | needed for live data migration tools such as 'pvmove'. | 232 | needed for live data migration tools such as 'pvmove'. |
| 233 | 233 | ||
| 234 | config DM_LOG_USERSPACE | ||
| 235 | tristate "Mirror userspace logging (EXPERIMENTAL)" | ||
| 236 | depends on DM_MIRROR && EXPERIMENTAL && NET | ||
| 237 | select CONNECTOR | ||
| 238 | ---help--- | ||
| 239 | The userspace logging module provides a mechanism for | ||
| 240 | relaying the dm-dirty-log API to userspace. Log designs | ||
| 241 | which are more suited to userspace implementation (e.g. | ||
| 242 | shared storage logs) or experimental logs can be implemented | ||
| 243 | by leveraging this framework. | ||
| 244 | |||
| 234 | config DM_ZERO | 245 | config DM_ZERO |
| 235 | tristate "Zero target" | 246 | tristate "Zero target" |
| 236 | depends on BLK_DEV_DM | 247 | depends on BLK_DEV_DM |
| @@ -249,6 +260,25 @@ config DM_MULTIPATH | |||
| 249 | ---help--- | 260 | ---help--- |
| 250 | Allow volume managers to support multipath hardware. | 261 | Allow volume managers to support multipath hardware. |
| 251 | 262 | ||
| 263 | config DM_MULTIPATH_QL | ||
| 264 | tristate "I/O Path Selector based on the number of in-flight I/Os" | ||
| 265 | depends on DM_MULTIPATH | ||
| 266 | ---help--- | ||
| 267 | This path selector is a dynamic load balancer which selects | ||
| 268 | the path with the least number of in-flight I/Os. | ||
| 269 | |||
| 270 | If unsure, say N. | ||
| 271 | |||
| 272 | config DM_MULTIPATH_ST | ||
| 273 | tristate "I/O Path Selector based on the service time" | ||
| 274 | depends on DM_MULTIPATH | ||
| 275 | ---help--- | ||
| 276 | This path selector is a dynamic load balancer which selects | ||
| 277 | the path expected to complete the incoming I/O in the shortest | ||
| 278 | time. | ||
| 279 | |||
| 280 | If unsure, say N. | ||
| 281 | |||
| 252 | config DM_DELAY | 282 | config DM_DELAY |
| 253 | tristate "I/O delaying target (EXPERIMENTAL)" | 283 | tristate "I/O delaying target (EXPERIMENTAL)" |
| 254 | depends on BLK_DEV_DM && EXPERIMENTAL | 284 | depends on BLK_DEV_DM && EXPERIMENTAL |
diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 45cc5951d928..1dc4185bd781 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile | |||
| @@ -8,6 +8,8 @@ dm-multipath-y += dm-path-selector.o dm-mpath.o | |||
| 8 | dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ | 8 | dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ |
| 9 | dm-snap-persistent.o | 9 | dm-snap-persistent.o |
| 10 | dm-mirror-y += dm-raid1.o | 10 | dm-mirror-y += dm-raid1.o |
| 11 | dm-log-userspace-y \ | ||
| 12 | += dm-log-userspace-base.o dm-log-userspace-transfer.o | ||
| 11 | md-mod-y += md.o bitmap.o | 13 | md-mod-y += md.o bitmap.o |
| 12 | raid456-y += raid5.o | 14 | raid456-y += raid5.o |
| 13 | raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \ | 15 | raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \ |
| @@ -36,8 +38,11 @@ obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o | |||
| 36 | obj-$(CONFIG_DM_CRYPT) += dm-crypt.o | 38 | obj-$(CONFIG_DM_CRYPT) += dm-crypt.o |
| 37 | obj-$(CONFIG_DM_DELAY) += dm-delay.o | 39 | obj-$(CONFIG_DM_DELAY) += dm-delay.o |
| 38 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o | 40 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o |
| 41 | obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o | ||
| 42 | obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o | ||
| 39 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o | 43 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o |
| 40 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o | 44 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o |
| 45 | obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o | ||
| 41 | obj-$(CONFIG_DM_ZERO) += dm-zero.o | 46 | obj-$(CONFIG_DM_ZERO) += dm-zero.o |
| 42 | 47 | ||
| 43 | quiet_cmd_unroll = UNROLL $@ | 48 | quiet_cmd_unroll = UNROLL $@ |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 53394e863c74..529e2ba505c3 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -776,7 +776,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) | |||
| 776 | * But don't wait if split was due to the io size restriction | 776 | * But don't wait if split was due to the io size restriction |
| 777 | */ | 777 | */ |
| 778 | if (unlikely(out_of_pages)) | 778 | if (unlikely(out_of_pages)) |
| 779 | congestion_wait(WRITE, HZ/100); | 779 | congestion_wait(BLK_RW_ASYNC, HZ/100); |
| 780 | 780 | ||
| 781 | /* | 781 | /* |
| 782 | * With async crypto it is unsafe to share the crypto context | 782 | * With async crypto it is unsafe to share the crypto context |
| @@ -1132,6 +1132,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1132 | goto bad_crypt_queue; | 1132 | goto bad_crypt_queue; |
| 1133 | } | 1133 | } |
| 1134 | 1134 | ||
| 1135 | ti->num_flush_requests = 1; | ||
| 1135 | ti->private = cc; | 1136 | ti->private = cc; |
| 1136 | return 0; | 1137 | return 0; |
| 1137 | 1138 | ||
| @@ -1189,6 +1190,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
| 1189 | union map_info *map_context) | 1190 | union map_info *map_context) |
| 1190 | { | 1191 | { |
| 1191 | struct dm_crypt_io *io; | 1192 | struct dm_crypt_io *io; |
| 1193 | struct crypt_config *cc; | ||
| 1194 | |||
| 1195 | if (unlikely(bio_empty_barrier(bio))) { | ||
| 1196 | cc = ti->private; | ||
| 1197 | bio->bi_bdev = cc->dev->bdev; | ||
| 1198 | return DM_MAPIO_REMAPPED; | ||
| 1199 | } | ||
| 1192 | 1200 | ||
| 1193 | io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); | 1201 | io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); |
| 1194 | 1202 | ||
| @@ -1305,9 +1313,17 @@ static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
| 1305 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 1313 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
| 1306 | } | 1314 | } |
| 1307 | 1315 | ||
| 1316 | static int crypt_iterate_devices(struct dm_target *ti, | ||
| 1317 | iterate_devices_callout_fn fn, void *data) | ||
| 1318 | { | ||
| 1319 | struct crypt_config *cc = ti->private; | ||
| 1320 | |||
| 1321 | return fn(ti, cc->dev, cc->start, data); | ||
| 1322 | } | ||
| 1323 | |||
| 1308 | static struct target_type crypt_target = { | 1324 | static struct target_type crypt_target = { |
| 1309 | .name = "crypt", | 1325 | .name = "crypt", |
| 1310 | .version= {1, 6, 0}, | 1326 | .version = {1, 7, 0}, |
| 1311 | .module = THIS_MODULE, | 1327 | .module = THIS_MODULE, |
| 1312 | .ctr = crypt_ctr, | 1328 | .ctr = crypt_ctr, |
| 1313 | .dtr = crypt_dtr, | 1329 | .dtr = crypt_dtr, |
| @@ -1318,6 +1334,7 @@ static struct target_type crypt_target = { | |||
| 1318 | .resume = crypt_resume, | 1334 | .resume = crypt_resume, |
| 1319 | .message = crypt_message, | 1335 | .message = crypt_message, |
| 1320 | .merge = crypt_merge, | 1336 | .merge = crypt_merge, |
| 1337 | .iterate_devices = crypt_iterate_devices, | ||
| 1321 | }; | 1338 | }; |
| 1322 | 1339 | ||
| 1323 | static int __init dm_crypt_init(void) | 1340 | static int __init dm_crypt_init(void) |
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 559dbb52bc85..4e5b843cd4d7 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
| @@ -197,6 +197,7 @@ out: | |||
| 197 | mutex_init(&dc->timer_lock); | 197 | mutex_init(&dc->timer_lock); |
| 198 | atomic_set(&dc->may_delay, 1); | 198 | atomic_set(&dc->may_delay, 1); |
| 199 | 199 | ||
| 200 | ti->num_flush_requests = 1; | ||
| 200 | ti->private = dc; | 201 | ti->private = dc; |
| 201 | return 0; | 202 | return 0; |
| 202 | 203 | ||
| @@ -278,8 +279,9 @@ static int delay_map(struct dm_target *ti, struct bio *bio, | |||
| 278 | 279 | ||
| 279 | if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { | 280 | if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { |
| 280 | bio->bi_bdev = dc->dev_write->bdev; | 281 | bio->bi_bdev = dc->dev_write->bdev; |
| 281 | bio->bi_sector = dc->start_write + | 282 | if (bio_sectors(bio)) |
| 282 | (bio->bi_sector - ti->begin); | 283 | bio->bi_sector = dc->start_write + |
| 284 | (bio->bi_sector - ti->begin); | ||
| 283 | 285 | ||
| 284 | return delay_bio(dc, dc->write_delay, bio); | 286 | return delay_bio(dc, dc->write_delay, bio); |
| 285 | } | 287 | } |
| @@ -316,9 +318,26 @@ static int delay_status(struct dm_target *ti, status_type_t type, | |||
| 316 | return 0; | 318 | return 0; |
| 317 | } | 319 | } |
| 318 | 320 | ||
| 321 | static int delay_iterate_devices(struct dm_target *ti, | ||
| 322 | iterate_devices_callout_fn fn, void *data) | ||
| 323 | { | ||
| 324 | struct delay_c *dc = ti->private; | ||
| 325 | int ret = 0; | ||
| 326 | |||
| 327 | ret = fn(ti, dc->dev_read, dc->start_read, data); | ||
| 328 | if (ret) | ||
| 329 | goto out; | ||
| 330 | |||
| 331 | if (dc->dev_write) | ||
| 332 | ret = fn(ti, dc->dev_write, dc->start_write, data); | ||
| 333 | |||
| 334 | out: | ||
| 335 | return ret; | ||
| 336 | } | ||
| 337 | |||
| 319 | static struct target_type delay_target = { | 338 | static struct target_type delay_target = { |
| 320 | .name = "delay", | 339 | .name = "delay", |
| 321 | .version = {1, 0, 2}, | 340 | .version = {1, 1, 0}, |
| 322 | .module = THIS_MODULE, | 341 | .module = THIS_MODULE, |
| 323 | .ctr = delay_ctr, | 342 | .ctr = delay_ctr, |
| 324 | .dtr = delay_dtr, | 343 | .dtr = delay_dtr, |
| @@ -326,6 +345,7 @@ static struct target_type delay_target = { | |||
| 326 | .presuspend = delay_presuspend, | 345 | .presuspend = delay_presuspend, |
| 327 | .resume = delay_resume, | 346 | .resume = delay_resume, |
| 328 | .status = delay_status, | 347 | .status = delay_status, |
| 348 | .iterate_devices = delay_iterate_devices, | ||
| 329 | }; | 349 | }; |
| 330 | 350 | ||
| 331 | static int __init dm_delay_init(void) | 351 | static int __init dm_delay_init(void) |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 75d8081a9041..3710ff88fc10 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
| @@ -195,7 +195,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, | |||
| 195 | struct dm_exception_store **store) | 195 | struct dm_exception_store **store) |
| 196 | { | 196 | { |
| 197 | int r = 0; | 197 | int r = 0; |
| 198 | struct dm_exception_store_type *type; | 198 | struct dm_exception_store_type *type = NULL; |
| 199 | struct dm_exception_store *tmp_store; | 199 | struct dm_exception_store *tmp_store; |
| 200 | char persistent; | 200 | char persistent; |
| 201 | 201 | ||
| @@ -211,12 +211,15 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, | |||
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | persistent = toupper(*argv[1]); | 213 | persistent = toupper(*argv[1]); |
| 214 | if (persistent != 'P' && persistent != 'N') { | 214 | if (persistent == 'P') |
| 215 | type = get_type("P"); | ||
| 216 | else if (persistent == 'N') | ||
| 217 | type = get_type("N"); | ||
| 218 | else { | ||
| 215 | ti->error = "Persistent flag is not P or N"; | 219 | ti->error = "Persistent flag is not P or N"; |
| 216 | return -EINVAL; | 220 | return -EINVAL; |
| 217 | } | 221 | } |
| 218 | 222 | ||
| 219 | type = get_type(argv[1]); | ||
| 220 | if (!type) { | 223 | if (!type) { |
| 221 | ti->error = "Exception store type not recognised"; | 224 | ti->error = "Exception store type not recognised"; |
| 222 | r = -EINVAL; | 225 | r = -EINVAL; |
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h index c92701dc5001..2442c8c07898 100644 --- a/drivers/md/dm-exception-store.h +++ b/drivers/md/dm-exception-store.h | |||
| @@ -156,7 +156,7 @@ static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) | |||
| 156 | */ | 156 | */ |
| 157 | static inline sector_t get_dev_size(struct block_device *bdev) | 157 | static inline sector_t get_dev_size(struct block_device *bdev) |
| 158 | { | 158 | { |
| 159 | return bdev->bd_inode->i_size >> SECTOR_SHIFT; | 159 | return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | static inline chunk_t sector_to_chunk(struct dm_exception_store *store, | 162 | static inline chunk_t sector_to_chunk(struct dm_exception_store *store, |
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index e73aabd61cd7..3a2e6a2f8bdd 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
| @@ -22,6 +22,7 @@ struct dm_io_client { | |||
| 22 | /* FIXME: can we shrink this ? */ | 22 | /* FIXME: can we shrink this ? */ |
| 23 | struct io { | 23 | struct io { |
| 24 | unsigned long error_bits; | 24 | unsigned long error_bits; |
| 25 | unsigned long eopnotsupp_bits; | ||
| 25 | atomic_t count; | 26 | atomic_t count; |
| 26 | struct task_struct *sleeper; | 27 | struct task_struct *sleeper; |
| 27 | struct dm_io_client *client; | 28 | struct dm_io_client *client; |
| @@ -107,8 +108,11 @@ static inline unsigned bio_get_region(struct bio *bio) | |||
| 107 | *---------------------------------------------------------------*/ | 108 | *---------------------------------------------------------------*/ |
| 108 | static void dec_count(struct io *io, unsigned int region, int error) | 109 | static void dec_count(struct io *io, unsigned int region, int error) |
| 109 | { | 110 | { |
| 110 | if (error) | 111 | if (error) { |
| 111 | set_bit(region, &io->error_bits); | 112 | set_bit(region, &io->error_bits); |
| 113 | if (error == -EOPNOTSUPP) | ||
| 114 | set_bit(region, &io->eopnotsupp_bits); | ||
| 115 | } | ||
| 112 | 116 | ||
| 113 | if (atomic_dec_and_test(&io->count)) { | 117 | if (atomic_dec_and_test(&io->count)) { |
| 114 | if (io->sleeper) | 118 | if (io->sleeper) |
| @@ -360,7 +364,9 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, | |||
| 360 | return -EIO; | 364 | return -EIO; |
| 361 | } | 365 | } |
| 362 | 366 | ||
| 367 | retry: | ||
| 363 | io.error_bits = 0; | 368 | io.error_bits = 0; |
| 369 | io.eopnotsupp_bits = 0; | ||
| 364 | atomic_set(&io.count, 1); /* see dispatch_io() */ | 370 | atomic_set(&io.count, 1); /* see dispatch_io() */ |
| 365 | io.sleeper = current; | 371 | io.sleeper = current; |
| 366 | io.client = client; | 372 | io.client = client; |
| @@ -377,6 +383,11 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, | |||
| 377 | } | 383 | } |
| 378 | set_current_state(TASK_RUNNING); | 384 | set_current_state(TASK_RUNNING); |
| 379 | 385 | ||
| 386 | if (io.eopnotsupp_bits && (rw & (1 << BIO_RW_BARRIER))) { | ||
| 387 | rw &= ~(1 << BIO_RW_BARRIER); | ||
| 388 | goto retry; | ||
| 389 | } | ||
| 390 | |||
| 380 | if (error_bits) | 391 | if (error_bits) |
| 381 | *error_bits = io.error_bits; | 392 | *error_bits = io.error_bits; |
| 382 | 393 | ||
| @@ -397,6 +408,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, | |||
| 397 | 408 | ||
| 398 | io = mempool_alloc(client->pool, GFP_NOIO); | 409 | io = mempool_alloc(client->pool, GFP_NOIO); |
| 399 | io->error_bits = 0; | 410 | io->error_bits = 0; |
| 411 | io->eopnotsupp_bits = 0; | ||
| 400 | atomic_set(&io->count, 1); /* see dispatch_io() */ | 412 | atomic_set(&io->count, 1); /* see dispatch_io() */ |
| 401 | io->sleeper = NULL; | 413 | io->sleeper = NULL; |
| 402 | io->client = client; | 414 | io->client = client; |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 1128d3fba797..7f77f18fcafa 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
| @@ -276,7 +276,7 @@ retry: | |||
| 276 | up_write(&_hash_lock); | 276 | up_write(&_hash_lock); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | static int dm_hash_rename(const char *old, const char *new) | 279 | static int dm_hash_rename(uint32_t cookie, const char *old, const char *new) |
| 280 | { | 280 | { |
| 281 | char *new_name, *old_name; | 281 | char *new_name, *old_name; |
| 282 | struct hash_cell *hc; | 282 | struct hash_cell *hc; |
| @@ -333,7 +333,7 @@ static int dm_hash_rename(const char *old, const char *new) | |||
| 333 | dm_table_put(table); | 333 | dm_table_put(table); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | dm_kobject_uevent(hc->md); | 336 | dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie); |
| 337 | 337 | ||
| 338 | dm_put(hc->md); | 338 | dm_put(hc->md); |
| 339 | up_write(&_hash_lock); | 339 | up_write(&_hash_lock); |
| @@ -680,6 +680,9 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) | |||
| 680 | 680 | ||
| 681 | __hash_remove(hc); | 681 | __hash_remove(hc); |
| 682 | up_write(&_hash_lock); | 682 | up_write(&_hash_lock); |
| 683 | |||
| 684 | dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr); | ||
| 685 | |||
| 683 | dm_put(md); | 686 | dm_put(md); |
| 684 | param->data_size = 0; | 687 | param->data_size = 0; |
| 685 | return 0; | 688 | return 0; |
| @@ -715,7 +718,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
| 715 | return r; | 718 | return r; |
| 716 | 719 | ||
| 717 | param->data_size = 0; | 720 | param->data_size = 0; |
| 718 | return dm_hash_rename(param->name, new_name); | 721 | return dm_hash_rename(param->event_nr, param->name, new_name); |
| 719 | } | 722 | } |
| 720 | 723 | ||
| 721 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | 724 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) |
| @@ -842,8 +845,11 @@ static int do_resume(struct dm_ioctl *param) | |||
| 842 | if (dm_suspended(md)) | 845 | if (dm_suspended(md)) |
| 843 | r = dm_resume(md); | 846 | r = dm_resume(md); |
| 844 | 847 | ||
| 845 | if (!r) | 848 | |
| 849 | if (!r) { | ||
| 850 | dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr); | ||
| 846 | r = __dev_status(md, param); | 851 | r = __dev_status(md, param); |
| 852 | } | ||
| 847 | 853 | ||
| 848 | dm_put(md); | 854 | dm_put(md); |
| 849 | return r; | 855 | return r; |
| @@ -1044,6 +1050,12 @@ static int populate_table(struct dm_table *table, | |||
| 1044 | next = spec->next; | 1050 | next = spec->next; |
| 1045 | } | 1051 | } |
| 1046 | 1052 | ||
| 1053 | r = dm_table_set_type(table); | ||
| 1054 | if (r) { | ||
| 1055 | DMWARN("unable to set table type"); | ||
| 1056 | return r; | ||
| 1057 | } | ||
| 1058 | |||
| 1047 | return dm_table_complete(table); | 1059 | return dm_table_complete(table); |
| 1048 | } | 1060 | } |
| 1049 | 1061 | ||
| @@ -1089,6 +1101,13 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
| 1089 | goto out; | 1101 | goto out; |
| 1090 | } | 1102 | } |
| 1091 | 1103 | ||
| 1104 | r = dm_table_alloc_md_mempools(t); | ||
| 1105 | if (r) { | ||
| 1106 | DMWARN("unable to allocate mempools for this table"); | ||
| 1107 | dm_table_destroy(t); | ||
| 1108 | goto out; | ||
| 1109 | } | ||
| 1110 | |||
| 1092 | down_write(&_hash_lock); | 1111 | down_write(&_hash_lock); |
| 1093 | hc = dm_get_mdptr(md); | 1112 | hc = dm_get_mdptr(md); |
| 1094 | if (!hc || hc->md != md) { | 1113 | if (!hc || hc->md != md) { |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 79fb53e51c70..9184b6deb868 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
| @@ -53,6 +53,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 53 | goto bad; | 53 | goto bad; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | ti->num_flush_requests = 1; | ||
| 56 | ti->private = lc; | 57 | ti->private = lc; |
| 57 | return 0; | 58 | return 0; |
| 58 | 59 | ||
| @@ -81,7 +82,8 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio) | |||
| 81 | struct linear_c *lc = ti->private; | 82 | struct linear_c *lc = ti->private; |
| 82 | 83 | ||
| 83 | bio->bi_bdev = lc->dev->bdev; | 84 | bio->bi_bdev = lc->dev->bdev; |
| 84 | bio->bi_sector = linear_map_sector(ti, bio->bi_sector); | 85 | if (bio_sectors(bio)) |
| 86 | bio->bi_sector = linear_map_sector(ti, bio->bi_sector); | ||
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | static int linear_map(struct dm_target *ti, struct bio *bio, | 89 | static int linear_map(struct dm_target *ti, struct bio *bio, |
| @@ -132,9 +134,17 @@ static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
| 132 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 134 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
| 133 | } | 135 | } |
| 134 | 136 | ||
| 137 | static int linear_iterate_devices(struct dm_target *ti, | ||
| 138 | iterate_devices_callout_fn fn, void *data) | ||
| 139 | { | ||
| 140 | struct linear_c *lc = ti->private; | ||
| 141 | |||
| 142 | return fn(ti, lc->dev, lc->start, data); | ||
| 143 | } | ||
| 144 | |||
| 135 | static struct target_type linear_target = { | 145 | static struct target_type linear_target = { |
| 136 | .name = "linear", | 146 | .name = "linear", |
| 137 | .version= {1, 0, 3}, | 147 | .version = {1, 1, 0}, |
| 138 | .module = THIS_MODULE, | 148 | .module = THIS_MODULE, |
| 139 | .ctr = linear_ctr, | 149 | .ctr = linear_ctr, |
| 140 | .dtr = linear_dtr, | 150 | .dtr = linear_dtr, |
| @@ -142,6 +152,7 @@ static struct target_type linear_target = { | |||
| 142 | .status = linear_status, | 152 | .status = linear_status, |
| 143 | .ioctl = linear_ioctl, | 153 | .ioctl = linear_ioctl, |
| 144 | .merge = linear_merge, | 154 | .merge = linear_merge, |
| 155 | .iterate_devices = linear_iterate_devices, | ||
| 145 | }; | 156 | }; |
| 146 | 157 | ||
| 147 | int __init dm_linear_init(void) | 158 | int __init dm_linear_init(void) |
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c new file mode 100644 index 000000000000..e69b96560997 --- /dev/null +++ b/drivers/md/dm-log-userspace-base.c | |||
| @@ -0,0 +1,696 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006-2009 Red Hat, Inc. | ||
| 3 | * | ||
| 4 | * This file is released under the LGPL. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/bio.h> | ||
| 8 | #include <linux/dm-dirty-log.h> | ||
| 9 | #include <linux/device-mapper.h> | ||
| 10 | #include <linux/dm-log-userspace.h> | ||
| 11 | |||
| 12 | #include "dm-log-userspace-transfer.h" | ||
| 13 | |||
| 14 | struct flush_entry { | ||
| 15 | int type; | ||
| 16 | region_t region; | ||
| 17 | struct list_head list; | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct log_c { | ||
| 21 | struct dm_target *ti; | ||
| 22 | uint32_t region_size; | ||
| 23 | region_t region_count; | ||
| 24 | char uuid[DM_UUID_LEN]; | ||
| 25 | |||
| 26 | char *usr_argv_str; | ||
| 27 | uint32_t usr_argc; | ||
| 28 | |||
| 29 | /* | ||
| 30 | * in_sync_hint gets set when doing is_remote_recovering. It | ||
| 31 | * represents the first region that needs recovery. IOW, the | ||
| 32 | * first zero bit of sync_bits. This can be useful for to limit | ||
| 33 | * traffic for calls like is_remote_recovering and get_resync_work, | ||
| 34 | * but be take care in its use for anything else. | ||
| 35 | */ | ||
| 36 | uint64_t in_sync_hint; | ||
| 37 | |||
| 38 | spinlock_t flush_lock; | ||
| 39 | struct list_head flush_list; /* only for clear and mark requests */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | static mempool_t *flush_entry_pool; | ||
| 43 | |||
| 44 | static void *flush_entry_alloc(gfp_t gfp_mask, void *pool_data) | ||
| 45 | { | ||
| 46 | return kmalloc(sizeof(struct flush_entry), gfp_mask); | ||
| 47 | } | ||
| 48 | |||
| 49 | static void flush_entry_free(void *element, void *pool_data) | ||
| 50 | { | ||
| 51 | kfree(element); | ||
| 52 | } | ||
| 53 | |||
| 54 | static int userspace_do_request(struct log_c *lc, const char *uuid, | ||
| 55 | int request_type, char *data, size_t data_size, | ||
| 56 | char *rdata, size_t *rdata_size) | ||
| 57 | { | ||
| 58 | int r; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * If the server isn't there, -ESRCH is returned, | ||
| 62 | * and we must keep trying until the server is | ||
| 63 | * restored. | ||
| 64 | */ | ||
| 65 | retry: | ||
| 66 | r = dm_consult_userspace(uuid, request_type, data, | ||
| 67 | data_size, rdata, rdata_size); | ||
| 68 | |||
| 69 | if (r != -ESRCH) | ||
| 70 | return r; | ||
| 71 | |||
| 72 | DMERR(" Userspace log server not found."); | ||
| 73 | while (1) { | ||
| 74 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 75 | schedule_timeout(2*HZ); | ||
| 76 | DMWARN("Attempting to contact userspace log server..."); | ||
| 77 | r = dm_consult_userspace(uuid, DM_ULOG_CTR, lc->usr_argv_str, | ||
| 78 | strlen(lc->usr_argv_str) + 1, | ||
| 79 | NULL, NULL); | ||
| 80 | if (!r) | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete"); | ||
| 84 | r = dm_consult_userspace(uuid, DM_ULOG_RESUME, NULL, | ||
| 85 | 0, NULL, NULL); | ||
| 86 | if (!r) | ||
| 87 | goto retry; | ||
| 88 | |||
| 89 | DMERR("Error trying to resume userspace log: %d", r); | ||
| 90 | |||
| 91 | return -ESRCH; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int build_constructor_string(struct dm_target *ti, | ||
| 95 | unsigned argc, char **argv, | ||
| 96 | char **ctr_str) | ||
| 97 | { | ||
| 98 | int i, str_size; | ||
| 99 | char *str = NULL; | ||
| 100 | |||
| 101 | *ctr_str = NULL; | ||
| 102 | |||
| 103 | for (i = 0, str_size = 0; i < argc; i++) | ||
| 104 | str_size += strlen(argv[i]) + 1; /* +1 for space between args */ | ||
| 105 | |||
| 106 | str_size += 20; /* Max number of chars in a printed u64 number */ | ||
| 107 | |||
| 108 | str = kzalloc(str_size, GFP_KERNEL); | ||
| 109 | if (!str) { | ||
| 110 | DMWARN("Unable to allocate memory for constructor string"); | ||
| 111 | return -ENOMEM; | ||
| 112 | } | ||
| 113 | |||
| 114 | for (i = 0, str_size = 0; i < argc; i++) | ||
| 115 | str_size += sprintf(str + str_size, "%s ", argv[i]); | ||
| 116 | str_size += sprintf(str + str_size, "%llu", | ||
| 117 | (unsigned long long)ti->len); | ||
| 118 | |||
| 119 | *ctr_str = str; | ||
| 120 | return str_size; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 124 | * userspace_ctr | ||
| 125 | * | ||
| 126 | * argv contains: | ||
| 127 | * <UUID> <other args> | ||
| 128 | * Where 'other args' is the userspace implementation specific log | ||
| 129 | * arguments. An example might be: | ||
| 130 | * <UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync] | ||
| 131 | * | ||
| 132 | * So, this module will strip off the <UUID> for identification purposes | ||
| 133 | * when communicating with userspace about a log; but will pass on everything | ||
| 134 | * else. | ||
| 135 | */ | ||
| 136 | static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, | ||
| 137 | unsigned argc, char **argv) | ||
| 138 | { | ||
| 139 | int r = 0; | ||
| 140 | int str_size; | ||
| 141 | char *ctr_str = NULL; | ||
| 142 | struct log_c *lc = NULL; | ||
| 143 | uint64_t rdata; | ||
| 144 | size_t rdata_size = sizeof(rdata); | ||
| 145 | |||
| 146 | if (argc < 3) { | ||
| 147 | DMWARN("Too few arguments to userspace dirty log"); | ||
| 148 | return -EINVAL; | ||
| 149 | } | ||
| 150 | |||
| 151 | lc = kmalloc(sizeof(*lc), GFP_KERNEL); | ||
| 152 | if (!lc) { | ||
| 153 | DMWARN("Unable to allocate userspace log context."); | ||
| 154 | return -ENOMEM; | ||
| 155 | } | ||
| 156 | |||
| 157 | lc->ti = ti; | ||
| 158 | |||
| 159 | if (strlen(argv[0]) > (DM_UUID_LEN - 1)) { | ||
| 160 | DMWARN("UUID argument too long."); | ||
| 161 | kfree(lc); | ||
| 162 | return -EINVAL; | ||
| 163 | } | ||
| 164 | |||
| 165 | strncpy(lc->uuid, argv[0], DM_UUID_LEN); | ||
| 166 | spin_lock_init(&lc->flush_lock); | ||
| 167 | INIT_LIST_HEAD(&lc->flush_list); | ||
| 168 | |||
| 169 | str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str); | ||
| 170 | if (str_size < 0) { | ||
| 171 | kfree(lc); | ||
| 172 | return str_size; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* Send table string */ | ||
| 176 | r = dm_consult_userspace(lc->uuid, DM_ULOG_CTR, | ||
| 177 | ctr_str, str_size, NULL, NULL); | ||
| 178 | |||
| 179 | if (r == -ESRCH) { | ||
| 180 | DMERR("Userspace log server not found"); | ||
| 181 | goto out; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Since the region size does not change, get it now */ | ||
| 185 | rdata_size = sizeof(rdata); | ||
| 186 | r = dm_consult_userspace(lc->uuid, DM_ULOG_GET_REGION_SIZE, | ||
| 187 | NULL, 0, (char *)&rdata, &rdata_size); | ||
| 188 | |||
| 189 | if (r) { | ||
| 190 | DMERR("Failed to get region size of dirty log"); | ||
| 191 | goto out; | ||
| 192 | } | ||
| 193 | |||
| 194 | lc->region_size = (uint32_t)rdata; | ||
| 195 | lc->region_count = dm_sector_div_up(ti->len, lc->region_size); | ||
| 196 | |||
| 197 | out: | ||
| 198 | if (r) { | ||
| 199 | kfree(lc); | ||
| 200 | kfree(ctr_str); | ||
| 201 | } else { | ||
| 202 | lc->usr_argv_str = ctr_str; | ||
| 203 | lc->usr_argc = argc; | ||
| 204 | log->context = lc; | ||
| 205 | } | ||
| 206 | |||
| 207 | return r; | ||
| 208 | } | ||
| 209 | |||
| 210 | static void userspace_dtr(struct dm_dirty_log *log) | ||
| 211 | { | ||
| 212 | int r; | ||
| 213 | struct log_c *lc = log->context; | ||
| 214 | |||
| 215 | r = dm_consult_userspace(lc->uuid, DM_ULOG_DTR, | ||
| 216 | NULL, 0, | ||
| 217 | NULL, NULL); | ||
| 218 | |||
| 219 | kfree(lc->usr_argv_str); | ||
| 220 | kfree(lc); | ||
| 221 | |||
| 222 | return; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int userspace_presuspend(struct dm_dirty_log *log) | ||
| 226 | { | ||
| 227 | int r; | ||
| 228 | struct log_c *lc = log->context; | ||
| 229 | |||
| 230 | r = dm_consult_userspace(lc->uuid, DM_ULOG_PRESUSPEND, | ||
| 231 | NULL, 0, | ||
| 232 | NULL, NULL); | ||
| 233 | |||
| 234 | return r; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int userspace_postsuspend(struct dm_dirty_log *log) | ||
| 238 | { | ||
| 239 | int r; | ||
| 240 | struct log_c *lc = log->context; | ||
| 241 | |||
| 242 | r = dm_consult_userspace(lc->uuid, DM_ULOG_POSTSUSPEND, | ||
| 243 | NULL, 0, | ||
| 244 | NULL, NULL); | ||
| 245 | |||
| 246 | return r; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int userspace_resume(struct dm_dirty_log *log) | ||
| 250 | { | ||
| 251 | int r; | ||
| 252 | struct log_c *lc = log->context; | ||
| 253 | |||
| 254 | lc->in_sync_hint = 0; | ||
| 255 | r = dm_consult_userspace(lc->uuid, DM_ULOG_RESUME, | ||
| 256 | NULL, 0, | ||
| 257 | NULL, NULL); | ||
| 258 | |||
| 259 | return r; | ||
| 260 | } | ||
| 261 | |||
| 262 | static uint32_t userspace_get_region_size(struct dm_dirty_log *log) | ||
| 263 | { | ||
| 264 | struct log_c *lc = log->context; | ||
| 265 | |||
| 266 | return lc->region_size; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* | ||
| 270 | * userspace_is_clean | ||
| 271 | * | ||
| 272 | * Check whether a region is clean. If there is any sort of | ||
| 273 | * failure when consulting the server, we return not clean. | ||
| 274 | * | ||
| 275 | * Returns: 1 if clean, 0 otherwise | ||
| 276 | */ | ||
| 277 | static int userspace_is_clean(struct dm_dirty_log *log, region_t region) | ||
| 278 | { | ||
| 279 | int r; | ||
| 280 | uint64_t region64 = (uint64_t)region; | ||
| 281 | int64_t is_clean; | ||
| 282 | size_t rdata_size; | ||
| 283 | struct log_c *lc = log->context; | ||
| 284 | |||
| 285 | rdata_size = sizeof(is_clean); | ||
| 286 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_CLEAN, | ||
| 287 | (char *)®ion64, sizeof(region64), | ||
| 288 | (char *)&is_clean, &rdata_size); | ||
| 289 | |||
| 290 | return (r) ? 0 : (int)is_clean; | ||
| 291 | } | ||
| 292 | |||
| 293 | /* | ||
| 294 | * userspace_in_sync | ||
| 295 | * | ||
| 296 | * Check if the region is in-sync. If there is any sort | ||
| 297 | * of failure when consulting the server, we assume that | ||
| 298 | * the region is not in sync. | ||
| 299 | * | ||
| 300 | * If 'can_block' is set, return immediately | ||
| 301 | * | ||
| 302 | * Returns: 1 if in-sync, 0 if not-in-sync, -EWOULDBLOCK | ||
| 303 | */ | ||
| 304 | static int userspace_in_sync(struct dm_dirty_log *log, region_t region, | ||
| 305 | int can_block) | ||
| 306 | { | ||
| 307 | int r; | ||
| 308 | uint64_t region64 = region; | ||
| 309 | int64_t in_sync; | ||
| 310 | size_t rdata_size; | ||
| 311 | struct log_c *lc = log->context; | ||
| 312 | |||
| 313 | /* | ||
| 314 | * We can never respond directly - even if in_sync_hint is | ||
| 315 | * set. This is because another machine could see a device | ||
| 316 | * failure and mark the region out-of-sync. If we don't go | ||
| 317 | * to userspace to ask, we might think the region is in-sync | ||
| 318 | * and allow a read to pick up data that is stale. (This is | ||
| 319 | * very unlikely if a device actually fails; but it is very | ||
| 320 | * likely if a connection to one device from one machine fails.) | ||
| 321 | * | ||
| 322 | * There still might be a problem if the mirror caches the region | ||
| 323 | * state as in-sync... but then this call would not be made. So, | ||
| 324 | * that is a mirror problem. | ||
| 325 | */ | ||
| 326 | if (!can_block) | ||
| 327 | return -EWOULDBLOCK; | ||
| 328 | |||
| 329 | rdata_size = sizeof(in_sync); | ||
| 330 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_IN_SYNC, | ||
| 331 | (char *)®ion64, sizeof(region64), | ||
| 332 | (char *)&in_sync, &rdata_size); | ||
| 333 | return (r) ? 0 : (int)in_sync; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* | ||
| 337 | * userspace_flush | ||
| 338 | * | ||
| 339 | * This function is ok to block. | ||
| 340 | * The flush happens in two stages. First, it sends all | ||
| 341 | * clear/mark requests that are on the list. Then it | ||
| 342 | * tells the server to commit them. This gives the | ||
| 343 | * server a chance to optimise the commit, instead of | ||
| 344 | * doing it for every request. | ||
| 345 | * | ||
| 346 | * Additionally, we could implement another thread that | ||
| 347 | * sends the requests up to the server - reducing the | ||
| 348 | * load on flush. Then the flush would have less in | ||
| 349 | * the list and be responsible for the finishing commit. | ||
| 350 | * | ||
| 351 | * Returns: 0 on success, < 0 on failure | ||
| 352 | */ | ||
| 353 | static int userspace_flush(struct dm_dirty_log *log) | ||
| 354 | { | ||
| 355 | int r = 0; | ||
| 356 | unsigned long flags; | ||
| 357 | struct log_c *lc = log->context; | ||
| 358 | LIST_HEAD(flush_list); | ||
| 359 | struct flush_entry *fe, *tmp_fe; | ||
| 360 | |||
| 361 | spin_lock_irqsave(&lc->flush_lock, flags); | ||
| 362 | list_splice_init(&lc->flush_list, &flush_list); | ||
| 363 | spin_unlock_irqrestore(&lc->flush_lock, flags); | ||
| 364 | |||
| 365 | if (list_empty(&flush_list)) | ||
| 366 | return 0; | ||
| 367 | |||
| 368 | /* | ||
| 369 | * FIXME: Count up requests, group request types, | ||
| 370 | * allocate memory to stick all requests in and | ||
| 371 | * send to server in one go. Failing the allocation, | ||
| 372 | * do it one by one. | ||
| 373 | */ | ||
| 374 | |||
| 375 | list_for_each_entry(fe, &flush_list, list) { | ||
| 376 | r = userspace_do_request(lc, lc->uuid, fe->type, | ||
| 377 | (char *)&fe->region, | ||
| 378 | sizeof(fe->region), | ||
| 379 | NULL, NULL); | ||
| 380 | if (r) | ||
| 381 | goto fail; | ||
| 382 | } | ||
| 383 | |||
| 384 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_FLUSH, | ||
| 385 | NULL, 0, NULL, NULL); | ||
| 386 | |||
| 387 | fail: | ||
| 388 | /* | ||
| 389 | * We can safely remove these entries, even if failure. | ||
| 390 | * Calling code will receive an error and will know that | ||
| 391 | * the log facility has failed. | ||
| 392 | */ | ||
| 393 | list_for_each_entry_safe(fe, tmp_fe, &flush_list, list) { | ||
| 394 | list_del(&fe->list); | ||
| 395 | mempool_free(fe, flush_entry_pool); | ||
| 396 | } | ||
| 397 | |||
| 398 | if (r) | ||
| 399 | dm_table_event(lc->ti->table); | ||
| 400 | |||
| 401 | return r; | ||
| 402 | } | ||
| 403 | |||
| 404 | /* | ||
| 405 | * userspace_mark_region | ||
| 406 | * | ||
| 407 | * This function should avoid blocking unless absolutely required. | ||
| 408 | * (Memory allocation is valid for blocking.) | ||
| 409 | */ | ||
| 410 | static void userspace_mark_region(struct dm_dirty_log *log, region_t region) | ||
| 411 | { | ||
| 412 | unsigned long flags; | ||
| 413 | struct log_c *lc = log->context; | ||
| 414 | struct flush_entry *fe; | ||
| 415 | |||
| 416 | /* Wait for an allocation, but _never_ fail */ | ||
| 417 | fe = mempool_alloc(flush_entry_pool, GFP_NOIO); | ||
| 418 | BUG_ON(!fe); | ||
| 419 | |||
| 420 | spin_lock_irqsave(&lc->flush_lock, flags); | ||
| 421 | fe->type = DM_ULOG_MARK_REGION; | ||
| 422 | fe->region = region; | ||
| 423 | list_add(&fe->list, &lc->flush_list); | ||
| 424 | spin_unlock_irqrestore(&lc->flush_lock, flags); | ||
| 425 | |||
| 426 | return; | ||
| 427 | } | ||
| 428 | |||
| 429 | /* | ||
| 430 | * userspace_clear_region | ||
| 431 | * | ||
| 432 | * This function must not block. | ||
| 433 | * So, the alloc can't block. In the worst case, it is ok to | ||
| 434 | * fail. It would simply mean we can't clear the region. | ||
| 435 | * Does nothing to current sync context, but does mean | ||
| 436 | * the region will be re-sync'ed on a reload of the mirror | ||
| 437 | * even though it is in-sync. | ||
| 438 | */ | ||
| 439 | static void userspace_clear_region(struct dm_dirty_log *log, region_t region) | ||
| 440 | { | ||
| 441 | unsigned long flags; | ||
| 442 | struct log_c *lc = log->context; | ||
| 443 | struct flush_entry *fe; | ||
| 444 | |||
| 445 | /* | ||
| 446 | * If we fail to allocate, we skip the clearing of | ||
| 447 | * the region. This doesn't hurt us in any way, except | ||
| 448 | * to cause the region to be resync'ed when the | ||
| 449 | * device is activated next time. | ||
| 450 | */ | ||
| 451 | fe = mempool_alloc(flush_entry_pool, GFP_ATOMIC); | ||
| 452 | if (!fe) { | ||
| 453 | DMERR("Failed to allocate memory to clear region."); | ||
| 454 | return; | ||
| 455 | } | ||
| 456 | |||
| 457 | spin_lock_irqsave(&lc->flush_lock, flags); | ||
| 458 | fe->type = DM_ULOG_CLEAR_REGION; | ||
| 459 | fe->region = region; | ||
| 460 | list_add(&fe->list, &lc->flush_list); | ||
| 461 | spin_unlock_irqrestore(&lc->flush_lock, flags); | ||
| 462 | |||
| 463 | return; | ||
| 464 | } | ||
| 465 | |||
| 466 | /* | ||
| 467 | * userspace_get_resync_work | ||
| 468 | * | ||
| 469 | * Get a region that needs recovery. It is valid to return | ||
| 470 | * an error for this function. | ||
| 471 | * | ||
| 472 | * Returns: 1 if region filled, 0 if no work, <0 on error | ||
| 473 | */ | ||
| 474 | static int userspace_get_resync_work(struct dm_dirty_log *log, region_t *region) | ||
| 475 | { | ||
| 476 | int r; | ||
| 477 | size_t rdata_size; | ||
| 478 | struct log_c *lc = log->context; | ||
| 479 | struct { | ||
| 480 | int64_t i; /* 64-bit for mix arch compatibility */ | ||
| 481 | region_t r; | ||
| 482 | } pkg; | ||
| 483 | |||
| 484 | if (lc->in_sync_hint >= lc->region_count) | ||
| 485 | return 0; | ||
| 486 | |||
| 487 | rdata_size = sizeof(pkg); | ||
| 488 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_RESYNC_WORK, | ||
| 489 | NULL, 0, | ||
| 490 | (char *)&pkg, &rdata_size); | ||
| 491 | |||
| 492 | *region = pkg.r; | ||
| 493 | return (r) ? r : (int)pkg.i; | ||
| 494 | } | ||
| 495 | |||
| 496 | /* | ||
| 497 | * userspace_set_region_sync | ||
| 498 | * | ||
| 499 | * Set the sync status of a given region. This function | ||
| 500 | * must not fail. | ||
| 501 | */ | ||
| 502 | static void userspace_set_region_sync(struct dm_dirty_log *log, | ||
| 503 | region_t region, int in_sync) | ||
| 504 | { | ||
| 505 | int r; | ||
| 506 | struct log_c *lc = log->context; | ||
| 507 | struct { | ||
| 508 | region_t r; | ||
| 509 | int64_t i; | ||
| 510 | } pkg; | ||
| 511 | |||
| 512 | pkg.r = region; | ||
| 513 | pkg.i = (int64_t)in_sync; | ||
| 514 | |||
| 515 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_SET_REGION_SYNC, | ||
| 516 | (char *)&pkg, sizeof(pkg), | ||
| 517 | NULL, NULL); | ||
| 518 | |||
| 519 | /* | ||
| 520 | * It would be nice to be able to report failures. | ||
| 521 | * However, it is easy emough to detect and resolve. | ||
| 522 | */ | ||
| 523 | return; | ||
| 524 | } | ||
| 525 | |||
| 526 | /* | ||
| 527 | * userspace_get_sync_count | ||
| 528 | * | ||
| 529 | * If there is any sort of failure when consulting the server, | ||
| 530 | * we assume that the sync count is zero. | ||
| 531 | * | ||
| 532 | * Returns: sync count on success, 0 on failure | ||
| 533 | */ | ||
| 534 | static region_t userspace_get_sync_count(struct dm_dirty_log *log) | ||
| 535 | { | ||
| 536 | int r; | ||
| 537 | size_t rdata_size; | ||
| 538 | uint64_t sync_count; | ||
| 539 | struct log_c *lc = log->context; | ||
| 540 | |||
| 541 | rdata_size = sizeof(sync_count); | ||
| 542 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_SYNC_COUNT, | ||
| 543 | NULL, 0, | ||
| 544 | (char *)&sync_count, &rdata_size); | ||
| 545 | |||
| 546 | if (r) | ||
| 547 | return 0; | ||
| 548 | |||
| 549 | if (sync_count >= lc->region_count) | ||
| 550 | lc->in_sync_hint = lc->region_count; | ||
| 551 | |||
| 552 | return (region_t)sync_count; | ||
| 553 | } | ||
| 554 | |||
| 555 | /* | ||
| 556 | * userspace_status | ||
| 557 | * | ||
| 558 | * Returns: amount of space consumed | ||
| 559 | */ | ||
| 560 | static int userspace_status(struct dm_dirty_log *log, status_type_t status_type, | ||
| 561 | char *result, unsigned maxlen) | ||
| 562 | { | ||
| 563 | int r = 0; | ||
| 564 | size_t sz = (size_t)maxlen; | ||
| 565 | struct log_c *lc = log->context; | ||
| 566 | |||
| 567 | switch (status_type) { | ||
| 568 | case STATUSTYPE_INFO: | ||
| 569 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_STATUS_INFO, | ||
| 570 | NULL, 0, | ||
| 571 | result, &sz); | ||
| 572 | |||
| 573 | if (r) { | ||
| 574 | sz = 0; | ||
| 575 | DMEMIT("%s 1 COM_FAILURE", log->type->name); | ||
| 576 | } | ||
| 577 | break; | ||
| 578 | case STATUSTYPE_TABLE: | ||
| 579 | sz = 0; | ||
| 580 | DMEMIT("%s %u %s %s", log->type->name, lc->usr_argc + 1, | ||
| 581 | lc->uuid, lc->usr_argv_str); | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | return (r) ? 0 : (int)sz; | ||
| 585 | } | ||
| 586 | |||
| 587 | /* | ||
| 588 | * userspace_is_remote_recovering | ||
| 589 | * | ||
| 590 | * Returns: 1 if region recovering, 0 otherwise | ||
| 591 | */ | ||
| 592 | static int userspace_is_remote_recovering(struct dm_dirty_log *log, | ||
| 593 | region_t region) | ||
| 594 | { | ||
| 595 | int r; | ||
| 596 | uint64_t region64 = region; | ||
| 597 | struct log_c *lc = log->context; | ||
| 598 | static unsigned long long limit; | ||
| 599 | struct { | ||
| 600 | int64_t is_recovering; | ||
| 601 | uint64_t in_sync_hint; | ||
| 602 | } pkg; | ||
| 603 | size_t rdata_size = sizeof(pkg); | ||
| 604 | |||
| 605 | /* | ||
| 606 | * Once the mirror has been reported to be in-sync, | ||
| 607 | * it will never again ask for recovery work. So, | ||
| 608 | * we can safely say there is not a remote machine | ||
| 609 | * recovering if the device is in-sync. (in_sync_hint | ||
| 610 | * must be reset at resume time.) | ||
| 611 | */ | ||
| 612 | if (region < lc->in_sync_hint) | ||
| 613 | return 0; | ||
| 614 | else if (jiffies < limit) | ||
| 615 | return 1; | ||
| 616 | |||
| 617 | limit = jiffies + (HZ / 4); | ||
| 618 | r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_REMOTE_RECOVERING, | ||
| 619 | (char *)®ion64, sizeof(region64), | ||
| 620 | (char *)&pkg, &rdata_size); | ||
| 621 | if (r) | ||
| 622 | return 1; | ||
| 623 | |||
| 624 | lc->in_sync_hint = pkg.in_sync_hint; | ||
| 625 | |||
| 626 | return (int)pkg.is_recovering; | ||
| 627 | } | ||
| 628 | |||
| 629 | static struct dm_dirty_log_type _userspace_type = { | ||
| 630 | .name = "userspace", | ||
| 631 | .module = THIS_MODULE, | ||
| 632 | .ctr = userspace_ctr, | ||
| 633 | .dtr = userspace_dtr, | ||
| 634 | .presuspend = userspace_presuspend, | ||
| 635 | .postsuspend = userspace_postsuspend, | ||
| 636 | .resume = userspace_resume, | ||
| 637 | .get_region_size = userspace_get_region_size, | ||
| 638 | .is_clean = userspace_is_clean, | ||
| 639 | .in_sync = userspace_in_sync, | ||
| 640 | .flush = userspace_flush, | ||
| 641 | .mark_region = userspace_mark_region, | ||
| 642 | .clear_region = userspace_clear_region, | ||
| 643 | .get_resync_work = userspace_get_resync_work, | ||
| 644 | .set_region_sync = userspace_set_region_sync, | ||
| 645 | .get_sync_count = userspace_get_sync_count, | ||
| 646 | .status = userspace_status, | ||
| 647 | .is_remote_recovering = userspace_is_remote_recovering, | ||
| 648 | }; | ||
| 649 | |||
| 650 | static int __init userspace_dirty_log_init(void) | ||
| 651 | { | ||
| 652 | int r = 0; | ||
| 653 | |||
| 654 | flush_entry_pool = mempool_create(100, flush_entry_alloc, | ||
| 655 | flush_entry_free, NULL); | ||
| 656 | |||
| 657 | if (!flush_entry_pool) { | ||
| 658 | DMWARN("Unable to create flush_entry_pool: No memory."); | ||
| 659 | return -ENOMEM; | ||
| 660 | } | ||
| 661 | |||
| 662 | r = dm_ulog_tfr_init(); | ||
| 663 | if (r) { | ||
| 664 | DMWARN("Unable to initialize userspace log communications"); | ||
| 665 | mempool_destroy(flush_entry_pool); | ||
| 666 | return r; | ||
| 667 | } | ||
| 668 | |||
| 669 | r = dm_dirty_log_type_register(&_userspace_type); | ||
| 670 | if (r) { | ||
| 671 | DMWARN("Couldn't register userspace dirty log type"); | ||
| 672 | dm_ulog_tfr_exit(); | ||
| 673 | mempool_destroy(flush_entry_pool); | ||
| 674 | return r; | ||
| 675 | } | ||
| 676 | |||
| 677 | DMINFO("version 1.0.0 loaded"); | ||
| 678 | return 0; | ||
| 679 | } | ||
| 680 | |||
| 681 | static void __exit userspace_dirty_log_exit(void) | ||
| 682 | { | ||
| 683 | dm_dirty_log_type_unregister(&_userspace_type); | ||
| 684 | dm_ulog_tfr_exit(); | ||
| 685 | mempool_destroy(flush_entry_pool); | ||
| 686 | |||
| 687 | DMINFO("version 1.0.0 unloaded"); | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | module_init(userspace_dirty_log_init); | ||
| 692 | module_exit(userspace_dirty_log_exit); | ||
| 693 | |||
| 694 | MODULE_DESCRIPTION(DM_NAME " userspace dirty log link"); | ||
| 695 | MODULE_AUTHOR("Jonathan Brassow <dm-devel@redhat.com>"); | ||
| 696 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c new file mode 100644 index 000000000000..0ca1ee768a1f --- /dev/null +++ b/drivers/md/dm-log-userspace-transfer.c | |||
| @@ -0,0 +1,276 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006-2009 Red Hat, Inc. | ||
| 3 | * | ||
| 4 | * This file is released under the LGPL. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <net/sock.h> | ||
| 10 | #include <linux/workqueue.h> | ||
| 11 | #include <linux/connector.h> | ||
| 12 | #include <linux/device-mapper.h> | ||
| 13 | #include <linux/dm-log-userspace.h> | ||
| 14 | |||
| 15 | #include "dm-log-userspace-transfer.h" | ||
| 16 | |||
| 17 | static uint32_t dm_ulog_seq; | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Netlink/Connector is an unreliable protocol. How long should | ||
| 21 | * we wait for a response before assuming it was lost and retrying? | ||
| 22 | * (If we do receive a response after this time, it will be discarded | ||
| 23 | * and the response to the resent request will be waited for. | ||
| 24 | */ | ||
| 25 | #define DM_ULOG_RETRY_TIMEOUT (15 * HZ) | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Pre-allocated space for speed | ||
| 29 | */ | ||
| 30 | #define DM_ULOG_PREALLOCED_SIZE 512 | ||
| 31 | static struct cn_msg *prealloced_cn_msg; | ||
| 32 | static struct dm_ulog_request *prealloced_ulog_tfr; | ||
| 33 | |||
| 34 | static struct cb_id ulog_cn_id = { | ||
| 35 | .idx = CN_IDX_DM, | ||
| 36 | .val = CN_VAL_DM_USERSPACE_LOG | ||
| 37 | }; | ||
| 38 | |||
| 39 | static DEFINE_MUTEX(dm_ulog_lock); | ||
| 40 | |||
| 41 | struct receiving_pkg { | ||
| 42 | struct list_head list; | ||
| 43 | struct completion complete; | ||
| 44 | |||
| 45 | uint32_t seq; | ||
| 46 | |||
| 47 | int error; | ||
| 48 | size_t *data_size; | ||
| 49 | char *data; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static DEFINE_SPINLOCK(receiving_list_lock); | ||
| 53 | static struct list_head receiving_list; | ||
| 54 | |||
| 55 | static int dm_ulog_sendto_server(struct dm_ulog_request *tfr) | ||
| 56 | { | ||
| 57 | int r; | ||
| 58 | struct cn_msg *msg = prealloced_cn_msg; | ||
| 59 | |||
| 60 | memset(msg, 0, sizeof(struct cn_msg)); | ||
| 61 | |||
| 62 | msg->id.idx = ulog_cn_id.idx; | ||
| 63 | msg->id.val = ulog_cn_id.val; | ||
| 64 | msg->ack = 0; | ||
| 65 | msg->seq = tfr->seq; | ||
| 66 | msg->len = sizeof(struct dm_ulog_request) + tfr->data_size; | ||
| 67 | |||
| 68 | r = cn_netlink_send(msg, 0, gfp_any()); | ||
| 69 | |||
| 70 | return r; | ||
| 71 | } | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Parameters for this function can be either msg or tfr, but not | ||
| 75 | * both. This function fills in the reply for a waiting request. | ||
| 76 | * If just msg is given, then the reply is simply an ACK from userspace | ||
| 77 | * that the request was received. | ||
| 78 | * | ||
| 79 | * Returns: 0 on success, -ENOENT on failure | ||
| 80 | */ | ||
| 81 | static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr) | ||
| 82 | { | ||
| 83 | uint32_t rtn_seq = (msg) ? msg->seq : (tfr) ? tfr->seq : 0; | ||
| 84 | struct receiving_pkg *pkg; | ||
| 85 | |||
| 86 | /* | ||
| 87 | * The 'receiving_pkg' entries in this list are statically | ||
| 88 | * allocated on the stack in 'dm_consult_userspace'. | ||
| 89 | * Each process that is waiting for a reply from the user | ||
| 90 | * space server will have an entry in this list. | ||
| 91 | * | ||
| 92 | * We are safe to do it this way because the stack space | ||
| 93 | * is unique to each process, but still addressable by | ||
| 94 | * other processes. | ||
| 95 | */ | ||
| 96 | list_for_each_entry(pkg, &receiving_list, list) { | ||
| 97 | if (rtn_seq != pkg->seq) | ||
| 98 | continue; | ||
| 99 | |||
| 100 | if (msg) { | ||
| 101 | pkg->error = -msg->ack; | ||
| 102 | /* | ||
| 103 | * If we are trying again, we will need to know our | ||
| 104 | * storage capacity. Otherwise, along with the | ||
| 105 | * error code, we make explicit that we have no data. | ||
| 106 | */ | ||
| 107 | if (pkg->error != -EAGAIN) | ||
| 108 | *(pkg->data_size) = 0; | ||
| 109 | } else if (tfr->data_size > *(pkg->data_size)) { | ||
| 110 | DMERR("Insufficient space to receive package [%u] " | ||
| 111 | "(%u vs %lu)", tfr->request_type, | ||
| 112 | tfr->data_size, *(pkg->data_size)); | ||
| 113 | |||
| 114 | *(pkg->data_size) = 0; | ||
| 115 | pkg->error = -ENOSPC; | ||
| 116 | } else { | ||
| 117 | pkg->error = tfr->error; | ||
| 118 | memcpy(pkg->data, tfr->data, tfr->data_size); | ||
| 119 | *(pkg->data_size) = tfr->data_size; | ||
| 120 | } | ||
| 121 | complete(&pkg->complete); | ||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | return -ENOENT; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * This is the connector callback that delivers data | ||
| 130 | * that was sent from userspace. | ||
| 131 | */ | ||
| 132 | static void cn_ulog_callback(void *data) | ||
| 133 | { | ||
| 134 | struct cn_msg *msg = (struct cn_msg *)data; | ||
| 135 | struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1); | ||
| 136 | |||
| 137 | spin_lock(&receiving_list_lock); | ||
| 138 | if (msg->len == 0) | ||
| 139 | fill_pkg(msg, NULL); | ||
| 140 | else if (msg->len < sizeof(*tfr)) | ||
| 141 | DMERR("Incomplete message received (expected %u, got %u): [%u]", | ||
| 142 | (unsigned)sizeof(*tfr), msg->len, msg->seq); | ||
| 143 | else | ||
| 144 | fill_pkg(NULL, tfr); | ||
| 145 | spin_unlock(&receiving_list_lock); | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * dm_consult_userspace | ||
| 150 | * @uuid: log's uuid (must be DM_UUID_LEN in size) | ||
| 151 | * @request_type: found in include/linux/dm-log-userspace.h | ||
| 152 | * @data: data to tx to the server | ||
| 153 | * @data_size: size of data in bytes | ||
| 154 | * @rdata: place to put return data from server | ||
| 155 | * @rdata_size: value-result (amount of space given/amount of space used) | ||
| 156 | * | ||
| 157 | * rdata_size is undefined on failure. | ||
| 158 | * | ||
| 159 | * Memory used to communicate with userspace is zero'ed | ||
| 160 | * before populating to ensure that no unwanted bits leak | ||
| 161 | * from kernel space to user-space. All userspace log communications | ||
| 162 | * between kernel and user space go through this function. | ||
| 163 | * | ||
| 164 | * Returns: 0 on success, -EXXX on failure | ||
| 165 | **/ | ||
| 166 | int dm_consult_userspace(const char *uuid, int request_type, | ||
| 167 | char *data, size_t data_size, | ||
| 168 | char *rdata, size_t *rdata_size) | ||
| 169 | { | ||
| 170 | int r = 0; | ||
| 171 | size_t dummy = 0; | ||
| 172 | int overhead_size = | ||
| 173 | sizeof(struct dm_ulog_request *) + sizeof(struct cn_msg); | ||
| 174 | struct dm_ulog_request *tfr = prealloced_ulog_tfr; | ||
| 175 | struct receiving_pkg pkg; | ||
| 176 | |||
| 177 | if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) { | ||
| 178 | DMINFO("Size of tfr exceeds preallocated size"); | ||
| 179 | return -EINVAL; | ||
| 180 | } | ||
| 181 | |||
| 182 | if (!rdata_size) | ||
| 183 | rdata_size = &dummy; | ||
| 184 | resend: | ||
| 185 | /* | ||
| 186 | * We serialize the sending of requests so we can | ||
| 187 | * use the preallocated space. | ||
| 188 | */ | ||
| 189 | mutex_lock(&dm_ulog_lock); | ||
| 190 | |||
| 191 | memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size); | ||
| 192 | memcpy(tfr->uuid, uuid, DM_UUID_LEN); | ||
| 193 | tfr->seq = dm_ulog_seq++; | ||
| 194 | |||
| 195 | /* | ||
| 196 | * Must be valid request type (all other bits set to | ||
| 197 | * zero). This reserves other bits for possible future | ||
| 198 | * use. | ||
| 199 | */ | ||
| 200 | tfr->request_type = request_type & DM_ULOG_REQUEST_MASK; | ||
| 201 | |||
| 202 | tfr->data_size = data_size; | ||
| 203 | if (data && data_size) | ||
| 204 | memcpy(tfr->data, data, data_size); | ||
| 205 | |||
| 206 | memset(&pkg, 0, sizeof(pkg)); | ||
| 207 | init_completion(&pkg.complete); | ||
| 208 | pkg.seq = tfr->seq; | ||
| 209 | pkg.data_size = rdata_size; | ||
| 210 | pkg.data = rdata; | ||
| 211 | spin_lock(&receiving_list_lock); | ||
| 212 | list_add(&(pkg.list), &receiving_list); | ||
| 213 | spin_unlock(&receiving_list_lock); | ||
| 214 | |||
| 215 | r = dm_ulog_sendto_server(tfr); | ||
| 216 | |||
| 217 | mutex_unlock(&dm_ulog_lock); | ||
| 218 | |||
| 219 | if (r) { | ||
| 220 | DMERR("Unable to send log request [%u] to userspace: %d", | ||
| 221 | request_type, r); | ||
| 222 | spin_lock(&receiving_list_lock); | ||
| 223 | list_del_init(&(pkg.list)); | ||
| 224 | spin_unlock(&receiving_list_lock); | ||
| 225 | |||
| 226 | goto out; | ||
| 227 | } | ||
| 228 | |||
| 229 | r = wait_for_completion_timeout(&(pkg.complete), DM_ULOG_RETRY_TIMEOUT); | ||
| 230 | spin_lock(&receiving_list_lock); | ||
| 231 | list_del_init(&(pkg.list)); | ||
| 232 | spin_unlock(&receiving_list_lock); | ||
| 233 | if (!r) { | ||
| 234 | DMWARN("[%s] Request timed out: [%u/%u] - retrying", | ||
| 235 | (strlen(uuid) > 8) ? | ||
| 236 | (uuid + (strlen(uuid) - 8)) : (uuid), | ||
| 237 | request_type, pkg.seq); | ||
| 238 | goto resend; | ||
| 239 | } | ||
| 240 | |||
| 241 | r = pkg.error; | ||
| 242 | if (r == -EAGAIN) | ||
| 243 | goto resend; | ||
| 244 | |||
| 245 | out: | ||
| 246 | return r; | ||
| 247 | } | ||
| 248 | |||
| 249 | int dm_ulog_tfr_init(void) | ||
| 250 | { | ||
| 251 | int r; | ||
| 252 | void *prealloced; | ||
| 253 | |||
| 254 | INIT_LIST_HEAD(&receiving_list); | ||
| 255 | |||
| 256 | prealloced = kmalloc(DM_ULOG_PREALLOCED_SIZE, GFP_KERNEL); | ||
| 257 | if (!prealloced) | ||
| 258 | return -ENOMEM; | ||
| 259 | |||
| 260 | prealloced_cn_msg = prealloced; | ||
| 261 | prealloced_ulog_tfr = prealloced + sizeof(struct cn_msg); | ||
| 262 | |||
| 263 | r = cn_add_callback(&ulog_cn_id, "dmlogusr", cn_ulog_callback); | ||
| 264 | if (r) { | ||
| 265 | cn_del_callback(&ulog_cn_id); | ||
| 266 | return r; | ||
| 267 | } | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | void dm_ulog_tfr_exit(void) | ||
| 273 | { | ||
| 274 | cn_del_callback(&ulog_cn_id); | ||
| 275 | kfree(prealloced_cn_msg); | ||
| 276 | } | ||
diff --git a/drivers/md/dm-log-userspace-transfer.h b/drivers/md/dm-log-userspace-transfer.h new file mode 100644 index 000000000000..c26d8e4e2710 --- /dev/null +++ b/drivers/md/dm-log-userspace-transfer.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006-2009 Red Hat, Inc. | ||
| 3 | * | ||
| 4 | * This file is released under the LGPL. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __DM_LOG_USERSPACE_TRANSFER_H__ | ||
| 8 | #define __DM_LOG_USERSPACE_TRANSFER_H__ | ||
| 9 | |||
| 10 | #define DM_MSG_PREFIX "dm-log-userspace" | ||
| 11 | |||
| 12 | int dm_ulog_tfr_init(void); | ||
| 13 | void dm_ulog_tfr_exit(void); | ||
| 14 | int dm_consult_userspace(const char *uuid, int request_type, | ||
| 15 | char *data, size_t data_size, | ||
| 16 | char *rdata, size_t *rdata_size); | ||
| 17 | |||
| 18 | #endif /* __DM_LOG_USERSPACE_TRANSFER_H__ */ | ||
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 6fa8ccf91c70..9443896ede07 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
| @@ -412,11 +412,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
| 412 | /* | 412 | /* |
| 413 | * Buffer holds both header and bitset. | 413 | * Buffer holds both header and bitset. |
| 414 | */ | 414 | */ |
| 415 | buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + | 415 | buf_size = |
| 416 | bitset_size, | 416 | dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size, |
| 417 | ti->limits.logical_block_size); | 417 | bdev_logical_block_size(lc->header_location. |
| 418 | bdev)); | ||
| 418 | 419 | ||
| 419 | if (buf_size > dev->bdev->bd_inode->i_size) { | 420 | if (buf_size > i_size_read(dev->bdev->bd_inode)) { |
| 420 | DMWARN("log device %s too small: need %llu bytes", | 421 | DMWARN("log device %s too small: need %llu bytes", |
| 421 | dev->name, (unsigned long long)buf_size); | 422 | dev->name, (unsigned long long)buf_size); |
| 422 | kfree(lc); | 423 | kfree(lc); |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 6a386ab4f7eb..c70604a20897 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <linux/device-mapper.h> | 8 | #include <linux/device-mapper.h> |
| 9 | 9 | ||
| 10 | #include "dm-path-selector.h" | 10 | #include "dm-path-selector.h" |
| 11 | #include "dm-bio-record.h" | ||
| 12 | #include "dm-uevent.h" | 11 | #include "dm-uevent.h" |
| 13 | 12 | ||
| 14 | #include <linux/ctype.h> | 13 | #include <linux/ctype.h> |
| @@ -35,6 +34,7 @@ struct pgpath { | |||
| 35 | 34 | ||
| 36 | struct dm_path path; | 35 | struct dm_path path; |
| 37 | struct work_struct deactivate_path; | 36 | struct work_struct deactivate_path; |
| 37 | struct work_struct activate_path; | ||
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) | 40 | #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) |
| @@ -64,8 +64,6 @@ struct multipath { | |||
| 64 | spinlock_t lock; | 64 | spinlock_t lock; |
| 65 | 65 | ||
| 66 | const char *hw_handler_name; | 66 | const char *hw_handler_name; |
| 67 | struct work_struct activate_path; | ||
| 68 | struct pgpath *pgpath_to_activate; | ||
| 69 | unsigned nr_priority_groups; | 67 | unsigned nr_priority_groups; |
| 70 | struct list_head priority_groups; | 68 | struct list_head priority_groups; |
| 71 | unsigned pg_init_required; /* pg_init needs calling? */ | 69 | unsigned pg_init_required; /* pg_init needs calling? */ |
| @@ -84,7 +82,7 @@ struct multipath { | |||
| 84 | unsigned pg_init_count; /* Number of times pg_init called */ | 82 | unsigned pg_init_count; /* Number of times pg_init called */ |
| 85 | 83 | ||
| 86 | struct work_struct process_queued_ios; | 84 | struct work_struct process_queued_ios; |
| 87 | struct bio_list queued_ios; | 85 | struct list_head queued_ios; |
| 88 | unsigned queue_size; | 86 | unsigned queue_size; |
| 89 | 87 | ||
| 90 | struct work_struct trigger_event; | 88 | struct work_struct trigger_event; |
| @@ -101,7 +99,7 @@ struct multipath { | |||
| 101 | */ | 99 | */ |
| 102 | struct dm_mpath_io { | 100 | struct dm_mpath_io { |
| 103 | struct pgpath *pgpath; | 101 | struct pgpath *pgpath; |
| 104 | struct dm_bio_details details; | 102 | size_t nr_bytes; |
| 105 | }; | 103 | }; |
| 106 | 104 | ||
| 107 | typedef int (*action_fn) (struct pgpath *pgpath); | 105 | typedef int (*action_fn) (struct pgpath *pgpath); |
| @@ -128,6 +126,7 @@ static struct pgpath *alloc_pgpath(void) | |||
| 128 | if (pgpath) { | 126 | if (pgpath) { |
| 129 | pgpath->is_active = 1; | 127 | pgpath->is_active = 1; |
| 130 | INIT_WORK(&pgpath->deactivate_path, deactivate_path); | 128 | INIT_WORK(&pgpath->deactivate_path, deactivate_path); |
| 129 | INIT_WORK(&pgpath->activate_path, activate_path); | ||
| 131 | } | 130 | } |
| 132 | 131 | ||
| 133 | return pgpath; | 132 | return pgpath; |
| @@ -160,7 +159,6 @@ static struct priority_group *alloc_priority_group(void) | |||
| 160 | 159 | ||
| 161 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) | 160 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) |
| 162 | { | 161 | { |
| 163 | unsigned long flags; | ||
| 164 | struct pgpath *pgpath, *tmp; | 162 | struct pgpath *pgpath, *tmp; |
| 165 | struct multipath *m = ti->private; | 163 | struct multipath *m = ti->private; |
| 166 | 164 | ||
| @@ -169,10 +167,6 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) | |||
| 169 | if (m->hw_handler_name) | 167 | if (m->hw_handler_name) |
| 170 | scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); | 168 | scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); |
| 171 | dm_put_device(ti, pgpath->path.dev); | 169 | dm_put_device(ti, pgpath->path.dev); |
| 172 | spin_lock_irqsave(&m->lock, flags); | ||
| 173 | if (m->pgpath_to_activate == pgpath) | ||
| 174 | m->pgpath_to_activate = NULL; | ||
| 175 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 176 | free_pgpath(pgpath); | 170 | free_pgpath(pgpath); |
| 177 | } | 171 | } |
| 178 | } | 172 | } |
| @@ -198,11 +192,11 @@ static struct multipath *alloc_multipath(struct dm_target *ti) | |||
| 198 | m = kzalloc(sizeof(*m), GFP_KERNEL); | 192 | m = kzalloc(sizeof(*m), GFP_KERNEL); |
| 199 | if (m) { | 193 | if (m) { |
| 200 | INIT_LIST_HEAD(&m->priority_groups); | 194 | INIT_LIST_HEAD(&m->priority_groups); |
| 195 | INIT_LIST_HEAD(&m->queued_ios); | ||
| 201 | spin_lock_init(&m->lock); | 196 | spin_lock_init(&m->lock); |
| 202 | m->queue_io = 1; | 197 | m->queue_io = 1; |
| 203 | INIT_WORK(&m->process_queued_ios, process_queued_ios); | 198 | INIT_WORK(&m->process_queued_ios, process_queued_ios); |
| 204 | INIT_WORK(&m->trigger_event, trigger_event); | 199 | INIT_WORK(&m->trigger_event, trigger_event); |
| 205 | INIT_WORK(&m->activate_path, activate_path); | ||
| 206 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); | 200 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); |
| 207 | if (!m->mpio_pool) { | 201 | if (!m->mpio_pool) { |
| 208 | kfree(m); | 202 | kfree(m); |
| @@ -250,11 +244,12 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) | |||
| 250 | m->pg_init_count = 0; | 244 | m->pg_init_count = 0; |
| 251 | } | 245 | } |
| 252 | 246 | ||
| 253 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) | 247 | static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg, |
| 248 | size_t nr_bytes) | ||
| 254 | { | 249 | { |
| 255 | struct dm_path *path; | 250 | struct dm_path *path; |
| 256 | 251 | ||
| 257 | path = pg->ps.type->select_path(&pg->ps, &m->repeat_count); | 252 | path = pg->ps.type->select_path(&pg->ps, &m->repeat_count, nr_bytes); |
| 258 | if (!path) | 253 | if (!path) |
| 259 | return -ENXIO; | 254 | return -ENXIO; |
| 260 | 255 | ||
| @@ -266,7 +261,7 @@ static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) | |||
| 266 | return 0; | 261 | return 0; |
| 267 | } | 262 | } |
| 268 | 263 | ||
| 269 | static void __choose_pgpath(struct multipath *m) | 264 | static void __choose_pgpath(struct multipath *m, size_t nr_bytes) |
| 270 | { | 265 | { |
| 271 | struct priority_group *pg; | 266 | struct priority_group *pg; |
| 272 | unsigned bypassed = 1; | 267 | unsigned bypassed = 1; |
| @@ -278,12 +273,12 @@ static void __choose_pgpath(struct multipath *m) | |||
| 278 | if (m->next_pg) { | 273 | if (m->next_pg) { |
| 279 | pg = m->next_pg; | 274 | pg = m->next_pg; |
| 280 | m->next_pg = NULL; | 275 | m->next_pg = NULL; |
| 281 | if (!__choose_path_in_pg(m, pg)) | 276 | if (!__choose_path_in_pg(m, pg, nr_bytes)) |
| 282 | return; | 277 | return; |
| 283 | } | 278 | } |
| 284 | 279 | ||
| 285 | /* Don't change PG until it has no remaining paths */ | 280 | /* Don't change PG until it has no remaining paths */ |
| 286 | if (m->current_pg && !__choose_path_in_pg(m, m->current_pg)) | 281 | if (m->current_pg && !__choose_path_in_pg(m, m->current_pg, nr_bytes)) |
| 287 | return; | 282 | return; |
| 288 | 283 | ||
| 289 | /* | 284 | /* |
| @@ -295,7 +290,7 @@ static void __choose_pgpath(struct multipath *m) | |||
| 295 | list_for_each_entry(pg, &m->priority_groups, list) { | 290 | list_for_each_entry(pg, &m->priority_groups, list) { |
| 296 | if (pg->bypassed == bypassed) | 291 | if (pg->bypassed == bypassed) |
| 297 | continue; | 292 | continue; |
| 298 | if (!__choose_path_in_pg(m, pg)) | 293 | if (!__choose_path_in_pg(m, pg, nr_bytes)) |
| 299 | return; | 294 | return; |
| 300 | } | 295 | } |
| 301 | } while (bypassed--); | 296 | } while (bypassed--); |
| @@ -322,19 +317,21 @@ static int __must_push_back(struct multipath *m) | |||
| 322 | dm_noflush_suspending(m->ti)); | 317 | dm_noflush_suspending(m->ti)); |
| 323 | } | 318 | } |
| 324 | 319 | ||
| 325 | static int map_io(struct multipath *m, struct bio *bio, | 320 | static int map_io(struct multipath *m, struct request *clone, |
| 326 | struct dm_mpath_io *mpio, unsigned was_queued) | 321 | struct dm_mpath_io *mpio, unsigned was_queued) |
| 327 | { | 322 | { |
| 328 | int r = DM_MAPIO_REMAPPED; | 323 | int r = DM_MAPIO_REMAPPED; |
| 324 | size_t nr_bytes = blk_rq_bytes(clone); | ||
| 329 | unsigned long flags; | 325 | unsigned long flags; |
| 330 | struct pgpath *pgpath; | 326 | struct pgpath *pgpath; |
| 327 | struct block_device *bdev; | ||
| 331 | 328 | ||
| 332 | spin_lock_irqsave(&m->lock, flags); | 329 | spin_lock_irqsave(&m->lock, flags); |
| 333 | 330 | ||
| 334 | /* Do we need to select a new pgpath? */ | 331 | /* Do we need to select a new pgpath? */ |
| 335 | if (!m->current_pgpath || | 332 | if (!m->current_pgpath || |
| 336 | (!m->queue_io && (m->repeat_count && --m->repeat_count == 0))) | 333 | (!m->queue_io && (m->repeat_count && --m->repeat_count == 0))) |
| 337 | __choose_pgpath(m); | 334 | __choose_pgpath(m, nr_bytes); |
| 338 | 335 | ||
| 339 | pgpath = m->current_pgpath; | 336 | pgpath = m->current_pgpath; |
| 340 | 337 | ||
| @@ -344,21 +341,28 @@ static int map_io(struct multipath *m, struct bio *bio, | |||
| 344 | if ((pgpath && m->queue_io) || | 341 | if ((pgpath && m->queue_io) || |
| 345 | (!pgpath && m->queue_if_no_path)) { | 342 | (!pgpath && m->queue_if_no_path)) { |
| 346 | /* Queue for the daemon to resubmit */ | 343 | /* Queue for the daemon to resubmit */ |
| 347 | bio_list_add(&m->queued_ios, bio); | 344 | list_add_tail(&clone->queuelist, &m->queued_ios); |
| 348 | m->queue_size++; | 345 | m->queue_size++; |
| 349 | if ((m->pg_init_required && !m->pg_init_in_progress) || | 346 | if ((m->pg_init_required && !m->pg_init_in_progress) || |
| 350 | !m->queue_io) | 347 | !m->queue_io) |
| 351 | queue_work(kmultipathd, &m->process_queued_ios); | 348 | queue_work(kmultipathd, &m->process_queued_ios); |
| 352 | pgpath = NULL; | 349 | pgpath = NULL; |
| 353 | r = DM_MAPIO_SUBMITTED; | 350 | r = DM_MAPIO_SUBMITTED; |
| 354 | } else if (pgpath) | 351 | } else if (pgpath) { |
| 355 | bio->bi_bdev = pgpath->path.dev->bdev; | 352 | bdev = pgpath->path.dev->bdev; |
| 356 | else if (__must_push_back(m)) | 353 | clone->q = bdev_get_queue(bdev); |
| 354 | clone->rq_disk = bdev->bd_disk; | ||
| 355 | } else if (__must_push_back(m)) | ||
| 357 | r = DM_MAPIO_REQUEUE; | 356 | r = DM_MAPIO_REQUEUE; |
| 358 | else | 357 | else |
| 359 | r = -EIO; /* Failed */ | 358 | r = -EIO; /* Failed */ |
| 360 | 359 | ||
| 361 | mpio->pgpath = pgpath; | 360 | mpio->pgpath = pgpath; |
| 361 | mpio->nr_bytes = nr_bytes; | ||
| 362 | |||
| 363 | if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io) | ||
| 364 | pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path, | ||
| 365 | nr_bytes); | ||
| 362 | 366 | ||
| 363 | spin_unlock_irqrestore(&m->lock, flags); | 367 | spin_unlock_irqrestore(&m->lock, flags); |
| 364 | 368 | ||
| @@ -396,30 +400,31 @@ static void dispatch_queued_ios(struct multipath *m) | |||
| 396 | { | 400 | { |
| 397 | int r; | 401 | int r; |
| 398 | unsigned long flags; | 402 | unsigned long flags; |
| 399 | struct bio *bio = NULL, *next; | ||
| 400 | struct dm_mpath_io *mpio; | 403 | struct dm_mpath_io *mpio; |
| 401 | union map_info *info; | 404 | union map_info *info; |
| 405 | struct request *clone, *n; | ||
| 406 | LIST_HEAD(cl); | ||
| 402 | 407 | ||
| 403 | spin_lock_irqsave(&m->lock, flags); | 408 | spin_lock_irqsave(&m->lock, flags); |
| 404 | bio = bio_list_get(&m->queued_ios); | 409 | list_splice_init(&m->queued_ios, &cl); |
| 405 | spin_unlock_irqrestore(&m->lock, flags); | 410 | spin_unlock_irqrestore(&m->lock, flags); |
| 406 | 411 | ||
| 407 | while (bio) { | 412 | list_for_each_entry_safe(clone, n, &cl, queuelist) { |
| 408 | next = bio->bi_next; | 413 | list_del_init(&clone->queuelist); |
| 409 | bio->bi_next = NULL; | ||
| 410 | 414 | ||
| 411 | info = dm_get_mapinfo(bio); | 415 | info = dm_get_rq_mapinfo(clone); |
| 412 | mpio = info->ptr; | 416 | mpio = info->ptr; |
| 413 | 417 | ||
| 414 | r = map_io(m, bio, mpio, 1); | 418 | r = map_io(m, clone, mpio, 1); |
| 415 | if (r < 0) | 419 | if (r < 0) { |
| 416 | bio_endio(bio, r); | 420 | mempool_free(mpio, m->mpio_pool); |
| 417 | else if (r == DM_MAPIO_REMAPPED) | 421 | dm_kill_unmapped_request(clone, r); |
| 418 | generic_make_request(bio); | 422 | } else if (r == DM_MAPIO_REMAPPED) |
| 419 | else if (r == DM_MAPIO_REQUEUE) | 423 | dm_dispatch_request(clone); |
| 420 | bio_endio(bio, -EIO); | 424 | else if (r == DM_MAPIO_REQUEUE) { |
| 421 | 425 | mempool_free(mpio, m->mpio_pool); | |
| 422 | bio = next; | 426 | dm_requeue_unmapped_request(clone); |
| 427 | } | ||
| 423 | } | 428 | } |
| 424 | } | 429 | } |
| 425 | 430 | ||
| @@ -427,8 +432,8 @@ static void process_queued_ios(struct work_struct *work) | |||
| 427 | { | 432 | { |
| 428 | struct multipath *m = | 433 | struct multipath *m = |
| 429 | container_of(work, struct multipath, process_queued_ios); | 434 | container_of(work, struct multipath, process_queued_ios); |
| 430 | struct pgpath *pgpath = NULL; | 435 | struct pgpath *pgpath = NULL, *tmp; |
| 431 | unsigned init_required = 0, must_queue = 1; | 436 | unsigned must_queue = 1; |
| 432 | unsigned long flags; | 437 | unsigned long flags; |
| 433 | 438 | ||
| 434 | spin_lock_irqsave(&m->lock, flags); | 439 | spin_lock_irqsave(&m->lock, flags); |
| @@ -437,7 +442,7 @@ static void process_queued_ios(struct work_struct *work) | |||
| 437 | goto out; | 442 | goto out; |
| 438 | 443 | ||
| 439 | if (!m->current_pgpath) | 444 | if (!m->current_pgpath) |
| 440 | __choose_pgpath(m); | 445 | __choose_pgpath(m, 0); |
| 441 | 446 | ||
| 442 | pgpath = m->current_pgpath; | 447 | pgpath = m->current_pgpath; |
| 443 | 448 | ||
| @@ -446,19 +451,15 @@ static void process_queued_ios(struct work_struct *work) | |||
| 446 | must_queue = 0; | 451 | must_queue = 0; |
| 447 | 452 | ||
| 448 | if (m->pg_init_required && !m->pg_init_in_progress && pgpath) { | 453 | if (m->pg_init_required && !m->pg_init_in_progress && pgpath) { |
| 449 | m->pgpath_to_activate = pgpath; | ||
| 450 | m->pg_init_count++; | 454 | m->pg_init_count++; |
| 451 | m->pg_init_required = 0; | 455 | m->pg_init_required = 0; |
| 452 | m->pg_init_in_progress = 1; | 456 | list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) { |
| 453 | init_required = 1; | 457 | if (queue_work(kmpath_handlerd, &tmp->activate_path)) |
| 458 | m->pg_init_in_progress++; | ||
| 459 | } | ||
| 454 | } | 460 | } |
| 455 | |||
| 456 | out: | 461 | out: |
| 457 | spin_unlock_irqrestore(&m->lock, flags); | 462 | spin_unlock_irqrestore(&m->lock, flags); |
| 458 | |||
| 459 | if (init_required) | ||
| 460 | queue_work(kmpath_handlerd, &m->activate_path); | ||
| 461 | |||
| 462 | if (!must_queue) | 463 | if (!must_queue) |
| 463 | dispatch_queued_ios(m); | 464 | dispatch_queued_ios(m); |
| 464 | } | 465 | } |
| @@ -553,6 +554,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg, | |||
| 553 | return -EINVAL; | 554 | return -EINVAL; |
| 554 | } | 555 | } |
| 555 | 556 | ||
| 557 | if (ps_argc > as->argc) { | ||
| 558 | dm_put_path_selector(pst); | ||
| 559 | ti->error = "not enough arguments for path selector"; | ||
| 560 | return -EINVAL; | ||
| 561 | } | ||
| 562 | |||
| 556 | r = pst->create(&pg->ps, ps_argc, as->argv); | 563 | r = pst->create(&pg->ps, ps_argc, as->argv); |
| 557 | if (r) { | 564 | if (r) { |
| 558 | dm_put_path_selector(pst); | 565 | dm_put_path_selector(pst); |
| @@ -591,9 +598,20 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | |||
| 591 | } | 598 | } |
| 592 | 599 | ||
| 593 | if (m->hw_handler_name) { | 600 | if (m->hw_handler_name) { |
| 594 | r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev), | 601 | struct request_queue *q = bdev_get_queue(p->path.dev->bdev); |
| 595 | m->hw_handler_name); | 602 | |
| 603 | r = scsi_dh_attach(q, m->hw_handler_name); | ||
| 604 | if (r == -EBUSY) { | ||
| 605 | /* | ||
| 606 | * Already attached to different hw_handler, | ||
| 607 | * try to reattach with correct one. | ||
| 608 | */ | ||
| 609 | scsi_dh_detach(q); | ||
| 610 | r = scsi_dh_attach(q, m->hw_handler_name); | ||
| 611 | } | ||
| 612 | |||
| 596 | if (r < 0) { | 613 | if (r < 0) { |
| 614 | ti->error = "error attaching hardware handler"; | ||
| 597 | dm_put_device(ti, p->path.dev); | 615 | dm_put_device(ti, p->path.dev); |
| 598 | goto bad; | 616 | goto bad; |
| 599 | } | 617 | } |
| @@ -699,6 +717,11 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) | |||
| 699 | if (!hw_argc) | 717 | if (!hw_argc) |
| 700 | return 0; | 718 | return 0; |
| 701 | 719 | ||
| 720 | if (hw_argc > as->argc) { | ||
| 721 | ti->error = "not enough arguments for hardware handler"; | ||
| 722 | return -EINVAL; | ||
| 723 | } | ||
| 724 | |||
| 702 | m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL); | 725 | m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL); |
| 703 | request_module("scsi_dh_%s", m->hw_handler_name); | 726 | request_module("scsi_dh_%s", m->hw_handler_name); |
| 704 | if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { | 727 | if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { |
| @@ -823,6 +846,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
| 823 | goto bad; | 846 | goto bad; |
| 824 | } | 847 | } |
| 825 | 848 | ||
| 849 | ti->num_flush_requests = 1; | ||
| 850 | |||
| 826 | return 0; | 851 | return 0; |
| 827 | 852 | ||
| 828 | bad: | 853 | bad: |
| @@ -836,25 +861,29 @@ static void multipath_dtr(struct dm_target *ti) | |||
| 836 | 861 | ||
| 837 | flush_workqueue(kmpath_handlerd); | 862 | flush_workqueue(kmpath_handlerd); |
| 838 | flush_workqueue(kmultipathd); | 863 | flush_workqueue(kmultipathd); |
| 864 | flush_scheduled_work(); | ||
| 839 | free_multipath(m); | 865 | free_multipath(m); |
| 840 | } | 866 | } |
| 841 | 867 | ||
| 842 | /* | 868 | /* |
| 843 | * Map bios, recording original fields for later in case we have to resubmit | 869 | * Map cloned requests |
| 844 | */ | 870 | */ |
| 845 | static int multipath_map(struct dm_target *ti, struct bio *bio, | 871 | static int multipath_map(struct dm_target *ti, struct request *clone, |
| 846 | union map_info *map_context) | 872 | union map_info *map_context) |
| 847 | { | 873 | { |
| 848 | int r; | 874 | int r; |
| 849 | struct dm_mpath_io *mpio; | 875 | struct dm_mpath_io *mpio; |
| 850 | struct multipath *m = (struct multipath *) ti->private; | 876 | struct multipath *m = (struct multipath *) ti->private; |
| 851 | 877 | ||
| 852 | mpio = mempool_alloc(m->mpio_pool, GFP_NOIO); | 878 | mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC); |
| 853 | dm_bio_record(&mpio->details, bio); | 879 | if (!mpio) |
| 880 | /* ENOMEM, requeue */ | ||
| 881 | return DM_MAPIO_REQUEUE; | ||
| 882 | memset(mpio, 0, sizeof(*mpio)); | ||
| 854 | 883 | ||
| 855 | map_context->ptr = mpio; | 884 | map_context->ptr = mpio; |
| 856 | bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT); | 885 | clone->cmd_flags |= REQ_FAILFAST_TRANSPORT; |
| 857 | r = map_io(m, bio, mpio, 0); | 886 | r = map_io(m, clone, mpio, 0); |
| 858 | if (r < 0 || r == DM_MAPIO_REQUEUE) | 887 | if (r < 0 || r == DM_MAPIO_REQUEUE) |
| 859 | mempool_free(mpio, m->mpio_pool); | 888 | mempool_free(mpio, m->mpio_pool); |
| 860 | 889 | ||
| @@ -924,9 +953,13 @@ static int reinstate_path(struct pgpath *pgpath) | |||
| 924 | 953 | ||
| 925 | pgpath->is_active = 1; | 954 | pgpath->is_active = 1; |
| 926 | 955 | ||
| 927 | m->current_pgpath = NULL; | 956 | if (!m->nr_valid_paths++ && m->queue_size) { |
| 928 | if (!m->nr_valid_paths++ && m->queue_size) | 957 | m->current_pgpath = NULL; |
| 929 | queue_work(kmultipathd, &m->process_queued_ios); | 958 | queue_work(kmultipathd, &m->process_queued_ios); |
| 959 | } else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) { | ||
| 960 | if (queue_work(kmpath_handlerd, &pgpath->activate_path)) | ||
| 961 | m->pg_init_in_progress++; | ||
| 962 | } | ||
| 930 | 963 | ||
| 931 | dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, | 964 | dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, |
| 932 | pgpath->path.dev->name, m->nr_valid_paths); | 965 | pgpath->path.dev->name, m->nr_valid_paths); |
| @@ -1102,87 +1135,70 @@ static void pg_init_done(struct dm_path *path, int errors) | |||
| 1102 | 1135 | ||
| 1103 | spin_lock_irqsave(&m->lock, flags); | 1136 | spin_lock_irqsave(&m->lock, flags); |
| 1104 | if (errors) { | 1137 | if (errors) { |
| 1105 | DMERR("Could not failover device. Error %d.", errors); | 1138 | if (pgpath == m->current_pgpath) { |
| 1106 | m->current_pgpath = NULL; | 1139 | DMERR("Could not failover device. Error %d.", errors); |
| 1107 | m->current_pg = NULL; | 1140 | m->current_pgpath = NULL; |
| 1141 | m->current_pg = NULL; | ||
| 1142 | } | ||
| 1108 | } else if (!m->pg_init_required) { | 1143 | } else if (!m->pg_init_required) { |
| 1109 | m->queue_io = 0; | 1144 | m->queue_io = 0; |
| 1110 | pg->bypassed = 0; | 1145 | pg->bypassed = 0; |
| 1111 | } | 1146 | } |
| 1112 | 1147 | ||
| 1113 | m->pg_init_in_progress = 0; | 1148 | m->pg_init_in_progress--; |
| 1114 | queue_work(kmultipathd, &m->process_queued_ios); | 1149 | if (!m->pg_init_in_progress) |
| 1150 | queue_work(kmultipathd, &m->process_queued_ios); | ||
| 1115 | spin_unlock_irqrestore(&m->lock, flags); | 1151 | spin_unlock_irqrestore(&m->lock, flags); |
| 1116 | } | 1152 | } |
| 1117 | 1153 | ||
| 1118 | static void activate_path(struct work_struct *work) | 1154 | static void activate_path(struct work_struct *work) |
| 1119 | { | 1155 | { |
| 1120 | int ret; | 1156 | int ret; |
| 1121 | struct multipath *m = | 1157 | struct pgpath *pgpath = |
| 1122 | container_of(work, struct multipath, activate_path); | 1158 | container_of(work, struct pgpath, activate_path); |
| 1123 | struct dm_path *path; | ||
| 1124 | unsigned long flags; | ||
| 1125 | 1159 | ||
| 1126 | spin_lock_irqsave(&m->lock, flags); | 1160 | ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev)); |
| 1127 | path = &m->pgpath_to_activate->path; | 1161 | pg_init_done(&pgpath->path, ret); |
| 1128 | m->pgpath_to_activate = NULL; | ||
| 1129 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1130 | if (!path) | ||
| 1131 | return; | ||
| 1132 | ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev)); | ||
| 1133 | pg_init_done(path, ret); | ||
| 1134 | } | 1162 | } |
| 1135 | 1163 | ||
| 1136 | /* | 1164 | /* |
| 1137 | * end_io handling | 1165 | * end_io handling |
| 1138 | */ | 1166 | */ |
| 1139 | static int do_end_io(struct multipath *m, struct bio *bio, | 1167 | static int do_end_io(struct multipath *m, struct request *clone, |
| 1140 | int error, struct dm_mpath_io *mpio) | 1168 | int error, struct dm_mpath_io *mpio) |
| 1141 | { | 1169 | { |
| 1170 | /* | ||
| 1171 | * We don't queue any clone request inside the multipath target | ||
| 1172 | * during end I/O handling, since those clone requests don't have | ||
| 1173 | * bio clones. If we queue them inside the multipath target, | ||
| 1174 | * we need to make bio clones, that requires memory allocation. | ||
| 1175 | * (See drivers/md/dm.c:end_clone_bio() about why the clone requests | ||
| 1176 | * don't have bio clones.) | ||
| 1177 | * Instead of queueing the clone request here, we queue the original | ||
| 1178 | * request into dm core, which will remake a clone request and | ||
| 1179 | * clone bios for it and resubmit it later. | ||
| 1180 | */ | ||
| 1181 | int r = DM_ENDIO_REQUEUE; | ||
| 1142 | unsigned long flags; | 1182 | unsigned long flags; |
| 1143 | 1183 | ||
| 1144 | if (!error) | 1184 | if (!error && !clone->errors) |
| 1145 | return 0; /* I/O complete */ | 1185 | return 0; /* I/O complete */ |
| 1146 | 1186 | ||
| 1147 | if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio)) | ||
| 1148 | return error; | ||
| 1149 | |||
| 1150 | if (error == -EOPNOTSUPP) | 1187 | if (error == -EOPNOTSUPP) |
| 1151 | return error; | 1188 | return error; |
| 1152 | 1189 | ||
| 1153 | spin_lock_irqsave(&m->lock, flags); | ||
| 1154 | if (!m->nr_valid_paths) { | ||
| 1155 | if (__must_push_back(m)) { | ||
| 1156 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1157 | return DM_ENDIO_REQUEUE; | ||
| 1158 | } else if (!m->queue_if_no_path) { | ||
| 1159 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1160 | return -EIO; | ||
| 1161 | } else { | ||
| 1162 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1163 | goto requeue; | ||
| 1164 | } | ||
| 1165 | } | ||
| 1166 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1167 | |||
| 1168 | if (mpio->pgpath) | 1190 | if (mpio->pgpath) |
| 1169 | fail_path(mpio->pgpath); | 1191 | fail_path(mpio->pgpath); |
| 1170 | 1192 | ||
| 1171 | requeue: | ||
| 1172 | dm_bio_restore(&mpio->details, bio); | ||
| 1173 | |||
| 1174 | /* queue for the daemon to resubmit or fail */ | ||
| 1175 | spin_lock_irqsave(&m->lock, flags); | 1193 | spin_lock_irqsave(&m->lock, flags); |
| 1176 | bio_list_add(&m->queued_ios, bio); | 1194 | if (!m->nr_valid_paths && !m->queue_if_no_path && !__must_push_back(m)) |
| 1177 | m->queue_size++; | 1195 | r = -EIO; |
| 1178 | if (!m->queue_io) | ||
| 1179 | queue_work(kmultipathd, &m->process_queued_ios); | ||
| 1180 | spin_unlock_irqrestore(&m->lock, flags); | 1196 | spin_unlock_irqrestore(&m->lock, flags); |
| 1181 | 1197 | ||
| 1182 | return DM_ENDIO_INCOMPLETE; /* io not complete */ | 1198 | return r; |
| 1183 | } | 1199 | } |
| 1184 | 1200 | ||
| 1185 | static int multipath_end_io(struct dm_target *ti, struct bio *bio, | 1201 | static int multipath_end_io(struct dm_target *ti, struct request *clone, |
| 1186 | int error, union map_info *map_context) | 1202 | int error, union map_info *map_context) |
| 1187 | { | 1203 | { |
| 1188 | struct multipath *m = ti->private; | 1204 | struct multipath *m = ti->private; |
| @@ -1191,14 +1207,13 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio, | |||
| 1191 | struct path_selector *ps; | 1207 | struct path_selector *ps; |
| 1192 | int r; | 1208 | int r; |
| 1193 | 1209 | ||
| 1194 | r = do_end_io(m, bio, error, mpio); | 1210 | r = do_end_io(m, clone, error, mpio); |
| 1195 | if (pgpath) { | 1211 | if (pgpath) { |
| 1196 | ps = &pgpath->pg->ps; | 1212 | ps = &pgpath->pg->ps; |
| 1197 | if (ps->type->end_io) | 1213 | if (ps->type->end_io) |
| 1198 | ps->type->end_io(ps, &pgpath->path); | 1214 | ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); |
| 1199 | } | 1215 | } |
| 1200 | if (r != DM_ENDIO_INCOMPLETE) | 1216 | mempool_free(mpio, m->mpio_pool); |
| 1201 | mempool_free(mpio, m->mpio_pool); | ||
| 1202 | 1217 | ||
| 1203 | return r; | 1218 | return r; |
| 1204 | } | 1219 | } |
| @@ -1411,7 +1426,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, | |||
| 1411 | spin_lock_irqsave(&m->lock, flags); | 1426 | spin_lock_irqsave(&m->lock, flags); |
| 1412 | 1427 | ||
| 1413 | if (!m->current_pgpath) | 1428 | if (!m->current_pgpath) |
| 1414 | __choose_pgpath(m); | 1429 | __choose_pgpath(m, 0); |
| 1415 | 1430 | ||
| 1416 | if (m->current_pgpath) { | 1431 | if (m->current_pgpath) { |
| 1417 | bdev = m->current_pgpath->path.dev->bdev; | 1432 | bdev = m->current_pgpath->path.dev->bdev; |
| @@ -1428,22 +1443,113 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, | |||
| 1428 | return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); | 1443 | return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
| 1429 | } | 1444 | } |
| 1430 | 1445 | ||
| 1446 | static int multipath_iterate_devices(struct dm_target *ti, | ||
| 1447 | iterate_devices_callout_fn fn, void *data) | ||
| 1448 | { | ||
| 1449 | struct multipath *m = ti->private; | ||
| 1450 | struct priority_group *pg; | ||
| 1451 | struct pgpath *p; | ||
| 1452 | int ret = 0; | ||
| 1453 | |||
| 1454 | list_for_each_entry(pg, &m->priority_groups, list) { | ||
| 1455 | list_for_each_entry(p, &pg->pgpaths, list) { | ||
| 1456 | ret = fn(ti, p->path.dev, ti->begin, data); | ||
| 1457 | if (ret) | ||
| 1458 | goto out; | ||
| 1459 | } | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | out: | ||
| 1463 | return ret; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static int __pgpath_busy(struct pgpath *pgpath) | ||
| 1467 | { | ||
| 1468 | struct request_queue *q = bdev_get_queue(pgpath->path.dev->bdev); | ||
| 1469 | |||
| 1470 | return dm_underlying_device_busy(q); | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | /* | ||
| 1474 | * We return "busy", only when we can map I/Os but underlying devices | ||
| 1475 | * are busy (so even if we map I/Os now, the I/Os will wait on | ||
| 1476 | * the underlying queue). | ||
| 1477 | * In other words, if we want to kill I/Os or queue them inside us | ||
| 1478 | * due to map unavailability, we don't return "busy". Otherwise, | ||
| 1479 | * dm core won't give us the I/Os and we can't do what we want. | ||
| 1480 | */ | ||
| 1481 | static int multipath_busy(struct dm_target *ti) | ||
| 1482 | { | ||
| 1483 | int busy = 0, has_active = 0; | ||
| 1484 | struct multipath *m = ti->private; | ||
| 1485 | struct priority_group *pg; | ||
| 1486 | struct pgpath *pgpath; | ||
| 1487 | unsigned long flags; | ||
| 1488 | |||
| 1489 | spin_lock_irqsave(&m->lock, flags); | ||
| 1490 | |||
| 1491 | /* Guess which priority_group will be used at next mapping time */ | ||
| 1492 | if (unlikely(!m->current_pgpath && m->next_pg)) | ||
| 1493 | pg = m->next_pg; | ||
| 1494 | else if (likely(m->current_pg)) | ||
| 1495 | pg = m->current_pg; | ||
| 1496 | else | ||
| 1497 | /* | ||
| 1498 | * We don't know which pg will be used at next mapping time. | ||
| 1499 | * We don't call __choose_pgpath() here to avoid to trigger | ||
| 1500 | * pg_init just by busy checking. | ||
| 1501 | * So we don't know whether underlying devices we will be using | ||
| 1502 | * at next mapping time are busy or not. Just try mapping. | ||
| 1503 | */ | ||
| 1504 | goto out; | ||
| 1505 | |||
| 1506 | /* | ||
| 1507 | * If there is one non-busy active path at least, the path selector | ||
| 1508 | * will be able to select it. So we consider such a pg as not busy. | ||
| 1509 | */ | ||
| 1510 | busy = 1; | ||
| 1511 | list_for_each_entry(pgpath, &pg->pgpaths, list) | ||
| 1512 | if (pgpath->is_active) { | ||
| 1513 | has_active = 1; | ||
| 1514 | |||
| 1515 | if (!__pgpath_busy(pgpath)) { | ||
| 1516 | busy = 0; | ||
| 1517 | break; | ||
| 1518 | } | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | if (!has_active) | ||
| 1522 | /* | ||
| 1523 | * No active path in this pg, so this pg won't be used and | ||
| 1524 | * the current_pg will be changed at next mapping time. | ||
| 1525 | * We need to try mapping to determine it. | ||
| 1526 | */ | ||
| 1527 | busy = 0; | ||
| 1528 | |||
| 1529 | out: | ||
| 1530 | spin_unlock_irqrestore(&m->lock, flags); | ||
| 1531 | |||
| 1532 | return busy; | ||
| 1533 | } | ||
| 1534 | |||
| 1431 | /*----------------------------------------------------------------- | 1535 | /*----------------------------------------------------------------- |
| 1432 | * Module setup | 1536 | * Module setup |
| 1433 | *---------------------------------------------------------------*/ | 1537 | *---------------------------------------------------------------*/ |
| 1434 | static struct target_type multipath_target = { | 1538 | static struct target_type multipath_target = { |
| 1435 | .name = "multipath", | 1539 | .name = "multipath", |
| 1436 | .version = {1, 0, 5}, | 1540 | .version = {1, 1, 0}, |
| 1437 | .module = THIS_MODULE, | 1541 | .module = THIS_MODULE, |
| 1438 | .ctr = multipath_ctr, | 1542 | .ctr = multipath_ctr, |
| 1439 | .dtr = multipath_dtr, | 1543 | .dtr = multipath_dtr, |
| 1440 | .map = multipath_map, | 1544 | .map_rq = multipath_map, |
| 1441 | .end_io = multipath_end_io, | 1545 | .rq_end_io = multipath_end_io, |
| 1442 | .presuspend = multipath_presuspend, | 1546 | .presuspend = multipath_presuspend, |
| 1443 | .resume = multipath_resume, | 1547 | .resume = multipath_resume, |
| 1444 | .status = multipath_status, | 1548 | .status = multipath_status, |
| 1445 | .message = multipath_message, | 1549 | .message = multipath_message, |
| 1446 | .ioctl = multipath_ioctl, | 1550 | .ioctl = multipath_ioctl, |
| 1551 | .iterate_devices = multipath_iterate_devices, | ||
| 1552 | .busy = multipath_busy, | ||
| 1447 | }; | 1553 | }; |
| 1448 | 1554 | ||
| 1449 | static int __init dm_multipath_init(void) | 1555 | static int __init dm_multipath_init(void) |
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h index 27357b85d73d..e7d1fa8b0459 100644 --- a/drivers/md/dm-path-selector.h +++ b/drivers/md/dm-path-selector.h | |||
| @@ -56,7 +56,8 @@ struct path_selector_type { | |||
| 56 | * the path fails. | 56 | * the path fails. |
| 57 | */ | 57 | */ |
| 58 | struct dm_path *(*select_path) (struct path_selector *ps, | 58 | struct dm_path *(*select_path) (struct path_selector *ps, |
| 59 | unsigned *repeat_count); | 59 | unsigned *repeat_count, |
| 60 | size_t nr_bytes); | ||
| 60 | 61 | ||
| 61 | /* | 62 | /* |
| 62 | * Notify the selector that a path has failed. | 63 | * Notify the selector that a path has failed. |
| @@ -75,7 +76,10 @@ struct path_selector_type { | |||
| 75 | int (*status) (struct path_selector *ps, struct dm_path *path, | 76 | int (*status) (struct path_selector *ps, struct dm_path *path, |
| 76 | status_type_t type, char *result, unsigned int maxlen); | 77 | status_type_t type, char *result, unsigned int maxlen); |
| 77 | 78 | ||
| 78 | int (*end_io) (struct path_selector *ps, struct dm_path *path); | 79 | int (*start_io) (struct path_selector *ps, struct dm_path *path, |
| 80 | size_t nr_bytes); | ||
| 81 | int (*end_io) (struct path_selector *ps, struct dm_path *path, | ||
| 82 | size_t nr_bytes); | ||
| 79 | }; | 83 | }; |
| 80 | 84 | ||
| 81 | /* Register a path selector */ | 85 | /* Register a path selector */ |
diff --git a/drivers/md/dm-queue-length.c b/drivers/md/dm-queue-length.c new file mode 100644 index 000000000000..f92b6cea9d9c --- /dev/null +++ b/drivers/md/dm-queue-length.c | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2004-2005 IBM Corp. All Rights Reserved. | ||
| 3 | * Copyright (C) 2006-2009 NEC Corporation. | ||
| 4 | * | ||
| 5 | * dm-queue-length.c | ||
| 6 | * | ||
| 7 | * Module Author: Stefan Bader, IBM | ||
| 8 | * Modified by: Kiyoshi Ueda, NEC | ||
| 9 | * | ||
| 10 | * This file is released under the GPL. | ||
| 11 | * | ||
| 12 | * queue-length path selector - choose a path with the least number of | ||
| 13 | * in-flight I/Os. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include "dm.h" | ||
| 17 | #include "dm-path-selector.h" | ||
| 18 | |||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/ctype.h> | ||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <asm/atomic.h> | ||
| 24 | |||
| 25 | #define DM_MSG_PREFIX "multipath queue-length" | ||
| 26 | #define QL_MIN_IO 128 | ||
| 27 | #define QL_VERSION "0.1.0" | ||
| 28 | |||
| 29 | struct selector { | ||
| 30 | struct list_head valid_paths; | ||
| 31 | struct list_head failed_paths; | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct path_info { | ||
| 35 | struct list_head list; | ||
| 36 | struct dm_path *path; | ||
| 37 | unsigned repeat_count; | ||
| 38 | atomic_t qlen; /* the number of in-flight I/Os */ | ||
| 39 | }; | ||
| 40 | |||
| 41 | static struct selector *alloc_selector(void) | ||
| 42 | { | ||
| 43 | struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
| 44 | |||
| 45 | if (s) { | ||
| 46 | INIT_LIST_HEAD(&s->valid_paths); | ||
| 47 | INIT_LIST_HEAD(&s->failed_paths); | ||
| 48 | } | ||
| 49 | |||
| 50 | return s; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int ql_create(struct path_selector *ps, unsigned argc, char **argv) | ||
| 54 | { | ||
| 55 | struct selector *s = alloc_selector(); | ||
| 56 | |||
| 57 | if (!s) | ||
| 58 | return -ENOMEM; | ||
| 59 | |||
| 60 | ps->context = s; | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static void ql_free_paths(struct list_head *paths) | ||
| 65 | { | ||
| 66 | struct path_info *pi, *next; | ||
| 67 | |||
| 68 | list_for_each_entry_safe(pi, next, paths, list) { | ||
| 69 | list_del(&pi->list); | ||
| 70 | kfree(pi); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | static void ql_destroy(struct path_selector *ps) | ||
| 75 | { | ||
| 76 | struct selector *s = ps->context; | ||
| 77 | |||
| 78 | ql_free_paths(&s->valid_paths); | ||
| 79 | ql_free_paths(&s->failed_paths); | ||
| 80 | kfree(s); | ||
| 81 | ps->context = NULL; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int ql_status(struct path_selector *ps, struct dm_path *path, | ||
| 85 | status_type_t type, char *result, unsigned maxlen) | ||
| 86 | { | ||
| 87 | unsigned sz = 0; | ||
| 88 | struct path_info *pi; | ||
| 89 | |||
| 90 | /* When called with NULL path, return selector status/args. */ | ||
| 91 | if (!path) | ||
| 92 | DMEMIT("0 "); | ||
| 93 | else { | ||
| 94 | pi = path->pscontext; | ||
| 95 | |||
| 96 | switch (type) { | ||
| 97 | case STATUSTYPE_INFO: | ||
| 98 | DMEMIT("%d ", atomic_read(&pi->qlen)); | ||
| 99 | break; | ||
| 100 | case STATUSTYPE_TABLE: | ||
| 101 | DMEMIT("%u ", pi->repeat_count); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | return sz; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int ql_add_path(struct path_selector *ps, struct dm_path *path, | ||
| 110 | int argc, char **argv, char **error) | ||
| 111 | { | ||
| 112 | struct selector *s = ps->context; | ||
| 113 | struct path_info *pi; | ||
| 114 | unsigned repeat_count = QL_MIN_IO; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Arguments: [<repeat_count>] | ||
| 118 | * <repeat_count>: The number of I/Os before switching path. | ||
| 119 | * If not given, default (QL_MIN_IO) is used. | ||
| 120 | */ | ||
| 121 | if (argc > 1) { | ||
| 122 | *error = "queue-length ps: incorrect number of arguments"; | ||
| 123 | return -EINVAL; | ||
| 124 | } | ||
| 125 | |||
| 126 | if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) { | ||
| 127 | *error = "queue-length ps: invalid repeat count"; | ||
| 128 | return -EINVAL; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Allocate the path information structure */ | ||
| 132 | pi = kmalloc(sizeof(*pi), GFP_KERNEL); | ||
| 133 | if (!pi) { | ||
| 134 | *error = "queue-length ps: Error allocating path information"; | ||
| 135 | return -ENOMEM; | ||
| 136 | } | ||
| 137 | |||
| 138 | pi->path = path; | ||
| 139 | pi->repeat_count = repeat_count; | ||
| 140 | atomic_set(&pi->qlen, 0); | ||
| 141 | |||
| 142 | path->pscontext = pi; | ||
| 143 | |||
| 144 | list_add_tail(&pi->list, &s->valid_paths); | ||
| 145 | |||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static void ql_fail_path(struct path_selector *ps, struct dm_path *path) | ||
| 150 | { | ||
| 151 | struct selector *s = ps->context; | ||
| 152 | struct path_info *pi = path->pscontext; | ||
| 153 | |||
| 154 | list_move(&pi->list, &s->failed_paths); | ||
| 155 | } | ||
| 156 | |||
| 157 | static int ql_reinstate_path(struct path_selector *ps, struct dm_path *path) | ||
| 158 | { | ||
| 159 | struct selector *s = ps->context; | ||
| 160 | struct path_info *pi = path->pscontext; | ||
| 161 | |||
| 162 | list_move_tail(&pi->list, &s->valid_paths); | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | ||
| 168 | * Select a path having the minimum number of in-flight I/Os | ||
| 169 | */ | ||
| 170 | static struct dm_path *ql_select_path(struct path_selector *ps, | ||
| 171 | unsigned *repeat_count, size_t nr_bytes) | ||
| 172 | { | ||
| 173 | struct selector *s = ps->context; | ||
| 174 | struct path_info *pi = NULL, *best = NULL; | ||
| 175 | |||
| 176 | if (list_empty(&s->valid_paths)) | ||
| 177 | return NULL; | ||
| 178 | |||
| 179 | /* Change preferred (first in list) path to evenly balance. */ | ||
| 180 | list_move_tail(s->valid_paths.next, &s->valid_paths); | ||
| 181 | |||
| 182 | list_for_each_entry(pi, &s->valid_paths, list) { | ||
| 183 | if (!best || | ||
| 184 | (atomic_read(&pi->qlen) < atomic_read(&best->qlen))) | ||
| 185 | best = pi; | ||
| 186 | |||
| 187 | if (!atomic_read(&best->qlen)) | ||
| 188 | break; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (!best) | ||
| 192 | return NULL; | ||
| 193 | |||
| 194 | *repeat_count = best->repeat_count; | ||
| 195 | |||
| 196 | return best->path; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int ql_start_io(struct path_selector *ps, struct dm_path *path, | ||
| 200 | size_t nr_bytes) | ||
| 201 | { | ||
| 202 | struct path_info *pi = path->pscontext; | ||
| 203 | |||
| 204 | atomic_inc(&pi->qlen); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int ql_end_io(struct path_selector *ps, struct dm_path *path, | ||
| 210 | size_t nr_bytes) | ||
| 211 | { | ||
| 212 | struct path_info *pi = path->pscontext; | ||
| 213 | |||
| 214 | atomic_dec(&pi->qlen); | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static struct path_selector_type ql_ps = { | ||
| 220 | .name = "queue-length", | ||
| 221 | .module = THIS_MODULE, | ||
| 222 | .table_args = 1, | ||
| 223 | .info_args = 1, | ||
| 224 | .create = ql_create, | ||
| 225 | .destroy = ql_destroy, | ||
| 226 | .status = ql_status, | ||
| 227 | .add_path = ql_add_path, | ||
| 228 | .fail_path = ql_fail_path, | ||
| 229 | .reinstate_path = ql_reinstate_path, | ||
| 230 | .select_path = ql_select_path, | ||
| 231 | .start_io = ql_start_io, | ||
| 232 | .end_io = ql_end_io, | ||
| 233 | }; | ||
| 234 | |||
| 235 | static int __init dm_ql_init(void) | ||
| 236 | { | ||
| 237 | int r = dm_register_path_selector(&ql_ps); | ||
| 238 | |||
| 239 | if (r < 0) | ||
| 240 | DMERR("register failed %d", r); | ||
| 241 | |||
| 242 | DMINFO("version " QL_VERSION " loaded"); | ||
| 243 | |||
| 244 | return r; | ||
| 245 | } | ||
| 246 | |||
| 247 | static void __exit dm_ql_exit(void) | ||
| 248 | { | ||
| 249 | int r = dm_unregister_path_selector(&ql_ps); | ||
| 250 | |||
| 251 | if (r < 0) | ||
| 252 | DMERR("unregister failed %d", r); | ||
| 253 | } | ||
| 254 | |||
| 255 | module_init(dm_ql_init); | ||
| 256 | module_exit(dm_ql_exit); | ||
| 257 | |||
| 258 | MODULE_AUTHOR("Stefan Bader <Stefan.Bader at de.ibm.com>"); | ||
| 259 | MODULE_DESCRIPTION( | ||
| 260 | "(C) Copyright IBM Corp. 2004,2005 All Rights Reserved.\n" | ||
| 261 | DM_NAME " path selector to balance the number of in-flight I/Os" | ||
| 262 | ); | ||
| 263 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 076fbb4e967a..ce8868c768cc 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -1283,9 +1283,23 @@ static int mirror_status(struct dm_target *ti, status_type_t type, | |||
| 1283 | return 0; | 1283 | return 0; |
| 1284 | } | 1284 | } |
| 1285 | 1285 | ||
| 1286 | static int mirror_iterate_devices(struct dm_target *ti, | ||
| 1287 | iterate_devices_callout_fn fn, void *data) | ||
| 1288 | { | ||
| 1289 | struct mirror_set *ms = ti->private; | ||
| 1290 | int ret = 0; | ||
| 1291 | unsigned i; | ||
| 1292 | |||
| 1293 | for (i = 0; !ret && i < ms->nr_mirrors; i++) | ||
| 1294 | ret = fn(ti, ms->mirror[i].dev, | ||
| 1295 | ms->mirror[i].offset, data); | ||
| 1296 | |||
| 1297 | return ret; | ||
| 1298 | } | ||
| 1299 | |||
| 1286 | static struct target_type mirror_target = { | 1300 | static struct target_type mirror_target = { |
| 1287 | .name = "mirror", | 1301 | .name = "mirror", |
| 1288 | .version = {1, 0, 20}, | 1302 | .version = {1, 12, 0}, |
| 1289 | .module = THIS_MODULE, | 1303 | .module = THIS_MODULE, |
| 1290 | .ctr = mirror_ctr, | 1304 | .ctr = mirror_ctr, |
| 1291 | .dtr = mirror_dtr, | 1305 | .dtr = mirror_dtr, |
| @@ -1295,6 +1309,7 @@ static struct target_type mirror_target = { | |||
| 1295 | .postsuspend = mirror_postsuspend, | 1309 | .postsuspend = mirror_postsuspend, |
| 1296 | .resume = mirror_resume, | 1310 | .resume = mirror_resume, |
| 1297 | .status = mirror_status, | 1311 | .status = mirror_status, |
| 1312 | .iterate_devices = mirror_iterate_devices, | ||
| 1298 | }; | 1313 | }; |
| 1299 | 1314 | ||
| 1300 | static int __init dm_mirror_init(void) | 1315 | static int __init dm_mirror_init(void) |
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 7b899be0b087..36dbe29f2fd6 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c | |||
| @@ -283,7 +283,7 @@ static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region) | |||
| 283 | 283 | ||
| 284 | nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC); | 284 | nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC); |
| 285 | if (unlikely(!nreg)) | 285 | if (unlikely(!nreg)) |
| 286 | nreg = kmalloc(sizeof(*nreg), GFP_NOIO); | 286 | nreg = kmalloc(sizeof(*nreg), GFP_NOIO | __GFP_NOFAIL); |
| 287 | 287 | ||
| 288 | nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? | 288 | nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? |
| 289 | DM_RH_CLEAN : DM_RH_NOSYNC; | 289 | DM_RH_CLEAN : DM_RH_NOSYNC; |
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index cdfbf65b28cb..24752f449bef 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c | |||
| @@ -161,7 +161,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) | |||
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static struct dm_path *rr_select_path(struct path_selector *ps, | 163 | static struct dm_path *rr_select_path(struct path_selector *ps, |
| 164 | unsigned *repeat_count) | 164 | unsigned *repeat_count, size_t nr_bytes) |
| 165 | { | 165 | { |
| 166 | struct selector *s = (struct selector *) ps->context; | 166 | struct selector *s = (struct selector *) ps->context; |
| 167 | struct path_info *pi = NULL; | 167 | struct path_info *pi = NULL; |
diff --git a/drivers/md/dm-service-time.c b/drivers/md/dm-service-time.c new file mode 100644 index 000000000000..cfa668f46c40 --- /dev/null +++ b/drivers/md/dm-service-time.c | |||
| @@ -0,0 +1,339 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2009 NEC Corporation. All Rights Reserved. | ||
| 3 | * | ||
| 4 | * Module Author: Kiyoshi Ueda | ||
| 5 | * | ||
| 6 | * This file is released under the GPL. | ||
| 7 | * | ||
| 8 | * Throughput oriented path selector. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include "dm.h" | ||
| 12 | #include "dm-path-selector.h" | ||
| 13 | |||
| 14 | #define DM_MSG_PREFIX "multipath service-time" | ||
| 15 | #define ST_MIN_IO 1 | ||
| 16 | #define ST_MAX_RELATIVE_THROUGHPUT 100 | ||
| 17 | #define ST_MAX_RELATIVE_THROUGHPUT_SHIFT 7 | ||
| 18 | #define ST_MAX_INFLIGHT_SIZE ((size_t)-1 >> ST_MAX_RELATIVE_THROUGHPUT_SHIFT) | ||
| 19 | #define ST_VERSION "0.2.0" | ||
| 20 | |||
| 21 | struct selector { | ||
| 22 | struct list_head valid_paths; | ||
| 23 | struct list_head failed_paths; | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct path_info { | ||
| 27 | struct list_head list; | ||
| 28 | struct dm_path *path; | ||
| 29 | unsigned repeat_count; | ||
| 30 | unsigned relative_throughput; | ||
| 31 | atomic_t in_flight_size; /* Total size of in-flight I/Os */ | ||
| 32 | }; | ||
| 33 | |||
| 34 | static struct selector *alloc_selector(void) | ||
| 35 | { | ||
| 36 | struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
| 37 | |||
| 38 | if (s) { | ||
| 39 | INIT_LIST_HEAD(&s->valid_paths); | ||
| 40 | INIT_LIST_HEAD(&s->failed_paths); | ||
| 41 | } | ||
| 42 | |||
| 43 | return s; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int st_create(struct path_selector *ps, unsigned argc, char **argv) | ||
| 47 | { | ||
| 48 | struct selector *s = alloc_selector(); | ||
| 49 | |||
| 50 | if (!s) | ||
| 51 | return -ENOMEM; | ||
| 52 | |||
| 53 | ps->context = s; | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void free_paths(struct list_head *paths) | ||
| 58 | { | ||
| 59 | struct path_info *pi, *next; | ||
| 60 | |||
| 61 | list_for_each_entry_safe(pi, next, paths, list) { | ||
| 62 | list_del(&pi->list); | ||
| 63 | kfree(pi); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | static void st_destroy(struct path_selector *ps) | ||
| 68 | { | ||
| 69 | struct selector *s = ps->context; | ||
| 70 | |||
| 71 | free_paths(&s->valid_paths); | ||
| 72 | free_paths(&s->failed_paths); | ||
| 73 | kfree(s); | ||
| 74 | ps->context = NULL; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int st_status(struct path_selector *ps, struct dm_path *path, | ||
| 78 | status_type_t type, char *result, unsigned maxlen) | ||
| 79 | { | ||
| 80 | unsigned sz = 0; | ||
| 81 | struct path_info *pi; | ||
| 82 | |||
| 83 | if (!path) | ||
| 84 | DMEMIT("0 "); | ||
| 85 | else { | ||
| 86 | pi = path->pscontext; | ||
| 87 | |||
| 88 | switch (type) { | ||
| 89 | case STATUSTYPE_INFO: | ||
| 90 | DMEMIT("%d %u ", atomic_read(&pi->in_flight_size), | ||
| 91 | pi->relative_throughput); | ||
| 92 | break; | ||
| 93 | case STATUSTYPE_TABLE: | ||
| 94 | DMEMIT("%u %u ", pi->repeat_count, | ||
| 95 | pi->relative_throughput); | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | return sz; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int st_add_path(struct path_selector *ps, struct dm_path *path, | ||
| 104 | int argc, char **argv, char **error) | ||
| 105 | { | ||
| 106 | struct selector *s = ps->context; | ||
| 107 | struct path_info *pi; | ||
| 108 | unsigned repeat_count = ST_MIN_IO; | ||
| 109 | unsigned relative_throughput = 1; | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Arguments: [<repeat_count> [<relative_throughput>]] | ||
| 113 | * <repeat_count>: The number of I/Os before switching path. | ||
| 114 | * If not given, default (ST_MIN_IO) is used. | ||
| 115 | * <relative_throughput>: The relative throughput value of | ||
| 116 | * the path among all paths in the path-group. | ||
| 117 | * The valid range: 0-<ST_MAX_RELATIVE_THROUGHPUT> | ||
| 118 | * If not given, minimum value '1' is used. | ||
| 119 | * If '0' is given, the path isn't selected while | ||
| 120 | * other paths having a positive value are | ||
| 121 | * available. | ||
| 122 | */ | ||
| 123 | if (argc > 2) { | ||
| 124 | *error = "service-time ps: incorrect number of arguments"; | ||
| 125 | return -EINVAL; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (argc && (sscanf(argv[0], "%u", &repeat_count) != 1)) { | ||
| 129 | *error = "service-time ps: invalid repeat count"; | ||
| 130 | return -EINVAL; | ||
| 131 | } | ||
| 132 | |||
| 133 | if ((argc == 2) && | ||
| 134 | (sscanf(argv[1], "%u", &relative_throughput) != 1 || | ||
| 135 | relative_throughput > ST_MAX_RELATIVE_THROUGHPUT)) { | ||
| 136 | *error = "service-time ps: invalid relative_throughput value"; | ||
| 137 | return -EINVAL; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* allocate the path */ | ||
| 141 | pi = kmalloc(sizeof(*pi), GFP_KERNEL); | ||
| 142 | if (!pi) { | ||
| 143 | *error = "service-time ps: Error allocating path context"; | ||
| 144 | return -ENOMEM; | ||
| 145 | } | ||
| 146 | |||
| 147 | pi->path = path; | ||
| 148 | pi->repeat_count = repeat_count; | ||
| 149 | pi->relative_throughput = relative_throughput; | ||
| 150 | atomic_set(&pi->in_flight_size, 0); | ||
| 151 | |||
| 152 | path->pscontext = pi; | ||
| 153 | |||
| 154 | list_add_tail(&pi->list, &s->valid_paths); | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static void st_fail_path(struct path_selector *ps, struct dm_path *path) | ||
| 160 | { | ||
| 161 | struct selector *s = ps->context; | ||
| 162 | struct path_info *pi = path->pscontext; | ||
| 163 | |||
| 164 | list_move(&pi->list, &s->failed_paths); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int st_reinstate_path(struct path_selector *ps, struct dm_path *path) | ||
| 168 | { | ||
| 169 | struct selector *s = ps->context; | ||
| 170 | struct path_info *pi = path->pscontext; | ||
| 171 | |||
| 172 | list_move_tail(&pi->list, &s->valid_paths); | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Compare the estimated service time of 2 paths, pi1 and pi2, | ||
| 179 | * for the incoming I/O. | ||
| 180 | * | ||
| 181 | * Returns: | ||
| 182 | * < 0 : pi1 is better | ||
| 183 | * 0 : no difference between pi1 and pi2 | ||
| 184 | * > 0 : pi2 is better | ||
| 185 | * | ||
| 186 | * Description: | ||
| 187 | * Basically, the service time is estimated by: | ||
| 188 | * ('pi->in-flight-size' + 'incoming') / 'pi->relative_throughput' | ||
| 189 | * To reduce the calculation, some optimizations are made. | ||
| 190 | * (See comments inline) | ||
| 191 | */ | ||
| 192 | static int st_compare_load(struct path_info *pi1, struct path_info *pi2, | ||
| 193 | size_t incoming) | ||
| 194 | { | ||
| 195 | size_t sz1, sz2, st1, st2; | ||
| 196 | |||
| 197 | sz1 = atomic_read(&pi1->in_flight_size); | ||
| 198 | sz2 = atomic_read(&pi2->in_flight_size); | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Case 1: Both have same throughput value. Choose less loaded path. | ||
| 202 | */ | ||
| 203 | if (pi1->relative_throughput == pi2->relative_throughput) | ||
| 204 | return sz1 - sz2; | ||
| 205 | |||
| 206 | /* | ||
| 207 | * Case 2a: Both have same load. Choose higher throughput path. | ||
| 208 | * Case 2b: One path has no throughput value. Choose the other one. | ||
| 209 | */ | ||
| 210 | if (sz1 == sz2 || | ||
| 211 | !pi1->relative_throughput || !pi2->relative_throughput) | ||
| 212 | return pi2->relative_throughput - pi1->relative_throughput; | ||
| 213 | |||
| 214 | /* | ||
| 215 | * Case 3: Calculate service time. Choose faster path. | ||
| 216 | * Service time using pi1: | ||
| 217 | * st1 = (sz1 + incoming) / pi1->relative_throughput | ||
| 218 | * Service time using pi2: | ||
| 219 | * st2 = (sz2 + incoming) / pi2->relative_throughput | ||
| 220 | * | ||
| 221 | * To avoid the division, transform the expression to use | ||
| 222 | * multiplication. | ||
| 223 | * Because ->relative_throughput > 0 here, if st1 < st2, | ||
| 224 | * the expressions below are the same meaning: | ||
| 225 | * (sz1 + incoming) / pi1->relative_throughput < | ||
| 226 | * (sz2 + incoming) / pi2->relative_throughput | ||
| 227 | * (sz1 + incoming) * pi2->relative_throughput < | ||
| 228 | * (sz2 + incoming) * pi1->relative_throughput | ||
| 229 | * So use the later one. | ||
| 230 | */ | ||
| 231 | sz1 += incoming; | ||
| 232 | sz2 += incoming; | ||
| 233 | if (unlikely(sz1 >= ST_MAX_INFLIGHT_SIZE || | ||
| 234 | sz2 >= ST_MAX_INFLIGHT_SIZE)) { | ||
| 235 | /* | ||
| 236 | * Size may be too big for multiplying pi->relative_throughput | ||
| 237 | * and overflow. | ||
| 238 | * To avoid the overflow and mis-selection, shift down both. | ||
| 239 | */ | ||
| 240 | sz1 >>= ST_MAX_RELATIVE_THROUGHPUT_SHIFT; | ||
| 241 | sz2 >>= ST_MAX_RELATIVE_THROUGHPUT_SHIFT; | ||
| 242 | } | ||
| 243 | st1 = sz1 * pi2->relative_throughput; | ||
| 244 | st2 = sz2 * pi1->relative_throughput; | ||
| 245 | if (st1 != st2) | ||
| 246 | return st1 - st2; | ||
| 247 | |||
| 248 | /* | ||
| 249 | * Case 4: Service time is equal. Choose higher throughput path. | ||
| 250 | */ | ||
| 251 | return pi2->relative_throughput - pi1->relative_throughput; | ||
| 252 | } | ||
| 253 | |||
| 254 | static struct dm_path *st_select_path(struct path_selector *ps, | ||
| 255 | unsigned *repeat_count, size_t nr_bytes) | ||
| 256 | { | ||
| 257 | struct selector *s = ps->context; | ||
| 258 | struct path_info *pi = NULL, *best = NULL; | ||
| 259 | |||
| 260 | if (list_empty(&s->valid_paths)) | ||
| 261 | return NULL; | ||
| 262 | |||
| 263 | /* Change preferred (first in list) path to evenly balance. */ | ||
| 264 | list_move_tail(s->valid_paths.next, &s->valid_paths); | ||
| 265 | |||
| 266 | list_for_each_entry(pi, &s->valid_paths, list) | ||
| 267 | if (!best || (st_compare_load(pi, best, nr_bytes) < 0)) | ||
| 268 | best = pi; | ||
| 269 | |||
| 270 | if (!best) | ||
| 271 | return NULL; | ||
| 272 | |||
| 273 | *repeat_count = best->repeat_count; | ||
| 274 | |||
| 275 | return best->path; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int st_start_io(struct path_selector *ps, struct dm_path *path, | ||
| 279 | size_t nr_bytes) | ||
| 280 | { | ||
| 281 | struct path_info *pi = path->pscontext; | ||
| 282 | |||
| 283 | atomic_add(nr_bytes, &pi->in_flight_size); | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int st_end_io(struct path_selector *ps, struct dm_path *path, | ||
| 289 | size_t nr_bytes) | ||
| 290 | { | ||
| 291 | struct path_info *pi = path->pscontext; | ||
| 292 | |||
| 293 | atomic_sub(nr_bytes, &pi->in_flight_size); | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static struct path_selector_type st_ps = { | ||
| 299 | .name = "service-time", | ||
| 300 | .module = THIS_MODULE, | ||
| 301 | .table_args = 2, | ||
| 302 | .info_args = 2, | ||
| 303 | .create = st_create, | ||
| 304 | .destroy = st_destroy, | ||
| 305 | .status = st_status, | ||
| 306 | .add_path = st_add_path, | ||
| 307 | .fail_path = st_fail_path, | ||
| 308 | .reinstate_path = st_reinstate_path, | ||
| 309 | .select_path = st_select_path, | ||
| 310 | .start_io = st_start_io, | ||
| 311 | .end_io = st_end_io, | ||
| 312 | }; | ||
| 313 | |||
| 314 | static int __init dm_st_init(void) | ||
| 315 | { | ||
| 316 | int r = dm_register_path_selector(&st_ps); | ||
| 317 | |||
| 318 | if (r < 0) | ||
| 319 | DMERR("register failed %d", r); | ||
| 320 | |||
| 321 | DMINFO("version " ST_VERSION " loaded"); | ||
| 322 | |||
| 323 | return r; | ||
| 324 | } | ||
| 325 | |||
| 326 | static void __exit dm_st_exit(void) | ||
| 327 | { | ||
| 328 | int r = dm_unregister_path_selector(&st_ps); | ||
| 329 | |||
| 330 | if (r < 0) | ||
| 331 | DMERR("unregister failed %d", r); | ||
| 332 | } | ||
| 333 | |||
| 334 | module_init(dm_st_init); | ||
| 335 | module_exit(dm_st_exit); | ||
| 336 | |||
| 337 | MODULE_DESCRIPTION(DM_NAME " throughput oriented path selector"); | ||
| 338 | MODULE_AUTHOR("Kiyoshi Ueda <k-ueda@ct.jp.nec.com>"); | ||
| 339 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 2662a41337e7..6e3fe4f14934 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
| @@ -636,7 +636,7 @@ static void persistent_commit_exception(struct dm_exception_store *store, | |||
| 636 | /* | 636 | /* |
| 637 | * Commit exceptions to disk. | 637 | * Commit exceptions to disk. |
| 638 | */ | 638 | */ |
| 639 | if (ps->valid && area_io(ps, WRITE)) | 639 | if (ps->valid && area_io(ps, WRITE_BARRIER)) |
| 640 | ps->valid = 0; | 640 | ps->valid = 0; |
| 641 | 641 | ||
| 642 | /* | 642 | /* |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index d73f17fc7778..d573165cd2b7 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -678,6 +678,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 678 | 678 | ||
| 679 | ti->private = s; | 679 | ti->private = s; |
| 680 | ti->split_io = s->store->chunk_size; | 680 | ti->split_io = s->store->chunk_size; |
| 681 | ti->num_flush_requests = 1; | ||
| 681 | 682 | ||
| 682 | return 0; | 683 | return 0; |
| 683 | 684 | ||
| @@ -1030,6 +1031,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 1030 | chunk_t chunk; | 1031 | chunk_t chunk; |
| 1031 | struct dm_snap_pending_exception *pe = NULL; | 1032 | struct dm_snap_pending_exception *pe = NULL; |
| 1032 | 1033 | ||
| 1034 | if (unlikely(bio_empty_barrier(bio))) { | ||
| 1035 | bio->bi_bdev = s->store->cow->bdev; | ||
| 1036 | return DM_MAPIO_REMAPPED; | ||
| 1037 | } | ||
| 1038 | |||
| 1033 | chunk = sector_to_chunk(s->store, bio->bi_sector); | 1039 | chunk = sector_to_chunk(s->store, bio->bi_sector); |
| 1034 | 1040 | ||
| 1035 | /* Full snapshots are not usable */ | 1041 | /* Full snapshots are not usable */ |
| @@ -1338,6 +1344,8 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1338 | } | 1344 | } |
| 1339 | 1345 | ||
| 1340 | ti->private = dev; | 1346 | ti->private = dev; |
| 1347 | ti->num_flush_requests = 1; | ||
| 1348 | |||
| 1341 | return 0; | 1349 | return 0; |
| 1342 | } | 1350 | } |
| 1343 | 1351 | ||
| @@ -1353,6 +1361,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio, | |||
| 1353 | struct dm_dev *dev = ti->private; | 1361 | struct dm_dev *dev = ti->private; |
| 1354 | bio->bi_bdev = dev->bdev; | 1362 | bio->bi_bdev = dev->bdev; |
| 1355 | 1363 | ||
| 1364 | if (unlikely(bio_empty_barrier(bio))) | ||
| 1365 | return DM_MAPIO_REMAPPED; | ||
| 1366 | |||
| 1356 | /* Only tell snapshots if this is a write */ | 1367 | /* Only tell snapshots if this is a write */ |
| 1357 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; | 1368 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; |
| 1358 | } | 1369 | } |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 41569bc60abc..b240e85ae39a 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
| @@ -167,6 +167,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 167 | sc->stripes = stripes; | 167 | sc->stripes = stripes; |
| 168 | sc->stripe_width = width; | 168 | sc->stripe_width = width; |
| 169 | ti->split_io = chunk_size; | 169 | ti->split_io = chunk_size; |
| 170 | ti->num_flush_requests = stripes; | ||
| 170 | 171 | ||
| 171 | sc->chunk_mask = ((sector_t) chunk_size) - 1; | 172 | sc->chunk_mask = ((sector_t) chunk_size) - 1; |
| 172 | for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) | 173 | for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) |
| @@ -211,10 +212,18 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, | |||
| 211 | union map_info *map_context) | 212 | union map_info *map_context) |
| 212 | { | 213 | { |
| 213 | struct stripe_c *sc = (struct stripe_c *) ti->private; | 214 | struct stripe_c *sc = (struct stripe_c *) ti->private; |
| 215 | sector_t offset, chunk; | ||
| 216 | uint32_t stripe; | ||
| 214 | 217 | ||
| 215 | sector_t offset = bio->bi_sector - ti->begin; | 218 | if (unlikely(bio_empty_barrier(bio))) { |
| 216 | sector_t chunk = offset >> sc->chunk_shift; | 219 | BUG_ON(map_context->flush_request >= sc->stripes); |
| 217 | uint32_t stripe = sector_div(chunk, sc->stripes); | 220 | bio->bi_bdev = sc->stripe[map_context->flush_request].dev->bdev; |
| 221 | return DM_MAPIO_REMAPPED; | ||
| 222 | } | ||
| 223 | |||
| 224 | offset = bio->bi_sector - ti->begin; | ||
| 225 | chunk = offset >> sc->chunk_shift; | ||
| 226 | stripe = sector_div(chunk, sc->stripes); | ||
| 218 | 227 | ||
| 219 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; | 228 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; |
| 220 | bio->bi_sector = sc->stripe[stripe].physical_start + | 229 | bio->bi_sector = sc->stripe[stripe].physical_start + |
| @@ -304,15 +313,31 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, | |||
| 304 | return error; | 313 | return error; |
| 305 | } | 314 | } |
| 306 | 315 | ||
| 316 | static int stripe_iterate_devices(struct dm_target *ti, | ||
| 317 | iterate_devices_callout_fn fn, void *data) | ||
| 318 | { | ||
| 319 | struct stripe_c *sc = ti->private; | ||
| 320 | int ret = 0; | ||
| 321 | unsigned i = 0; | ||
| 322 | |||
| 323 | do | ||
| 324 | ret = fn(ti, sc->stripe[i].dev, | ||
| 325 | sc->stripe[i].physical_start, data); | ||
| 326 | while (!ret && ++i < sc->stripes); | ||
| 327 | |||
| 328 | return ret; | ||
| 329 | } | ||
| 330 | |||
| 307 | static struct target_type stripe_target = { | 331 | static struct target_type stripe_target = { |
| 308 | .name = "striped", | 332 | .name = "striped", |
| 309 | .version = {1, 1, 0}, | 333 | .version = {1, 2, 0}, |
| 310 | .module = THIS_MODULE, | 334 | .module = THIS_MODULE, |
| 311 | .ctr = stripe_ctr, | 335 | .ctr = stripe_ctr, |
| 312 | .dtr = stripe_dtr, | 336 | .dtr = stripe_dtr, |
| 313 | .map = stripe_map, | 337 | .map = stripe_map, |
| 314 | .end_io = stripe_end_io, | 338 | .end_io = stripe_end_io, |
| 315 | .status = stripe_status, | 339 | .status = stripe_status, |
| 340 | .iterate_devices = stripe_iterate_devices, | ||
| 316 | }; | 341 | }; |
| 317 | 342 | ||
| 318 | int __init dm_stripe_init(void) | 343 | int __init dm_stripe_init(void) |
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index a2a45e6c7c8b..4b045903a4e2 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c | |||
| @@ -57,12 +57,21 @@ static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf) | |||
| 57 | return strlen(buf); | 57 | return strlen(buf); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf) | ||
| 61 | { | ||
| 62 | sprintf(buf, "%d\n", dm_suspended(md)); | ||
| 63 | |||
| 64 | return strlen(buf); | ||
| 65 | } | ||
| 66 | |||
| 60 | static DM_ATTR_RO(name); | 67 | static DM_ATTR_RO(name); |
| 61 | static DM_ATTR_RO(uuid); | 68 | static DM_ATTR_RO(uuid); |
| 69 | static DM_ATTR_RO(suspended); | ||
| 62 | 70 | ||
| 63 | static struct attribute *dm_attrs[] = { | 71 | static struct attribute *dm_attrs[] = { |
| 64 | &dm_attr_name.attr, | 72 | &dm_attr_name.attr, |
| 65 | &dm_attr_uuid.attr, | 73 | &dm_attr_uuid.attr, |
| 74 | &dm_attr_suspended.attr, | ||
| 66 | NULL, | 75 | NULL, |
| 67 | }; | 76 | }; |
| 68 | 77 | ||
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index e9a73bb242b0..2cba557d9e61 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | struct dm_table { | 41 | struct dm_table { |
| 42 | struct mapped_device *md; | 42 | struct mapped_device *md; |
| 43 | atomic_t holders; | 43 | atomic_t holders; |
| 44 | unsigned type; | ||
| 44 | 45 | ||
| 45 | /* btree table */ | 46 | /* btree table */ |
| 46 | unsigned int depth; | 47 | unsigned int depth; |
| @@ -62,15 +63,11 @@ struct dm_table { | |||
| 62 | /* a list of devices used by this table */ | 63 | /* a list of devices used by this table */ |
| 63 | struct list_head devices; | 64 | struct list_head devices; |
| 64 | 65 | ||
| 65 | /* | ||
| 66 | * These are optimistic limits taken from all the | ||
| 67 | * targets, some targets will need smaller limits. | ||
| 68 | */ | ||
| 69 | struct io_restrictions limits; | ||
| 70 | |||
| 71 | /* events get handed up using this callback */ | 66 | /* events get handed up using this callback */ |
| 72 | void (*event_fn)(void *); | 67 | void (*event_fn)(void *); |
| 73 | void *event_context; | 68 | void *event_context; |
| 69 | |||
| 70 | struct dm_md_mempools *mempools; | ||
| 74 | }; | 71 | }; |
| 75 | 72 | ||
| 76 | /* | 73 | /* |
| @@ -89,43 +86,6 @@ static unsigned int int_log(unsigned int n, unsigned int base) | |||
| 89 | } | 86 | } |
| 90 | 87 | ||
| 91 | /* | 88 | /* |
| 92 | * Returns the minimum that is _not_ zero, unless both are zero. | ||
| 93 | */ | ||
| 94 | #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Combine two io_restrictions, always taking the lower value. | ||
| 98 | */ | ||
| 99 | static void combine_restrictions_low(struct io_restrictions *lhs, | ||
| 100 | struct io_restrictions *rhs) | ||
| 101 | { | ||
| 102 | lhs->max_sectors = | ||
| 103 | min_not_zero(lhs->max_sectors, rhs->max_sectors); | ||
| 104 | |||
| 105 | lhs->max_phys_segments = | ||
| 106 | min_not_zero(lhs->max_phys_segments, rhs->max_phys_segments); | ||
| 107 | |||
| 108 | lhs->max_hw_segments = | ||
| 109 | min_not_zero(lhs->max_hw_segments, rhs->max_hw_segments); | ||
| 110 | |||
| 111 | lhs->logical_block_size = max(lhs->logical_block_size, | ||
| 112 | rhs->logical_block_size); | ||
| 113 | |||
| 114 | lhs->max_segment_size = | ||
| 115 | min_not_zero(lhs->max_segment_size, rhs->max_segment_size); | ||
| 116 | |||
| 117 | lhs->max_hw_sectors = | ||
| 118 | min_not_zero(lhs->max_hw_sectors, rhs->max_hw_sectors); | ||
| 119 | |||
| 120 | lhs->seg_boundary_mask = | ||
| 121 | min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask); | ||
| 122 | |||
| 123 | lhs->bounce_pfn = min_not_zero(lhs->bounce_pfn, rhs->bounce_pfn); | ||
| 124 | |||
| 125 | lhs->no_cluster |= rhs->no_cluster; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Calculate the index of the child node of the n'th node k'th key. | 89 | * Calculate the index of the child node of the n'th node k'th key. |
| 130 | */ | 90 | */ |
| 131 | static inline unsigned int get_child(unsigned int n, unsigned int k) | 91 | static inline unsigned int get_child(unsigned int n, unsigned int k) |
| @@ -267,6 +227,8 @@ static void free_devices(struct list_head *devices) | |||
| 267 | list_for_each_safe(tmp, next, devices) { | 227 | list_for_each_safe(tmp, next, devices) { |
| 268 | struct dm_dev_internal *dd = | 228 | struct dm_dev_internal *dd = |
| 269 | list_entry(tmp, struct dm_dev_internal, list); | 229 | list_entry(tmp, struct dm_dev_internal, list); |
| 230 | DMWARN("dm_table_destroy: dm_put_device call missing for %s", | ||
| 231 | dd->dm_dev.name); | ||
| 270 | kfree(dd); | 232 | kfree(dd); |
| 271 | } | 233 | } |
| 272 | } | 234 | } |
| @@ -296,12 +258,10 @@ void dm_table_destroy(struct dm_table *t) | |||
| 296 | vfree(t->highs); | 258 | vfree(t->highs); |
| 297 | 259 | ||
| 298 | /* free the device list */ | 260 | /* free the device list */ |
| 299 | if (t->devices.next != &t->devices) { | 261 | if (t->devices.next != &t->devices) |
| 300 | DMWARN("devices still present during destroy: " | ||
| 301 | "dm_table_remove_device calls missing"); | ||
| 302 | |||
| 303 | free_devices(&t->devices); | 262 | free_devices(&t->devices); |
| 304 | } | 263 | |
| 264 | dm_free_md_mempools(t->mempools); | ||
| 305 | 265 | ||
| 306 | kfree(t); | 266 | kfree(t); |
| 307 | } | 267 | } |
| @@ -385,15 +345,48 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md) | |||
| 385 | /* | 345 | /* |
| 386 | * If possible, this checks an area of a destination device is valid. | 346 | * If possible, this checks an area of a destination device is valid. |
| 387 | */ | 347 | */ |
| 388 | static int check_device_area(struct dm_dev_internal *dd, sector_t start, | 348 | static int device_area_is_valid(struct dm_target *ti, struct dm_dev *dev, |
| 389 | sector_t len) | 349 | sector_t start, void *data) |
| 390 | { | 350 | { |
| 391 | sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT; | 351 | struct queue_limits *limits = data; |
| 352 | struct block_device *bdev = dev->bdev; | ||
| 353 | sector_t dev_size = | ||
| 354 | i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; | ||
| 355 | unsigned short logical_block_size_sectors = | ||
| 356 | limits->logical_block_size >> SECTOR_SHIFT; | ||
| 357 | char b[BDEVNAME_SIZE]; | ||
| 392 | 358 | ||
| 393 | if (!dev_size) | 359 | if (!dev_size) |
| 394 | return 1; | 360 | return 1; |
| 395 | 361 | ||
| 396 | return ((start < dev_size) && (len <= (dev_size - start))); | 362 | if ((start >= dev_size) || (start + ti->len > dev_size)) { |
| 363 | DMWARN("%s: %s too small for target", | ||
| 364 | dm_device_name(ti->table->md), bdevname(bdev, b)); | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | if (logical_block_size_sectors <= 1) | ||
| 369 | return 1; | ||
| 370 | |||
| 371 | if (start & (logical_block_size_sectors - 1)) { | ||
| 372 | DMWARN("%s: start=%llu not aligned to h/w " | ||
| 373 | "logical block size %hu of %s", | ||
| 374 | dm_device_name(ti->table->md), | ||
| 375 | (unsigned long long)start, | ||
| 376 | limits->logical_block_size, bdevname(bdev, b)); | ||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | if (ti->len & (logical_block_size_sectors - 1)) { | ||
| 381 | DMWARN("%s: len=%llu not aligned to h/w " | ||
| 382 | "logical block size %hu of %s", | ||
| 383 | dm_device_name(ti->table->md), | ||
| 384 | (unsigned long long)ti->len, | ||
| 385 | limits->logical_block_size, bdevname(bdev, b)); | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | return 1; | ||
| 397 | } | 390 | } |
| 398 | 391 | ||
| 399 | /* | 392 | /* |
| @@ -479,38 +472,32 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, | |||
| 479 | } | 472 | } |
| 480 | atomic_inc(&dd->count); | 473 | atomic_inc(&dd->count); |
| 481 | 474 | ||
| 482 | if (!check_device_area(dd, start, len)) { | ||
| 483 | DMWARN("device %s too small for target", path); | ||
| 484 | dm_put_device(ti, &dd->dm_dev); | ||
| 485 | return -EINVAL; | ||
| 486 | } | ||
| 487 | |||
| 488 | *result = &dd->dm_dev; | 475 | *result = &dd->dm_dev; |
| 489 | |||
| 490 | return 0; | 476 | return 0; |
| 491 | } | 477 | } |
| 492 | 478 | ||
| 493 | void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) | 479 | /* |
| 480 | * Returns the minimum that is _not_ zero, unless both are zero. | ||
| 481 | */ | ||
| 482 | #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) | ||
| 483 | |||
| 484 | int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, | ||
| 485 | sector_t start, void *data) | ||
| 494 | { | 486 | { |
| 487 | struct queue_limits *limits = data; | ||
| 488 | struct block_device *bdev = dev->bdev; | ||
| 495 | struct request_queue *q = bdev_get_queue(bdev); | 489 | struct request_queue *q = bdev_get_queue(bdev); |
| 496 | struct io_restrictions *rs = &ti->limits; | ||
| 497 | char b[BDEVNAME_SIZE]; | 490 | char b[BDEVNAME_SIZE]; |
| 498 | 491 | ||
| 499 | if (unlikely(!q)) { | 492 | if (unlikely(!q)) { |
| 500 | DMWARN("%s: Cannot set limits for nonexistent device %s", | 493 | DMWARN("%s: Cannot set limits for nonexistent device %s", |
| 501 | dm_device_name(ti->table->md), bdevname(bdev, b)); | 494 | dm_device_name(ti->table->md), bdevname(bdev, b)); |
| 502 | return; | 495 | return 0; |
| 503 | } | 496 | } |
| 504 | 497 | ||
| 505 | /* | 498 | if (blk_stack_limits(limits, &q->limits, start << 9) < 0) |
| 506 | * Combine the device limits low. | 499 | DMWARN("%s: target device %s is misaligned", |
| 507 | * | 500 | dm_device_name(ti->table->md), bdevname(bdev, b)); |
| 508 | * FIXME: if we move an io_restriction struct | ||
| 509 | * into q this would just be a call to | ||
| 510 | * combine_restrictions_low() | ||
| 511 | */ | ||
| 512 | rs->max_sectors = | ||
| 513 | min_not_zero(rs->max_sectors, queue_max_sectors(q)); | ||
| 514 | 501 | ||
| 515 | /* | 502 | /* |
| 516 | * Check if merge fn is supported. | 503 | * Check if merge fn is supported. |
| @@ -519,48 +506,21 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) | |||
| 519 | */ | 506 | */ |
| 520 | 507 | ||
| 521 | if (q->merge_bvec_fn && !ti->type->merge) | 508 | if (q->merge_bvec_fn && !ti->type->merge) |
| 522 | rs->max_sectors = | 509 | limits->max_sectors = |
| 523 | min_not_zero(rs->max_sectors, | 510 | min_not_zero(limits->max_sectors, |
| 524 | (unsigned int) (PAGE_SIZE >> 9)); | 511 | (unsigned int) (PAGE_SIZE >> 9)); |
| 525 | 512 | return 0; | |
| 526 | rs->max_phys_segments = | ||
| 527 | min_not_zero(rs->max_phys_segments, | ||
| 528 | queue_max_phys_segments(q)); | ||
| 529 | |||
| 530 | rs->max_hw_segments = | ||
| 531 | min_not_zero(rs->max_hw_segments, queue_max_hw_segments(q)); | ||
| 532 | |||
| 533 | rs->logical_block_size = max(rs->logical_block_size, | ||
| 534 | queue_logical_block_size(q)); | ||
| 535 | |||
| 536 | rs->max_segment_size = | ||
| 537 | min_not_zero(rs->max_segment_size, queue_max_segment_size(q)); | ||
| 538 | |||
| 539 | rs->max_hw_sectors = | ||
| 540 | min_not_zero(rs->max_hw_sectors, queue_max_hw_sectors(q)); | ||
| 541 | |||
| 542 | rs->seg_boundary_mask = | ||
| 543 | min_not_zero(rs->seg_boundary_mask, | ||
| 544 | queue_segment_boundary(q)); | ||
| 545 | |||
| 546 | rs->bounce_pfn = min_not_zero(rs->bounce_pfn, queue_bounce_pfn(q)); | ||
| 547 | |||
| 548 | rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | ||
| 549 | } | 513 | } |
| 550 | EXPORT_SYMBOL_GPL(dm_set_device_limits); | 514 | EXPORT_SYMBOL_GPL(dm_set_device_limits); |
| 551 | 515 | ||
| 552 | int dm_get_device(struct dm_target *ti, const char *path, sector_t start, | 516 | int dm_get_device(struct dm_target *ti, const char *path, sector_t start, |
| 553 | sector_t len, fmode_t mode, struct dm_dev **result) | 517 | sector_t len, fmode_t mode, struct dm_dev **result) |
| 554 | { | 518 | { |
| 555 | int r = __table_get_device(ti->table, ti, path, | 519 | return __table_get_device(ti->table, ti, path, |
| 556 | start, len, mode, result); | 520 | start, len, mode, result); |
| 557 | |||
| 558 | if (!r) | ||
| 559 | dm_set_device_limits(ti, (*result)->bdev); | ||
| 560 | |||
| 561 | return r; | ||
| 562 | } | 521 | } |
| 563 | 522 | ||
| 523 | |||
| 564 | /* | 524 | /* |
| 565 | * Decrement a devices use count and remove it if necessary. | 525 | * Decrement a devices use count and remove it if necessary. |
| 566 | */ | 526 | */ |
| @@ -675,24 +635,78 @@ int dm_split_args(int *argc, char ***argvp, char *input) | |||
| 675 | return 0; | 635 | return 0; |
| 676 | } | 636 | } |
| 677 | 637 | ||
| 678 | static void check_for_valid_limits(struct io_restrictions *rs) | 638 | /* |
| 639 | * Impose necessary and sufficient conditions on a devices's table such | ||
| 640 | * that any incoming bio which respects its logical_block_size can be | ||
| 641 | * processed successfully. If it falls across the boundary between | ||
| 642 | * two or more targets, the size of each piece it gets split into must | ||
| 643 | * be compatible with the logical_block_size of the target processing it. | ||
| 644 | */ | ||
| 645 | static int validate_hardware_logical_block_alignment(struct dm_table *table, | ||
| 646 | struct queue_limits *limits) | ||
| 679 | { | 647 | { |
| 680 | if (!rs->max_sectors) | 648 | /* |
| 681 | rs->max_sectors = SAFE_MAX_SECTORS; | 649 | * This function uses arithmetic modulo the logical_block_size |
| 682 | if (!rs->max_hw_sectors) | 650 | * (in units of 512-byte sectors). |
| 683 | rs->max_hw_sectors = SAFE_MAX_SECTORS; | 651 | */ |
| 684 | if (!rs->max_phys_segments) | 652 | unsigned short device_logical_block_size_sects = |
| 685 | rs->max_phys_segments = MAX_PHYS_SEGMENTS; | 653 | limits->logical_block_size >> SECTOR_SHIFT; |
| 686 | if (!rs->max_hw_segments) | 654 | |
| 687 | rs->max_hw_segments = MAX_HW_SEGMENTS; | 655 | /* |
| 688 | if (!rs->logical_block_size) | 656 | * Offset of the start of the next table entry, mod logical_block_size. |
| 689 | rs->logical_block_size = 1 << SECTOR_SHIFT; | 657 | */ |
| 690 | if (!rs->max_segment_size) | 658 | unsigned short next_target_start = 0; |
| 691 | rs->max_segment_size = MAX_SEGMENT_SIZE; | 659 | |
| 692 | if (!rs->seg_boundary_mask) | 660 | /* |
| 693 | rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; | 661 | * Given an aligned bio that extends beyond the end of a |
| 694 | if (!rs->bounce_pfn) | 662 | * target, how many sectors must the next target handle? |
| 695 | rs->bounce_pfn = -1; | 663 | */ |
| 664 | unsigned short remaining = 0; | ||
| 665 | |||
| 666 | struct dm_target *uninitialized_var(ti); | ||
| 667 | struct queue_limits ti_limits; | ||
| 668 | unsigned i = 0; | ||
| 669 | |||
| 670 | /* | ||
| 671 | * Check each entry in the table in turn. | ||
| 672 | */ | ||
| 673 | while (i < dm_table_get_num_targets(table)) { | ||
| 674 | ti = dm_table_get_target(table, i++); | ||
| 675 | |||
| 676 | blk_set_default_limits(&ti_limits); | ||
| 677 | |||
| 678 | /* combine all target devices' limits */ | ||
| 679 | if (ti->type->iterate_devices) | ||
| 680 | ti->type->iterate_devices(ti, dm_set_device_limits, | ||
| 681 | &ti_limits); | ||
| 682 | |||
| 683 | /* | ||
| 684 | * If the remaining sectors fall entirely within this | ||
| 685 | * table entry are they compatible with its logical_block_size? | ||
| 686 | */ | ||
| 687 | if (remaining < ti->len && | ||
| 688 | remaining & ((ti_limits.logical_block_size >> | ||
| 689 | SECTOR_SHIFT) - 1)) | ||
| 690 | break; /* Error */ | ||
| 691 | |||
| 692 | next_target_start = | ||
| 693 | (unsigned short) ((next_target_start + ti->len) & | ||
| 694 | (device_logical_block_size_sects - 1)); | ||
| 695 | remaining = next_target_start ? | ||
| 696 | device_logical_block_size_sects - next_target_start : 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | if (remaining) { | ||
| 700 | DMWARN("%s: table line %u (start sect %llu len %llu) " | ||
| 701 | "not aligned to h/w logical block size %hu", | ||
| 702 | dm_device_name(table->md), i, | ||
| 703 | (unsigned long long) ti->begin, | ||
| 704 | (unsigned long long) ti->len, | ||
| 705 | limits->logical_block_size); | ||
| 706 | return -EINVAL; | ||
| 707 | } | ||
| 708 | |||
| 709 | return 0; | ||
| 696 | } | 710 | } |
| 697 | 711 | ||
| 698 | int dm_table_add_target(struct dm_table *t, const char *type, | 712 | int dm_table_add_target(struct dm_table *t, const char *type, |
| @@ -747,9 +761,6 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
| 747 | 761 | ||
| 748 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; | 762 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; |
| 749 | 763 | ||
| 750 | /* FIXME: the plan is to combine high here and then have | ||
| 751 | * the merge fn apply the target level restrictions. */ | ||
| 752 | combine_restrictions_low(&t->limits, &tgt->limits); | ||
| 753 | return 0; | 764 | return 0; |
| 754 | 765 | ||
| 755 | bad: | 766 | bad: |
| @@ -758,6 +769,104 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
| 758 | return r; | 769 | return r; |
| 759 | } | 770 | } |
| 760 | 771 | ||
| 772 | int dm_table_set_type(struct dm_table *t) | ||
| 773 | { | ||
| 774 | unsigned i; | ||
| 775 | unsigned bio_based = 0, request_based = 0; | ||
| 776 | struct dm_target *tgt; | ||
| 777 | struct dm_dev_internal *dd; | ||
| 778 | struct list_head *devices; | ||
| 779 | |||
| 780 | for (i = 0; i < t->num_targets; i++) { | ||
| 781 | tgt = t->targets + i; | ||
| 782 | if (dm_target_request_based(tgt)) | ||
| 783 | request_based = 1; | ||
| 784 | else | ||
| 785 | bio_based = 1; | ||
| 786 | |||
| 787 | if (bio_based && request_based) { | ||
| 788 | DMWARN("Inconsistent table: different target types" | ||
| 789 | " can't be mixed up"); | ||
| 790 | return -EINVAL; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | |||
| 794 | if (bio_based) { | ||
| 795 | /* We must use this table as bio-based */ | ||
| 796 | t->type = DM_TYPE_BIO_BASED; | ||
| 797 | return 0; | ||
| 798 | } | ||
| 799 | |||
| 800 | BUG_ON(!request_based); /* No targets in this table */ | ||
| 801 | |||
| 802 | /* Non-request-stackable devices can't be used for request-based dm */ | ||
| 803 | devices = dm_table_get_devices(t); | ||
| 804 | list_for_each_entry(dd, devices, list) { | ||
| 805 | if (!blk_queue_stackable(bdev_get_queue(dd->dm_dev.bdev))) { | ||
| 806 | DMWARN("table load rejected: including" | ||
| 807 | " non-request-stackable devices"); | ||
| 808 | return -EINVAL; | ||
| 809 | } | ||
| 810 | } | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Request-based dm supports only tables that have a single target now. | ||
| 814 | * To support multiple targets, request splitting support is needed, | ||
| 815 | * and that needs lots of changes in the block-layer. | ||
| 816 | * (e.g. request completion process for partial completion.) | ||
| 817 | */ | ||
| 818 | if (t->num_targets > 1) { | ||
| 819 | DMWARN("Request-based dm doesn't support multiple targets yet"); | ||
| 820 | return -EINVAL; | ||
| 821 | } | ||
| 822 | |||
| 823 | t->type = DM_TYPE_REQUEST_BASED; | ||
| 824 | |||
| 825 | return 0; | ||
| 826 | } | ||
| 827 | |||
| 828 | unsigned dm_table_get_type(struct dm_table *t) | ||
| 829 | { | ||
| 830 | return t->type; | ||
| 831 | } | ||
| 832 | |||
| 833 | bool dm_table_bio_based(struct dm_table *t) | ||
| 834 | { | ||
| 835 | return dm_table_get_type(t) == DM_TYPE_BIO_BASED; | ||
| 836 | } | ||
| 837 | |||
| 838 | bool dm_table_request_based(struct dm_table *t) | ||
| 839 | { | ||
| 840 | return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED; | ||
| 841 | } | ||
| 842 | |||
| 843 | int dm_table_alloc_md_mempools(struct dm_table *t) | ||
| 844 | { | ||
| 845 | unsigned type = dm_table_get_type(t); | ||
| 846 | |||
| 847 | if (unlikely(type == DM_TYPE_NONE)) { | ||
| 848 | DMWARN("no table type is set, can't allocate mempools"); | ||
| 849 | return -EINVAL; | ||
| 850 | } | ||
| 851 | |||
| 852 | t->mempools = dm_alloc_md_mempools(type); | ||
| 853 | if (!t->mempools) | ||
| 854 | return -ENOMEM; | ||
| 855 | |||
| 856 | return 0; | ||
| 857 | } | ||
| 858 | |||
| 859 | void dm_table_free_md_mempools(struct dm_table *t) | ||
| 860 | { | ||
| 861 | dm_free_md_mempools(t->mempools); | ||
| 862 | t->mempools = NULL; | ||
| 863 | } | ||
| 864 | |||
| 865 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t) | ||
| 866 | { | ||
| 867 | return t->mempools; | ||
| 868 | } | ||
| 869 | |||
| 761 | static int setup_indexes(struct dm_table *t) | 870 | static int setup_indexes(struct dm_table *t) |
| 762 | { | 871 | { |
| 763 | int i; | 872 | int i; |
| @@ -792,8 +901,6 @@ int dm_table_complete(struct dm_table *t) | |||
| 792 | int r = 0; | 901 | int r = 0; |
| 793 | unsigned int leaf_nodes; | 902 | unsigned int leaf_nodes; |
| 794 | 903 | ||
| 795 | check_for_valid_limits(&t->limits); | ||
| 796 | |||
| 797 | /* how many indexes will the btree have ? */ | 904 | /* how many indexes will the btree have ? */ |
| 798 | leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); | 905 | leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); |
| 799 | t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); | 906 | t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); |
| @@ -869,6 +976,57 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) | |||
| 869 | } | 976 | } |
| 870 | 977 | ||
| 871 | /* | 978 | /* |
| 979 | * Establish the new table's queue_limits and validate them. | ||
| 980 | */ | ||
| 981 | int dm_calculate_queue_limits(struct dm_table *table, | ||
| 982 | struct queue_limits *limits) | ||
| 983 | { | ||
| 984 | struct dm_target *uninitialized_var(ti); | ||
| 985 | struct queue_limits ti_limits; | ||
| 986 | unsigned i = 0; | ||
| 987 | |||
| 988 | blk_set_default_limits(limits); | ||
| 989 | |||
| 990 | while (i < dm_table_get_num_targets(table)) { | ||
| 991 | blk_set_default_limits(&ti_limits); | ||
| 992 | |||
| 993 | ti = dm_table_get_target(table, i++); | ||
| 994 | |||
| 995 | if (!ti->type->iterate_devices) | ||
| 996 | goto combine_limits; | ||
| 997 | |||
| 998 | /* | ||
| 999 | * Combine queue limits of all the devices this target uses. | ||
| 1000 | */ | ||
| 1001 | ti->type->iterate_devices(ti, dm_set_device_limits, | ||
| 1002 | &ti_limits); | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * Check each device area is consistent with the target's | ||
| 1006 | * overall queue limits. | ||
| 1007 | */ | ||
| 1008 | if (!ti->type->iterate_devices(ti, device_area_is_valid, | ||
| 1009 | &ti_limits)) | ||
| 1010 | return -EINVAL; | ||
| 1011 | |||
| 1012 | combine_limits: | ||
| 1013 | /* | ||
| 1014 | * Merge this target's queue limits into the overall limits | ||
| 1015 | * for the table. | ||
| 1016 | */ | ||
| 1017 | if (blk_stack_limits(limits, &ti_limits, 0) < 0) | ||
| 1018 | DMWARN("%s: target device " | ||
| 1019 | "(start sect %llu len %llu) " | ||
| 1020 | "is misaligned", | ||
| 1021 | dm_device_name(table->md), | ||
| 1022 | (unsigned long long) ti->begin, | ||
| 1023 | (unsigned long long) ti->len); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | return validate_hardware_logical_block_alignment(table, limits); | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | /* | ||
| 872 | * Set the integrity profile for this device if all devices used have | 1030 | * Set the integrity profile for this device if all devices used have |
| 873 | * matching profiles. | 1031 | * matching profiles. |
| 874 | */ | 1032 | */ |
| @@ -907,27 +1065,42 @@ no_integrity: | |||
| 907 | return; | 1065 | return; |
| 908 | } | 1066 | } |
| 909 | 1067 | ||
| 910 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) | 1068 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, |
| 1069 | struct queue_limits *limits) | ||
| 911 | { | 1070 | { |
| 912 | /* | 1071 | /* |
| 913 | * Make sure we obey the optimistic sub devices | 1072 | * Each target device in the table has a data area that should normally |
| 914 | * restrictions. | 1073 | * be aligned such that the DM device's alignment_offset is 0. |
| 1074 | * FIXME: Propagate alignment_offsets up the stack and warn of | ||
| 1075 | * sub-optimal or inconsistent settings. | ||
| 1076 | */ | ||
| 1077 | limits->alignment_offset = 0; | ||
| 1078 | limits->misaligned = 0; | ||
| 1079 | |||
| 1080 | /* | ||
| 1081 | * Copy table's limits to the DM device's request_queue | ||
| 915 | */ | 1082 | */ |
| 916 | blk_queue_max_sectors(q, t->limits.max_sectors); | 1083 | q->limits = *limits; |
| 917 | blk_queue_max_phys_segments(q, t->limits.max_phys_segments); | 1084 | |
| 918 | blk_queue_max_hw_segments(q, t->limits.max_hw_segments); | 1085 | if (limits->no_cluster) |
| 919 | blk_queue_logical_block_size(q, t->limits.logical_block_size); | ||
| 920 | blk_queue_max_segment_size(q, t->limits.max_segment_size); | ||
| 921 | blk_queue_max_hw_sectors(q, t->limits.max_hw_sectors); | ||
| 922 | blk_queue_segment_boundary(q, t->limits.seg_boundary_mask); | ||
| 923 | blk_queue_bounce_limit(q, t->limits.bounce_pfn); | ||
| 924 | |||
| 925 | if (t->limits.no_cluster) | ||
| 926 | queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); | 1086 | queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); |
| 927 | else | 1087 | else |
| 928 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); | 1088 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); |
| 929 | 1089 | ||
| 930 | dm_table_set_integrity(t); | 1090 | dm_table_set_integrity(t); |
| 1091 | |||
| 1092 | /* | ||
| 1093 | * QUEUE_FLAG_STACKABLE must be set after all queue settings are | ||
| 1094 | * visible to other CPUs because, once the flag is set, incoming bios | ||
| 1095 | * are processed by request-based dm, which refers to the queue | ||
| 1096 | * settings. | ||
| 1097 | * Until the flag set, bios are passed to bio-based dm and queued to | ||
| 1098 | * md->deferred where queue settings are not needed yet. | ||
| 1099 | * Those bios are passed to request-based dm at the resume time. | ||
| 1100 | */ | ||
| 1101 | smp_mb(); | ||
| 1102 | if (dm_table_request_based(t)) | ||
| 1103 | queue_flag_set_unlocked(QUEUE_FLAG_STACKABLE, q); | ||
| 931 | } | 1104 | } |
| 932 | 1105 | ||
| 933 | unsigned int dm_table_get_num_targets(struct dm_table *t) | 1106 | unsigned int dm_table_get_num_targets(struct dm_table *t) |
| @@ -1023,6 +1196,20 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits) | |||
| 1023 | return r; | 1196 | return r; |
| 1024 | } | 1197 | } |
| 1025 | 1198 | ||
| 1199 | int dm_table_any_busy_target(struct dm_table *t) | ||
| 1200 | { | ||
| 1201 | unsigned i; | ||
| 1202 | struct dm_target *ti; | ||
| 1203 | |||
| 1204 | for (i = 0; i < t->num_targets; i++) { | ||
| 1205 | ti = t->targets + i; | ||
| 1206 | if (ti->type->busy && ti->type->busy(ti)) | ||
| 1207 | return 1; | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | return 0; | ||
| 1211 | } | ||
| 1212 | |||
| 1026 | void dm_table_unplug_all(struct dm_table *t) | 1213 | void dm_table_unplug_all(struct dm_table *t) |
| 1027 | { | 1214 | { |
| 1028 | struct dm_dev_internal *dd; | 1215 | struct dm_dev_internal *dd; |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 48db308fae67..9acd54a5cffb 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -24,6 +24,13 @@ | |||
| 24 | 24 | ||
| 25 | #define DM_MSG_PREFIX "core" | 25 | #define DM_MSG_PREFIX "core" |
| 26 | 26 | ||
| 27 | /* | ||
| 28 | * Cookies are numeric values sent with CHANGE and REMOVE | ||
| 29 | * uevents while resuming, removing or renaming the device. | ||
| 30 | */ | ||
| 31 | #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE" | ||
| 32 | #define DM_COOKIE_LENGTH 24 | ||
| 33 | |||
| 27 | static const char *_name = DM_NAME; | 34 | static const char *_name = DM_NAME; |
| 28 | 35 | ||
| 29 | static unsigned int major = 0; | 36 | static unsigned int major = 0; |
| @@ -71,7 +78,7 @@ struct dm_rq_target_io { | |||
| 71 | */ | 78 | */ |
| 72 | struct dm_rq_clone_bio_info { | 79 | struct dm_rq_clone_bio_info { |
| 73 | struct bio *orig; | 80 | struct bio *orig; |
| 74 | struct request *rq; | 81 | struct dm_rq_target_io *tio; |
| 75 | }; | 82 | }; |
| 76 | 83 | ||
| 77 | union map_info *dm_get_mapinfo(struct bio *bio) | 84 | union map_info *dm_get_mapinfo(struct bio *bio) |
| @@ -81,6 +88,14 @@ union map_info *dm_get_mapinfo(struct bio *bio) | |||
| 81 | return NULL; | 88 | return NULL; |
| 82 | } | 89 | } |
| 83 | 90 | ||
| 91 | union map_info *dm_get_rq_mapinfo(struct request *rq) | ||
| 92 | { | ||
| 93 | if (rq && rq->end_io_data) | ||
| 94 | return &((struct dm_rq_target_io *)rq->end_io_data)->info; | ||
| 95 | return NULL; | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo); | ||
| 98 | |||
| 84 | #define MINOR_ALLOCED ((void *)-1) | 99 | #define MINOR_ALLOCED ((void *)-1) |
| 85 | 100 | ||
| 86 | /* | 101 | /* |
| @@ -157,13 +172,31 @@ struct mapped_device { | |||
| 157 | * freeze/thaw support require holding onto a super block | 172 | * freeze/thaw support require holding onto a super block |
| 158 | */ | 173 | */ |
| 159 | struct super_block *frozen_sb; | 174 | struct super_block *frozen_sb; |
| 160 | struct block_device *suspended_bdev; | 175 | struct block_device *bdev; |
| 161 | 176 | ||
| 162 | /* forced geometry settings */ | 177 | /* forced geometry settings */ |
| 163 | struct hd_geometry geometry; | 178 | struct hd_geometry geometry; |
| 164 | 179 | ||
| 180 | /* marker of flush suspend for request-based dm */ | ||
| 181 | struct request suspend_rq; | ||
| 182 | |||
| 183 | /* For saving the address of __make_request for request based dm */ | ||
| 184 | make_request_fn *saved_make_request_fn; | ||
| 185 | |||
| 165 | /* sysfs handle */ | 186 | /* sysfs handle */ |
| 166 | struct kobject kobj; | 187 | struct kobject kobj; |
| 188 | |||
| 189 | /* zero-length barrier that will be cloned and submitted to targets */ | ||
| 190 | struct bio barrier_bio; | ||
| 191 | }; | ||
| 192 | |||
| 193 | /* | ||
| 194 | * For mempools pre-allocation at the table loading time. | ||
| 195 | */ | ||
| 196 | struct dm_md_mempools { | ||
| 197 | mempool_t *io_pool; | ||
| 198 | mempool_t *tio_pool; | ||
| 199 | struct bio_set *bs; | ||
| 167 | }; | 200 | }; |
| 168 | 201 | ||
| 169 | #define MIN_IOS 256 | 202 | #define MIN_IOS 256 |
| @@ -391,14 +424,29 @@ static void free_io(struct mapped_device *md, struct dm_io *io) | |||
| 391 | mempool_free(io, md->io_pool); | 424 | mempool_free(io, md->io_pool); |
| 392 | } | 425 | } |
| 393 | 426 | ||
| 394 | static struct dm_target_io *alloc_tio(struct mapped_device *md) | 427 | static void free_tio(struct mapped_device *md, struct dm_target_io *tio) |
| 395 | { | 428 | { |
| 396 | return mempool_alloc(md->tio_pool, GFP_NOIO); | 429 | mempool_free(tio, md->tio_pool); |
| 397 | } | 430 | } |
| 398 | 431 | ||
| 399 | static void free_tio(struct mapped_device *md, struct dm_target_io *tio) | 432 | static struct dm_rq_target_io *alloc_rq_tio(struct mapped_device *md) |
| 400 | { | 433 | { |
| 401 | mempool_free(tio, md->tio_pool); | 434 | return mempool_alloc(md->tio_pool, GFP_ATOMIC); |
| 435 | } | ||
| 436 | |||
| 437 | static void free_rq_tio(struct dm_rq_target_io *tio) | ||
| 438 | { | ||
| 439 | mempool_free(tio, tio->md->tio_pool); | ||
| 440 | } | ||
| 441 | |||
| 442 | static struct dm_rq_clone_bio_info *alloc_bio_info(struct mapped_device *md) | ||
| 443 | { | ||
| 444 | return mempool_alloc(md->io_pool, GFP_ATOMIC); | ||
| 445 | } | ||
| 446 | |||
| 447 | static void free_bio_info(struct dm_rq_clone_bio_info *info) | ||
| 448 | { | ||
| 449 | mempool_free(info, info->tio->md->io_pool); | ||
| 402 | } | 450 | } |
| 403 | 451 | ||
| 404 | static void start_io_acct(struct dm_io *io) | 452 | static void start_io_acct(struct dm_io *io) |
| @@ -464,12 +512,13 @@ static void queue_io(struct mapped_device *md, struct bio *bio) | |||
| 464 | struct dm_table *dm_get_table(struct mapped_device *md) | 512 | struct dm_table *dm_get_table(struct mapped_device *md) |
| 465 | { | 513 | { |
| 466 | struct dm_table *t; | 514 | struct dm_table *t; |
| 515 | unsigned long flags; | ||
| 467 | 516 | ||
| 468 | read_lock(&md->map_lock); | 517 | read_lock_irqsave(&md->map_lock, flags); |
| 469 | t = md->map; | 518 | t = md->map; |
| 470 | if (t) | 519 | if (t) |
| 471 | dm_table_get(t); | 520 | dm_table_get(t); |
| 472 | read_unlock(&md->map_lock); | 521 | read_unlock_irqrestore(&md->map_lock, flags); |
| 473 | 522 | ||
| 474 | return t; | 523 | return t; |
| 475 | } | 524 | } |
| @@ -536,9 +585,11 @@ static void dec_pending(struct dm_io *io, int error) | |||
| 536 | * Target requested pushing back the I/O. | 585 | * Target requested pushing back the I/O. |
| 537 | */ | 586 | */ |
| 538 | spin_lock_irqsave(&md->deferred_lock, flags); | 587 | spin_lock_irqsave(&md->deferred_lock, flags); |
| 539 | if (__noflush_suspending(md)) | 588 | if (__noflush_suspending(md)) { |
| 540 | bio_list_add_head(&md->deferred, io->bio); | 589 | if (!bio_barrier(io->bio)) |
| 541 | else | 590 | bio_list_add_head(&md->deferred, |
| 591 | io->bio); | ||
| 592 | } else | ||
| 542 | /* noflush suspend was interrupted. */ | 593 | /* noflush suspend was interrupted. */ |
| 543 | io->error = -EIO; | 594 | io->error = -EIO; |
| 544 | spin_unlock_irqrestore(&md->deferred_lock, flags); | 595 | spin_unlock_irqrestore(&md->deferred_lock, flags); |
| @@ -553,7 +604,8 @@ static void dec_pending(struct dm_io *io, int error) | |||
| 553 | * a per-device variable for error reporting. | 604 | * a per-device variable for error reporting. |
| 554 | * Note that you can't touch the bio after end_io_acct | 605 | * Note that you can't touch the bio after end_io_acct |
| 555 | */ | 606 | */ |
| 556 | md->barrier_error = io_error; | 607 | if (!md->barrier_error && io_error != -EOPNOTSUPP) |
| 608 | md->barrier_error = io_error; | ||
| 557 | end_io_acct(io); | 609 | end_io_acct(io); |
| 558 | } else { | 610 | } else { |
| 559 | end_io_acct(io); | 611 | end_io_acct(io); |
| @@ -607,6 +659,262 @@ static void clone_endio(struct bio *bio, int error) | |||
| 607 | dec_pending(io, error); | 659 | dec_pending(io, error); |
| 608 | } | 660 | } |
| 609 | 661 | ||
| 662 | /* | ||
| 663 | * Partial completion handling for request-based dm | ||
| 664 | */ | ||
| 665 | static void end_clone_bio(struct bio *clone, int error) | ||
| 666 | { | ||
| 667 | struct dm_rq_clone_bio_info *info = clone->bi_private; | ||
| 668 | struct dm_rq_target_io *tio = info->tio; | ||
| 669 | struct bio *bio = info->orig; | ||
| 670 | unsigned int nr_bytes = info->orig->bi_size; | ||
| 671 | |||
| 672 | bio_put(clone); | ||
| 673 | |||
| 674 | if (tio->error) | ||
| 675 | /* | ||
| 676 | * An error has already been detected on the request. | ||
| 677 | * Once error occurred, just let clone->end_io() handle | ||
| 678 | * the remainder. | ||
| 679 | */ | ||
| 680 | return; | ||
| 681 | else if (error) { | ||
| 682 | /* | ||
| 683 | * Don't notice the error to the upper layer yet. | ||
| 684 | * The error handling decision is made by the target driver, | ||
| 685 | * when the request is completed. | ||
| 686 | */ | ||
| 687 | tio->error = error; | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | /* | ||
| 692 | * I/O for the bio successfully completed. | ||
| 693 | * Notice the data completion to the upper layer. | ||
| 694 | */ | ||
| 695 | |||
| 696 | /* | ||
| 697 | * bios are processed from the head of the list. | ||
| 698 | * So the completing bio should always be rq->bio. | ||
| 699 | * If it's not, something wrong is happening. | ||
| 700 | */ | ||
| 701 | if (tio->orig->bio != bio) | ||
| 702 | DMERR("bio completion is going in the middle of the request"); | ||
| 703 | |||
| 704 | /* | ||
| 705 | * Update the original request. | ||
| 706 | * Do not use blk_end_request() here, because it may complete | ||
| 707 | * the original request before the clone, and break the ordering. | ||
| 708 | */ | ||
| 709 | blk_update_request(tio->orig, 0, nr_bytes); | ||
| 710 | } | ||
| 711 | |||
| 712 | /* | ||
| 713 | * Don't touch any member of the md after calling this function because | ||
| 714 | * the md may be freed in dm_put() at the end of this function. | ||
| 715 | * Or do dm_get() before calling this function and dm_put() later. | ||
| 716 | */ | ||
| 717 | static void rq_completed(struct mapped_device *md, int run_queue) | ||
| 718 | { | ||
| 719 | int wakeup_waiters = 0; | ||
| 720 | struct request_queue *q = md->queue; | ||
| 721 | unsigned long flags; | ||
| 722 | |||
| 723 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 724 | if (!queue_in_flight(q)) | ||
| 725 | wakeup_waiters = 1; | ||
| 726 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 727 | |||
| 728 | /* nudge anyone waiting on suspend queue */ | ||
| 729 | if (wakeup_waiters) | ||
| 730 | wake_up(&md->wait); | ||
| 731 | |||
| 732 | if (run_queue) | ||
| 733 | blk_run_queue(q); | ||
| 734 | |||
| 735 | /* | ||
| 736 | * dm_put() must be at the end of this function. See the comment above | ||
| 737 | */ | ||
| 738 | dm_put(md); | ||
| 739 | } | ||
| 740 | |||
| 741 | static void dm_unprep_request(struct request *rq) | ||
| 742 | { | ||
| 743 | struct request *clone = rq->special; | ||
| 744 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 745 | |||
| 746 | rq->special = NULL; | ||
| 747 | rq->cmd_flags &= ~REQ_DONTPREP; | ||
| 748 | |||
| 749 | blk_rq_unprep_clone(clone); | ||
| 750 | free_rq_tio(tio); | ||
| 751 | } | ||
| 752 | |||
| 753 | /* | ||
| 754 | * Requeue the original request of a clone. | ||
| 755 | */ | ||
| 756 | void dm_requeue_unmapped_request(struct request *clone) | ||
| 757 | { | ||
| 758 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 759 | struct mapped_device *md = tio->md; | ||
| 760 | struct request *rq = tio->orig; | ||
| 761 | struct request_queue *q = rq->q; | ||
| 762 | unsigned long flags; | ||
| 763 | |||
| 764 | dm_unprep_request(rq); | ||
| 765 | |||
| 766 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 767 | if (elv_queue_empty(q)) | ||
| 768 | blk_plug_device(q); | ||
| 769 | blk_requeue_request(q, rq); | ||
| 770 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 771 | |||
| 772 | rq_completed(md, 0); | ||
| 773 | } | ||
| 774 | EXPORT_SYMBOL_GPL(dm_requeue_unmapped_request); | ||
| 775 | |||
| 776 | static void __stop_queue(struct request_queue *q) | ||
| 777 | { | ||
| 778 | blk_stop_queue(q); | ||
| 779 | } | ||
| 780 | |||
| 781 | static void stop_queue(struct request_queue *q) | ||
| 782 | { | ||
| 783 | unsigned long flags; | ||
| 784 | |||
| 785 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 786 | __stop_queue(q); | ||
| 787 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 788 | } | ||
| 789 | |||
| 790 | static void __start_queue(struct request_queue *q) | ||
| 791 | { | ||
| 792 | if (blk_queue_stopped(q)) | ||
| 793 | blk_start_queue(q); | ||
| 794 | } | ||
| 795 | |||
| 796 | static void start_queue(struct request_queue *q) | ||
| 797 | { | ||
| 798 | unsigned long flags; | ||
| 799 | |||
| 800 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 801 | __start_queue(q); | ||
| 802 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 803 | } | ||
| 804 | |||
| 805 | /* | ||
| 806 | * Complete the clone and the original request. | ||
| 807 | * Must be called without queue lock. | ||
| 808 | */ | ||
| 809 | static void dm_end_request(struct request *clone, int error) | ||
| 810 | { | ||
| 811 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 812 | struct mapped_device *md = tio->md; | ||
| 813 | struct request *rq = tio->orig; | ||
| 814 | |||
| 815 | if (blk_pc_request(rq)) { | ||
| 816 | rq->errors = clone->errors; | ||
| 817 | rq->resid_len = clone->resid_len; | ||
| 818 | |||
| 819 | if (rq->sense) | ||
| 820 | /* | ||
| 821 | * We are using the sense buffer of the original | ||
| 822 | * request. | ||
| 823 | * So setting the length of the sense data is enough. | ||
| 824 | */ | ||
| 825 | rq->sense_len = clone->sense_len; | ||
| 826 | } | ||
| 827 | |||
| 828 | BUG_ON(clone->bio); | ||
| 829 | free_rq_tio(tio); | ||
| 830 | |||
| 831 | blk_end_request_all(rq, error); | ||
| 832 | |||
| 833 | rq_completed(md, 1); | ||
| 834 | } | ||
| 835 | |||
| 836 | /* | ||
| 837 | * Request completion handler for request-based dm | ||
| 838 | */ | ||
| 839 | static void dm_softirq_done(struct request *rq) | ||
| 840 | { | ||
| 841 | struct request *clone = rq->completion_data; | ||
| 842 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 843 | dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io; | ||
| 844 | int error = tio->error; | ||
| 845 | |||
| 846 | if (!(rq->cmd_flags & REQ_FAILED) && rq_end_io) | ||
| 847 | error = rq_end_io(tio->ti, clone, error, &tio->info); | ||
| 848 | |||
| 849 | if (error <= 0) | ||
| 850 | /* The target wants to complete the I/O */ | ||
| 851 | dm_end_request(clone, error); | ||
| 852 | else if (error == DM_ENDIO_INCOMPLETE) | ||
| 853 | /* The target will handle the I/O */ | ||
| 854 | return; | ||
| 855 | else if (error == DM_ENDIO_REQUEUE) | ||
| 856 | /* The target wants to requeue the I/O */ | ||
| 857 | dm_requeue_unmapped_request(clone); | ||
| 858 | else { | ||
| 859 | DMWARN("unimplemented target endio return value: %d", error); | ||
| 860 | BUG(); | ||
| 861 | } | ||
| 862 | } | ||
| 863 | |||
| 864 | /* | ||
| 865 | * Complete the clone and the original request with the error status | ||
| 866 | * through softirq context. | ||
| 867 | */ | ||
| 868 | static void dm_complete_request(struct request *clone, int error) | ||
| 869 | { | ||
| 870 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 871 | struct request *rq = tio->orig; | ||
| 872 | |||
| 873 | tio->error = error; | ||
| 874 | rq->completion_data = clone; | ||
| 875 | blk_complete_request(rq); | ||
| 876 | } | ||
| 877 | |||
| 878 | /* | ||
| 879 | * Complete the not-mapped clone and the original request with the error status | ||
| 880 | * through softirq context. | ||
| 881 | * Target's rq_end_io() function isn't called. | ||
| 882 | * This may be used when the target's map_rq() function fails. | ||
| 883 | */ | ||
| 884 | void dm_kill_unmapped_request(struct request *clone, int error) | ||
| 885 | { | ||
| 886 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 887 | struct request *rq = tio->orig; | ||
| 888 | |||
| 889 | rq->cmd_flags |= REQ_FAILED; | ||
| 890 | dm_complete_request(clone, error); | ||
| 891 | } | ||
| 892 | EXPORT_SYMBOL_GPL(dm_kill_unmapped_request); | ||
| 893 | |||
| 894 | /* | ||
| 895 | * Called with the queue lock held | ||
| 896 | */ | ||
| 897 | static void end_clone_request(struct request *clone, int error) | ||
| 898 | { | ||
| 899 | /* | ||
| 900 | * For just cleaning up the information of the queue in which | ||
| 901 | * the clone was dispatched. | ||
| 902 | * The clone is *NOT* freed actually here because it is alloced from | ||
| 903 | * dm own mempool and REQ_ALLOCED isn't set in clone->cmd_flags. | ||
| 904 | */ | ||
| 905 | __blk_put_request(clone->q, clone); | ||
| 906 | |||
| 907 | /* | ||
| 908 | * Actual request completion is done in a softirq context which doesn't | ||
| 909 | * hold the queue lock. Otherwise, deadlock could occur because: | ||
| 910 | * - another request may be submitted by the upper level driver | ||
| 911 | * of the stacking during the completion | ||
| 912 | * - the submission which requires queue lock may be done | ||
| 913 | * against this queue | ||
| 914 | */ | ||
| 915 | dm_complete_request(clone, error); | ||
| 916 | } | ||
| 917 | |||
| 610 | static sector_t max_io_len(struct mapped_device *md, | 918 | static sector_t max_io_len(struct mapped_device *md, |
| 611 | sector_t sector, struct dm_target *ti) | 919 | sector_t sector, struct dm_target *ti) |
| 612 | { | 920 | { |
| @@ -634,11 +942,6 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, | |||
| 634 | sector_t sector; | 942 | sector_t sector; |
| 635 | struct mapped_device *md; | 943 | struct mapped_device *md; |
| 636 | 944 | ||
| 637 | /* | ||
| 638 | * Sanity checks. | ||
| 639 | */ | ||
| 640 | BUG_ON(!clone->bi_size); | ||
| 641 | |||
| 642 | clone->bi_end_io = clone_endio; | 945 | clone->bi_end_io = clone_endio; |
| 643 | clone->bi_private = tio; | 946 | clone->bi_private = tio; |
| 644 | 947 | ||
| @@ -714,7 +1017,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, | |||
| 714 | clone->bi_flags |= 1 << BIO_CLONED; | 1017 | clone->bi_flags |= 1 << BIO_CLONED; |
| 715 | 1018 | ||
| 716 | if (bio_integrity(bio)) { | 1019 | if (bio_integrity(bio)) { |
| 717 | bio_integrity_clone(clone, bio, GFP_NOIO); | 1020 | bio_integrity_clone(clone, bio, GFP_NOIO, bs); |
| 718 | bio_integrity_trim(clone, | 1021 | bio_integrity_trim(clone, |
| 719 | bio_sector_offset(bio, idx, offset), len); | 1022 | bio_sector_offset(bio, idx, offset), len); |
| 720 | } | 1023 | } |
| @@ -742,7 +1045,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, | |||
| 742 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); | 1045 | clone->bi_flags &= ~(1 << BIO_SEG_VALID); |
| 743 | 1046 | ||
| 744 | if (bio_integrity(bio)) { | 1047 | if (bio_integrity(bio)) { |
| 745 | bio_integrity_clone(clone, bio, GFP_NOIO); | 1048 | bio_integrity_clone(clone, bio, GFP_NOIO, bs); |
| 746 | 1049 | ||
| 747 | if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) | 1050 | if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) |
| 748 | bio_integrity_trim(clone, | 1051 | bio_integrity_trim(clone, |
| @@ -752,6 +1055,48 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, | |||
| 752 | return clone; | 1055 | return clone; |
| 753 | } | 1056 | } |
| 754 | 1057 | ||
| 1058 | static struct dm_target_io *alloc_tio(struct clone_info *ci, | ||
| 1059 | struct dm_target *ti) | ||
| 1060 | { | ||
| 1061 | struct dm_target_io *tio = mempool_alloc(ci->md->tio_pool, GFP_NOIO); | ||
| 1062 | |||
| 1063 | tio->io = ci->io; | ||
| 1064 | tio->ti = ti; | ||
| 1065 | memset(&tio->info, 0, sizeof(tio->info)); | ||
| 1066 | |||
| 1067 | return tio; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static void __flush_target(struct clone_info *ci, struct dm_target *ti, | ||
| 1071 | unsigned flush_nr) | ||
| 1072 | { | ||
| 1073 | struct dm_target_io *tio = alloc_tio(ci, ti); | ||
| 1074 | struct bio *clone; | ||
| 1075 | |||
| 1076 | tio->info.flush_request = flush_nr; | ||
| 1077 | |||
| 1078 | clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs); | ||
| 1079 | __bio_clone(clone, ci->bio); | ||
| 1080 | clone->bi_destructor = dm_bio_destructor; | ||
| 1081 | |||
| 1082 | __map_bio(ti, clone, tio); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static int __clone_and_map_empty_barrier(struct clone_info *ci) | ||
| 1086 | { | ||
| 1087 | unsigned target_nr = 0, flush_nr; | ||
| 1088 | struct dm_target *ti; | ||
| 1089 | |||
| 1090 | while ((ti = dm_table_get_target(ci->map, target_nr++))) | ||
| 1091 | for (flush_nr = 0; flush_nr < ti->num_flush_requests; | ||
| 1092 | flush_nr++) | ||
| 1093 | __flush_target(ci, ti, flush_nr); | ||
| 1094 | |||
| 1095 | ci->sector_count = 0; | ||
| 1096 | |||
| 1097 | return 0; | ||
| 1098 | } | ||
| 1099 | |||
| 755 | static int __clone_and_map(struct clone_info *ci) | 1100 | static int __clone_and_map(struct clone_info *ci) |
| 756 | { | 1101 | { |
| 757 | struct bio *clone, *bio = ci->bio; | 1102 | struct bio *clone, *bio = ci->bio; |
| @@ -759,6 +1104,9 @@ static int __clone_and_map(struct clone_info *ci) | |||
| 759 | sector_t len = 0, max; | 1104 | sector_t len = 0, max; |
| 760 | struct dm_target_io *tio; | 1105 | struct dm_target_io *tio; |
| 761 | 1106 | ||
| 1107 | if (unlikely(bio_empty_barrier(bio))) | ||
| 1108 | return __clone_and_map_empty_barrier(ci); | ||
| 1109 | |||
| 762 | ti = dm_table_find_target(ci->map, ci->sector); | 1110 | ti = dm_table_find_target(ci->map, ci->sector); |
| 763 | if (!dm_target_is_valid(ti)) | 1111 | if (!dm_target_is_valid(ti)) |
| 764 | return -EIO; | 1112 | return -EIO; |
| @@ -768,10 +1116,7 @@ static int __clone_and_map(struct clone_info *ci) | |||
| 768 | /* | 1116 | /* |
| 769 | * Allocate a target io object. | 1117 | * Allocate a target io object. |
| 770 | */ | 1118 | */ |
| 771 | tio = alloc_tio(ci->md); | 1119 | tio = alloc_tio(ci, ti); |
| 772 | tio->io = ci->io; | ||
| 773 | tio->ti = ti; | ||
| 774 | memset(&tio->info, 0, sizeof(tio->info)); | ||
| 775 | 1120 | ||
| 776 | if (ci->sector_count <= max) { | 1121 | if (ci->sector_count <= max) { |
| 777 | /* | 1122 | /* |
| @@ -827,10 +1172,7 @@ static int __clone_and_map(struct clone_info *ci) | |||
| 827 | 1172 | ||
| 828 | max = max_io_len(ci->md, ci->sector, ti); | 1173 | max = max_io_len(ci->md, ci->sector, ti); |
| 829 | 1174 | ||
| 830 | tio = alloc_tio(ci->md); | 1175 | tio = alloc_tio(ci, ti); |
| 831 | tio->io = ci->io; | ||
| 832 | tio->ti = ti; | ||
| 833 | memset(&tio->info, 0, sizeof(tio->info)); | ||
| 834 | } | 1176 | } |
| 835 | 1177 | ||
| 836 | len = min(remaining, max); | 1178 | len = min(remaining, max); |
| @@ -865,7 +1207,8 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) | |||
| 865 | if (!bio_barrier(bio)) | 1207 | if (!bio_barrier(bio)) |
| 866 | bio_io_error(bio); | 1208 | bio_io_error(bio); |
| 867 | else | 1209 | else |
| 868 | md->barrier_error = -EIO; | 1210 | if (!md->barrier_error) |
| 1211 | md->barrier_error = -EIO; | ||
| 869 | return; | 1212 | return; |
| 870 | } | 1213 | } |
| 871 | 1214 | ||
| @@ -878,6 +1221,8 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) | |||
| 878 | ci.io->md = md; | 1221 | ci.io->md = md; |
| 879 | ci.sector = bio->bi_sector; | 1222 | ci.sector = bio->bi_sector; |
| 880 | ci.sector_count = bio_sectors(bio); | 1223 | ci.sector_count = bio_sectors(bio); |
| 1224 | if (unlikely(bio_empty_barrier(bio))) | ||
| 1225 | ci.sector_count = 1; | ||
| 881 | ci.idx = bio->bi_idx; | 1226 | ci.idx = bio->bi_idx; |
| 882 | 1227 | ||
| 883 | start_io_acct(ci.io); | 1228 | start_io_acct(ci.io); |
| @@ -925,6 +1270,16 @@ static int dm_merge_bvec(struct request_queue *q, | |||
| 925 | */ | 1270 | */ |
| 926 | if (max_size && ti->type->merge) | 1271 | if (max_size && ti->type->merge) |
| 927 | max_size = ti->type->merge(ti, bvm, biovec, max_size); | 1272 | max_size = ti->type->merge(ti, bvm, biovec, max_size); |
| 1273 | /* | ||
| 1274 | * If the target doesn't support merge method and some of the devices | ||
| 1275 | * provided their merge_bvec method (we know this by looking at | ||
| 1276 | * queue_max_hw_sectors), then we can't allow bios with multiple vector | ||
| 1277 | * entries. So always set max_size to 0, and the code below allows | ||
| 1278 | * just one page. | ||
| 1279 | */ | ||
| 1280 | else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9) | ||
| 1281 | |||
| 1282 | max_size = 0; | ||
| 928 | 1283 | ||
| 929 | out_table: | 1284 | out_table: |
| 930 | dm_table_put(map); | 1285 | dm_table_put(map); |
| @@ -943,7 +1298,7 @@ out: | |||
| 943 | * The request function that just remaps the bio built up by | 1298 | * The request function that just remaps the bio built up by |
| 944 | * dm_merge_bvec. | 1299 | * dm_merge_bvec. |
| 945 | */ | 1300 | */ |
| 946 | static int dm_request(struct request_queue *q, struct bio *bio) | 1301 | static int _dm_request(struct request_queue *q, struct bio *bio) |
| 947 | { | 1302 | { |
| 948 | int rw = bio_data_dir(bio); | 1303 | int rw = bio_data_dir(bio); |
| 949 | struct mapped_device *md = q->queuedata; | 1304 | struct mapped_device *md = q->queuedata; |
| @@ -980,12 +1335,274 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
| 980 | return 0; | 1335 | return 0; |
| 981 | } | 1336 | } |
| 982 | 1337 | ||
| 1338 | static int dm_make_request(struct request_queue *q, struct bio *bio) | ||
| 1339 | { | ||
| 1340 | struct mapped_device *md = q->queuedata; | ||
| 1341 | |||
| 1342 | if (unlikely(bio_barrier(bio))) { | ||
| 1343 | bio_endio(bio, -EOPNOTSUPP); | ||
| 1344 | return 0; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | return md->saved_make_request_fn(q, bio); /* call __make_request() */ | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | static int dm_request_based(struct mapped_device *md) | ||
| 1351 | { | ||
| 1352 | return blk_queue_stackable(md->queue); | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | static int dm_request(struct request_queue *q, struct bio *bio) | ||
| 1356 | { | ||
| 1357 | struct mapped_device *md = q->queuedata; | ||
| 1358 | |||
| 1359 | if (dm_request_based(md)) | ||
| 1360 | return dm_make_request(q, bio); | ||
| 1361 | |||
| 1362 | return _dm_request(q, bio); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | void dm_dispatch_request(struct request *rq) | ||
| 1366 | { | ||
| 1367 | int r; | ||
| 1368 | |||
| 1369 | if (blk_queue_io_stat(rq->q)) | ||
| 1370 | rq->cmd_flags |= REQ_IO_STAT; | ||
| 1371 | |||
| 1372 | rq->start_time = jiffies; | ||
| 1373 | r = blk_insert_cloned_request(rq->q, rq); | ||
| 1374 | if (r) | ||
| 1375 | dm_complete_request(rq, r); | ||
| 1376 | } | ||
| 1377 | EXPORT_SYMBOL_GPL(dm_dispatch_request); | ||
| 1378 | |||
| 1379 | static void dm_rq_bio_destructor(struct bio *bio) | ||
| 1380 | { | ||
| 1381 | struct dm_rq_clone_bio_info *info = bio->bi_private; | ||
| 1382 | struct mapped_device *md = info->tio->md; | ||
| 1383 | |||
| 1384 | free_bio_info(info); | ||
| 1385 | bio_free(bio, md->bs); | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig, | ||
| 1389 | void *data) | ||
| 1390 | { | ||
| 1391 | struct dm_rq_target_io *tio = data; | ||
| 1392 | struct mapped_device *md = tio->md; | ||
| 1393 | struct dm_rq_clone_bio_info *info = alloc_bio_info(md); | ||
| 1394 | |||
| 1395 | if (!info) | ||
| 1396 | return -ENOMEM; | ||
| 1397 | |||
| 1398 | info->orig = bio_orig; | ||
| 1399 | info->tio = tio; | ||
| 1400 | bio->bi_end_io = end_clone_bio; | ||
| 1401 | bio->bi_private = info; | ||
| 1402 | bio->bi_destructor = dm_rq_bio_destructor; | ||
| 1403 | |||
| 1404 | return 0; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | static int setup_clone(struct request *clone, struct request *rq, | ||
| 1408 | struct dm_rq_target_io *tio) | ||
| 1409 | { | ||
| 1410 | int r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC, | ||
| 1411 | dm_rq_bio_constructor, tio); | ||
| 1412 | |||
| 1413 | if (r) | ||
| 1414 | return r; | ||
| 1415 | |||
| 1416 | clone->cmd = rq->cmd; | ||
| 1417 | clone->cmd_len = rq->cmd_len; | ||
| 1418 | clone->sense = rq->sense; | ||
| 1419 | clone->buffer = rq->buffer; | ||
| 1420 | clone->end_io = end_clone_request; | ||
| 1421 | clone->end_io_data = tio; | ||
| 1422 | |||
| 1423 | return 0; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | static int dm_rq_flush_suspending(struct mapped_device *md) | ||
| 1427 | { | ||
| 1428 | return !md->suspend_rq.special; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | /* | ||
| 1432 | * Called with the queue lock held. | ||
| 1433 | */ | ||
| 1434 | static int dm_prep_fn(struct request_queue *q, struct request *rq) | ||
| 1435 | { | ||
| 1436 | struct mapped_device *md = q->queuedata; | ||
| 1437 | struct dm_rq_target_io *tio; | ||
| 1438 | struct request *clone; | ||
| 1439 | |||
| 1440 | if (unlikely(rq == &md->suspend_rq)) { | ||
| 1441 | if (dm_rq_flush_suspending(md)) | ||
| 1442 | return BLKPREP_OK; | ||
| 1443 | else | ||
| 1444 | /* The flush suspend was interrupted */ | ||
| 1445 | return BLKPREP_KILL; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | if (unlikely(rq->special)) { | ||
| 1449 | DMWARN("Already has something in rq->special."); | ||
| 1450 | return BLKPREP_KILL; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | tio = alloc_rq_tio(md); /* Only one for each original request */ | ||
| 1454 | if (!tio) | ||
| 1455 | /* -ENOMEM */ | ||
| 1456 | return BLKPREP_DEFER; | ||
| 1457 | |||
| 1458 | tio->md = md; | ||
| 1459 | tio->ti = NULL; | ||
| 1460 | tio->orig = rq; | ||
| 1461 | tio->error = 0; | ||
| 1462 | memset(&tio->info, 0, sizeof(tio->info)); | ||
| 1463 | |||
| 1464 | clone = &tio->clone; | ||
| 1465 | if (setup_clone(clone, rq, tio)) { | ||
| 1466 | /* -ENOMEM */ | ||
| 1467 | free_rq_tio(tio); | ||
| 1468 | return BLKPREP_DEFER; | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | rq->special = clone; | ||
| 1472 | rq->cmd_flags |= REQ_DONTPREP; | ||
| 1473 | |||
| 1474 | return BLKPREP_OK; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | static void map_request(struct dm_target *ti, struct request *rq, | ||
| 1478 | struct mapped_device *md) | ||
| 1479 | { | ||
| 1480 | int r; | ||
| 1481 | struct request *clone = rq->special; | ||
| 1482 | struct dm_rq_target_io *tio = clone->end_io_data; | ||
| 1483 | |||
| 1484 | /* | ||
| 1485 | * Hold the md reference here for the in-flight I/O. | ||
| 1486 | * We can't rely on the reference count by device opener, | ||
| 1487 | * because the device may be closed during the request completion | ||
| 1488 | * when all bios are completed. | ||
| 1489 | * See the comment in rq_completed() too. | ||
| 1490 | */ | ||
| 1491 | dm_get(md); | ||
| 1492 | |||
| 1493 | tio->ti = ti; | ||
| 1494 | r = ti->type->map_rq(ti, clone, &tio->info); | ||
| 1495 | switch (r) { | ||
| 1496 | case DM_MAPIO_SUBMITTED: | ||
| 1497 | /* The target has taken the I/O to submit by itself later */ | ||
| 1498 | break; | ||
| 1499 | case DM_MAPIO_REMAPPED: | ||
| 1500 | /* The target has remapped the I/O so dispatch it */ | ||
| 1501 | dm_dispatch_request(clone); | ||
| 1502 | break; | ||
| 1503 | case DM_MAPIO_REQUEUE: | ||
| 1504 | /* The target wants to requeue the I/O */ | ||
| 1505 | dm_requeue_unmapped_request(clone); | ||
| 1506 | break; | ||
| 1507 | default: | ||
| 1508 | if (r > 0) { | ||
| 1509 | DMWARN("unimplemented target map return value: %d", r); | ||
| 1510 | BUG(); | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | /* The target wants to complete the I/O */ | ||
| 1514 | dm_kill_unmapped_request(clone, r); | ||
| 1515 | break; | ||
| 1516 | } | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | /* | ||
| 1520 | * q->request_fn for request-based dm. | ||
| 1521 | * Called with the queue lock held. | ||
| 1522 | */ | ||
| 1523 | static void dm_request_fn(struct request_queue *q) | ||
| 1524 | { | ||
| 1525 | struct mapped_device *md = q->queuedata; | ||
| 1526 | struct dm_table *map = dm_get_table(md); | ||
| 1527 | struct dm_target *ti; | ||
| 1528 | struct request *rq; | ||
| 1529 | |||
| 1530 | /* | ||
| 1531 | * For noflush suspend, check blk_queue_stopped() to immediately | ||
| 1532 | * quit I/O dispatching. | ||
| 1533 | */ | ||
| 1534 | while (!blk_queue_plugged(q) && !blk_queue_stopped(q)) { | ||
| 1535 | rq = blk_peek_request(q); | ||
| 1536 | if (!rq) | ||
| 1537 | goto plug_and_out; | ||
| 1538 | |||
| 1539 | if (unlikely(rq == &md->suspend_rq)) { /* Flush suspend maker */ | ||
| 1540 | if (queue_in_flight(q)) | ||
| 1541 | /* Not quiet yet. Wait more */ | ||
| 1542 | goto plug_and_out; | ||
| 1543 | |||
| 1544 | /* This device should be quiet now */ | ||
| 1545 | __stop_queue(q); | ||
| 1546 | blk_start_request(rq); | ||
| 1547 | __blk_end_request_all(rq, 0); | ||
| 1548 | wake_up(&md->wait); | ||
| 1549 | goto out; | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | ti = dm_table_find_target(map, blk_rq_pos(rq)); | ||
| 1553 | if (ti->type->busy && ti->type->busy(ti)) | ||
| 1554 | goto plug_and_out; | ||
| 1555 | |||
| 1556 | blk_start_request(rq); | ||
| 1557 | spin_unlock(q->queue_lock); | ||
| 1558 | map_request(ti, rq, md); | ||
| 1559 | spin_lock_irq(q->queue_lock); | ||
| 1560 | } | ||
| 1561 | |||
| 1562 | goto out; | ||
| 1563 | |||
| 1564 | plug_and_out: | ||
| 1565 | if (!elv_queue_empty(q)) | ||
| 1566 | /* Some requests still remain, retry later */ | ||
| 1567 | blk_plug_device(q); | ||
| 1568 | |||
| 1569 | out: | ||
| 1570 | dm_table_put(map); | ||
| 1571 | |||
| 1572 | return; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | int dm_underlying_device_busy(struct request_queue *q) | ||
| 1576 | { | ||
| 1577 | return blk_lld_busy(q); | ||
| 1578 | } | ||
| 1579 | EXPORT_SYMBOL_GPL(dm_underlying_device_busy); | ||
| 1580 | |||
| 1581 | static int dm_lld_busy(struct request_queue *q) | ||
| 1582 | { | ||
| 1583 | int r; | ||
| 1584 | struct mapped_device *md = q->queuedata; | ||
| 1585 | struct dm_table *map = dm_get_table(md); | ||
| 1586 | |||
| 1587 | if (!map || test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) | ||
| 1588 | r = 1; | ||
| 1589 | else | ||
| 1590 | r = dm_table_any_busy_target(map); | ||
| 1591 | |||
| 1592 | dm_table_put(map); | ||
| 1593 | |||
| 1594 | return r; | ||
| 1595 | } | ||
| 1596 | |||
| 983 | static void dm_unplug_all(struct request_queue *q) | 1597 | static void dm_unplug_all(struct request_queue *q) |
| 984 | { | 1598 | { |
| 985 | struct mapped_device *md = q->queuedata; | 1599 | struct mapped_device *md = q->queuedata; |
| 986 | struct dm_table *map = dm_get_table(md); | 1600 | struct dm_table *map = dm_get_table(md); |
| 987 | 1601 | ||
| 988 | if (map) { | 1602 | if (map) { |
| 1603 | if (dm_request_based(md)) | ||
| 1604 | generic_unplug_device(q); | ||
| 1605 | |||
| 989 | dm_table_unplug_all(map); | 1606 | dm_table_unplug_all(map); |
| 990 | dm_table_put(map); | 1607 | dm_table_put(map); |
| 991 | } | 1608 | } |
| @@ -1000,7 +1617,16 @@ static int dm_any_congested(void *congested_data, int bdi_bits) | |||
| 1000 | if (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) { | 1617 | if (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) { |
| 1001 | map = dm_get_table(md); | 1618 | map = dm_get_table(md); |
| 1002 | if (map) { | 1619 | if (map) { |
| 1003 | r = dm_table_any_congested(map, bdi_bits); | 1620 | /* |
| 1621 | * Request-based dm cares about only own queue for | ||
| 1622 | * the query about congestion status of request_queue | ||
| 1623 | */ | ||
| 1624 | if (dm_request_based(md)) | ||
| 1625 | r = md->queue->backing_dev_info.state & | ||
| 1626 | bdi_bits; | ||
| 1627 | else | ||
| 1628 | r = dm_table_any_congested(map, bdi_bits); | ||
| 1629 | |||
| 1004 | dm_table_put(map); | 1630 | dm_table_put(map); |
| 1005 | } | 1631 | } |
| 1006 | } | 1632 | } |
| @@ -1123,30 +1749,32 @@ static struct mapped_device *alloc_dev(int minor) | |||
| 1123 | INIT_LIST_HEAD(&md->uevent_list); | 1749 | INIT_LIST_HEAD(&md->uevent_list); |
| 1124 | spin_lock_init(&md->uevent_lock); | 1750 | spin_lock_init(&md->uevent_lock); |
| 1125 | 1751 | ||
| 1126 | md->queue = blk_alloc_queue(GFP_KERNEL); | 1752 | md->queue = blk_init_queue(dm_request_fn, NULL); |
| 1127 | if (!md->queue) | 1753 | if (!md->queue) |
| 1128 | goto bad_queue; | 1754 | goto bad_queue; |
| 1129 | 1755 | ||
| 1756 | /* | ||
| 1757 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
| 1758 | * devices. The type of this dm device has not been decided yet, | ||
| 1759 | * although we initialized the queue using blk_init_queue(). | ||
| 1760 | * The type is decided at the first table loading time. | ||
| 1761 | * To prevent problematic device stacking, clear the queue flag | ||
| 1762 | * for request stacking support until then. | ||
| 1763 | * | ||
| 1764 | * This queue is new, so no concurrency on the queue_flags. | ||
| 1765 | */ | ||
| 1766 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
| 1767 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
| 1130 | md->queue->queuedata = md; | 1768 | md->queue->queuedata = md; |
| 1131 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | 1769 | md->queue->backing_dev_info.congested_fn = dm_any_congested; |
| 1132 | md->queue->backing_dev_info.congested_data = md; | 1770 | md->queue->backing_dev_info.congested_data = md; |
| 1133 | blk_queue_make_request(md->queue, dm_request); | 1771 | blk_queue_make_request(md->queue, dm_request); |
| 1134 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN, NULL); | ||
| 1135 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | 1772 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); |
| 1136 | md->queue->unplug_fn = dm_unplug_all; | 1773 | md->queue->unplug_fn = dm_unplug_all; |
| 1137 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | 1774 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); |
| 1138 | 1775 | blk_queue_softirq_done(md->queue, dm_softirq_done); | |
| 1139 | md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); | 1776 | blk_queue_prep_rq(md->queue, dm_prep_fn); |
| 1140 | if (!md->io_pool) | 1777 | blk_queue_lld_busy(md->queue, dm_lld_busy); |
| 1141 | goto bad_io_pool; | ||
| 1142 | |||
| 1143 | md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); | ||
| 1144 | if (!md->tio_pool) | ||
| 1145 | goto bad_tio_pool; | ||
| 1146 | |||
| 1147 | md->bs = bioset_create(16, 0); | ||
| 1148 | if (!md->bs) | ||
| 1149 | goto bad_no_bioset; | ||
| 1150 | 1778 | ||
| 1151 | md->disk = alloc_disk(1); | 1779 | md->disk = alloc_disk(1); |
| 1152 | if (!md->disk) | 1780 | if (!md->disk) |
| @@ -1170,6 +1798,10 @@ static struct mapped_device *alloc_dev(int minor) | |||
| 1170 | if (!md->wq) | 1798 | if (!md->wq) |
| 1171 | goto bad_thread; | 1799 | goto bad_thread; |
| 1172 | 1800 | ||
| 1801 | md->bdev = bdget_disk(md->disk, 0); | ||
| 1802 | if (!md->bdev) | ||
| 1803 | goto bad_bdev; | ||
| 1804 | |||
| 1173 | /* Populate the mapping, nobody knows we exist yet */ | 1805 | /* Populate the mapping, nobody knows we exist yet */ |
| 1174 | spin_lock(&_minor_lock); | 1806 | spin_lock(&_minor_lock); |
| 1175 | old_md = idr_replace(&_minor_idr, md, minor); | 1807 | old_md = idr_replace(&_minor_idr, md, minor); |
| @@ -1179,15 +1811,11 @@ static struct mapped_device *alloc_dev(int minor) | |||
| 1179 | 1811 | ||
| 1180 | return md; | 1812 | return md; |
| 1181 | 1813 | ||
| 1814 | bad_bdev: | ||
| 1815 | destroy_workqueue(md->wq); | ||
| 1182 | bad_thread: | 1816 | bad_thread: |
| 1183 | put_disk(md->disk); | 1817 | put_disk(md->disk); |
| 1184 | bad_disk: | 1818 | bad_disk: |
| 1185 | bioset_free(md->bs); | ||
| 1186 | bad_no_bioset: | ||
| 1187 | mempool_destroy(md->tio_pool); | ||
| 1188 | bad_tio_pool: | ||
| 1189 | mempool_destroy(md->io_pool); | ||
| 1190 | bad_io_pool: | ||
| 1191 | blk_cleanup_queue(md->queue); | 1819 | blk_cleanup_queue(md->queue); |
| 1192 | bad_queue: | 1820 | bad_queue: |
| 1193 | free_minor(minor); | 1821 | free_minor(minor); |
| @@ -1204,14 +1832,15 @@ static void free_dev(struct mapped_device *md) | |||
| 1204 | { | 1832 | { |
| 1205 | int minor = MINOR(disk_devt(md->disk)); | 1833 | int minor = MINOR(disk_devt(md->disk)); |
| 1206 | 1834 | ||
| 1207 | if (md->suspended_bdev) { | 1835 | unlock_fs(md); |
| 1208 | unlock_fs(md); | 1836 | bdput(md->bdev); |
| 1209 | bdput(md->suspended_bdev); | ||
| 1210 | } | ||
| 1211 | destroy_workqueue(md->wq); | 1837 | destroy_workqueue(md->wq); |
| 1212 | mempool_destroy(md->tio_pool); | 1838 | if (md->tio_pool) |
| 1213 | mempool_destroy(md->io_pool); | 1839 | mempool_destroy(md->tio_pool); |
| 1214 | bioset_free(md->bs); | 1840 | if (md->io_pool) |
| 1841 | mempool_destroy(md->io_pool); | ||
| 1842 | if (md->bs) | ||
| 1843 | bioset_free(md->bs); | ||
| 1215 | blk_integrity_unregister(md->disk); | 1844 | blk_integrity_unregister(md->disk); |
| 1216 | del_gendisk(md->disk); | 1845 | del_gendisk(md->disk); |
| 1217 | free_minor(minor); | 1846 | free_minor(minor); |
| @@ -1226,6 +1855,29 @@ static void free_dev(struct mapped_device *md) | |||
| 1226 | kfree(md); | 1855 | kfree(md); |
| 1227 | } | 1856 | } |
| 1228 | 1857 | ||
| 1858 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) | ||
| 1859 | { | ||
| 1860 | struct dm_md_mempools *p; | ||
| 1861 | |||
| 1862 | if (md->io_pool && md->tio_pool && md->bs) | ||
| 1863 | /* the md already has necessary mempools */ | ||
| 1864 | goto out; | ||
| 1865 | |||
| 1866 | p = dm_table_get_md_mempools(t); | ||
| 1867 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); | ||
| 1868 | |||
| 1869 | md->io_pool = p->io_pool; | ||
| 1870 | p->io_pool = NULL; | ||
| 1871 | md->tio_pool = p->tio_pool; | ||
| 1872 | p->tio_pool = NULL; | ||
| 1873 | md->bs = p->bs; | ||
| 1874 | p->bs = NULL; | ||
| 1875 | |||
| 1876 | out: | ||
| 1877 | /* mempool bind completed, now no need any mempools in the table */ | ||
| 1878 | dm_table_free_md_mempools(t); | ||
| 1879 | } | ||
| 1880 | |||
| 1229 | /* | 1881 | /* |
| 1230 | * Bind a table to the device. | 1882 | * Bind a table to the device. |
| 1231 | */ | 1883 | */ |
| @@ -1249,15 +1901,17 @@ static void __set_size(struct mapped_device *md, sector_t size) | |||
| 1249 | { | 1901 | { |
| 1250 | set_capacity(md->disk, size); | 1902 | set_capacity(md->disk, size); |
| 1251 | 1903 | ||
| 1252 | mutex_lock(&md->suspended_bdev->bd_inode->i_mutex); | 1904 | mutex_lock(&md->bdev->bd_inode->i_mutex); |
| 1253 | i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); | 1905 | i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); |
| 1254 | mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex); | 1906 | mutex_unlock(&md->bdev->bd_inode->i_mutex); |
| 1255 | } | 1907 | } |
| 1256 | 1908 | ||
| 1257 | static int __bind(struct mapped_device *md, struct dm_table *t) | 1909 | static int __bind(struct mapped_device *md, struct dm_table *t, |
| 1910 | struct queue_limits *limits) | ||
| 1258 | { | 1911 | { |
| 1259 | struct request_queue *q = md->queue; | 1912 | struct request_queue *q = md->queue; |
| 1260 | sector_t size; | 1913 | sector_t size; |
| 1914 | unsigned long flags; | ||
| 1261 | 1915 | ||
| 1262 | size = dm_table_get_size(t); | 1916 | size = dm_table_get_size(t); |
| 1263 | 1917 | ||
| @@ -1267,8 +1921,7 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
| 1267 | if (size != get_capacity(md->disk)) | 1921 | if (size != get_capacity(md->disk)) |
| 1268 | memset(&md->geometry, 0, sizeof(md->geometry)); | 1922 | memset(&md->geometry, 0, sizeof(md->geometry)); |
| 1269 | 1923 | ||
| 1270 | if (md->suspended_bdev) | 1924 | __set_size(md, size); |
| 1271 | __set_size(md, size); | ||
| 1272 | 1925 | ||
| 1273 | if (!size) { | 1926 | if (!size) { |
| 1274 | dm_table_destroy(t); | 1927 | dm_table_destroy(t); |
| @@ -1277,10 +1930,22 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
| 1277 | 1930 | ||
| 1278 | dm_table_event_callback(t, event_callback, md); | 1931 | dm_table_event_callback(t, event_callback, md); |
| 1279 | 1932 | ||
| 1280 | write_lock(&md->map_lock); | 1933 | /* |
| 1934 | * The queue hasn't been stopped yet, if the old table type wasn't | ||
| 1935 | * for request-based during suspension. So stop it to prevent | ||
| 1936 | * I/O mapping before resume. | ||
| 1937 | * This must be done before setting the queue restrictions, | ||
| 1938 | * because request-based dm may be run just after the setting. | ||
| 1939 | */ | ||
| 1940 | if (dm_table_request_based(t) && !blk_queue_stopped(q)) | ||
| 1941 | stop_queue(q); | ||
| 1942 | |||
| 1943 | __bind_mempools(md, t); | ||
| 1944 | |||
| 1945 | write_lock_irqsave(&md->map_lock, flags); | ||
| 1281 | md->map = t; | 1946 | md->map = t; |
| 1282 | dm_table_set_restrictions(t, q); | 1947 | dm_table_set_restrictions(t, q, limits); |
| 1283 | write_unlock(&md->map_lock); | 1948 | write_unlock_irqrestore(&md->map_lock, flags); |
| 1284 | 1949 | ||
| 1285 | return 0; | 1950 | return 0; |
| 1286 | } | 1951 | } |
| @@ -1288,14 +1953,15 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
| 1288 | static void __unbind(struct mapped_device *md) | 1953 | static void __unbind(struct mapped_device *md) |
| 1289 | { | 1954 | { |
| 1290 | struct dm_table *map = md->map; | 1955 | struct dm_table *map = md->map; |
| 1956 | unsigned long flags; | ||
| 1291 | 1957 | ||
| 1292 | if (!map) | 1958 | if (!map) |
| 1293 | return; | 1959 | return; |
| 1294 | 1960 | ||
| 1295 | dm_table_event_callback(map, NULL, NULL); | 1961 | dm_table_event_callback(map, NULL, NULL); |
| 1296 | write_lock(&md->map_lock); | 1962 | write_lock_irqsave(&md->map_lock, flags); |
| 1297 | md->map = NULL; | 1963 | md->map = NULL; |
| 1298 | write_unlock(&md->map_lock); | 1964 | write_unlock_irqrestore(&md->map_lock, flags); |
| 1299 | dm_table_destroy(map); | 1965 | dm_table_destroy(map); |
| 1300 | } | 1966 | } |
| 1301 | 1967 | ||
| @@ -1399,6 +2065,8 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible) | |||
| 1399 | { | 2065 | { |
| 1400 | int r = 0; | 2066 | int r = 0; |
| 1401 | DECLARE_WAITQUEUE(wait, current); | 2067 | DECLARE_WAITQUEUE(wait, current); |
| 2068 | struct request_queue *q = md->queue; | ||
| 2069 | unsigned long flags; | ||
| 1402 | 2070 | ||
| 1403 | dm_unplug_all(md->queue); | 2071 | dm_unplug_all(md->queue); |
| 1404 | 2072 | ||
| @@ -1408,7 +2076,14 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible) | |||
| 1408 | set_current_state(interruptible); | 2076 | set_current_state(interruptible); |
| 1409 | 2077 | ||
| 1410 | smp_mb(); | 2078 | smp_mb(); |
| 1411 | if (!atomic_read(&md->pending)) | 2079 | if (dm_request_based(md)) { |
| 2080 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 2081 | if (!queue_in_flight(q) && blk_queue_stopped(q)) { | ||
| 2082 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 2083 | break; | ||
| 2084 | } | ||
| 2085 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 2086 | } else if (!atomic_read(&md->pending)) | ||
| 1412 | break; | 2087 | break; |
| 1413 | 2088 | ||
| 1414 | if (interruptible == TASK_INTERRUPTIBLE && | 2089 | if (interruptible == TASK_INTERRUPTIBLE && |
| @@ -1426,34 +2101,36 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible) | |||
| 1426 | return r; | 2101 | return r; |
| 1427 | } | 2102 | } |
| 1428 | 2103 | ||
| 1429 | static int dm_flush(struct mapped_device *md) | 2104 | static void dm_flush(struct mapped_device *md) |
| 1430 | { | 2105 | { |
| 1431 | dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); | 2106 | dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); |
| 1432 | return 0; | 2107 | |
| 2108 | bio_init(&md->barrier_bio); | ||
| 2109 | md->barrier_bio.bi_bdev = md->bdev; | ||
| 2110 | md->barrier_bio.bi_rw = WRITE_BARRIER; | ||
| 2111 | __split_and_process_bio(md, &md->barrier_bio); | ||
| 2112 | |||
| 2113 | dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); | ||
| 1433 | } | 2114 | } |
| 1434 | 2115 | ||
| 1435 | static void process_barrier(struct mapped_device *md, struct bio *bio) | 2116 | static void process_barrier(struct mapped_device *md, struct bio *bio) |
| 1436 | { | 2117 | { |
| 1437 | int error = dm_flush(md); | 2118 | md->barrier_error = 0; |
| 1438 | |||
| 1439 | if (unlikely(error)) { | ||
| 1440 | bio_endio(bio, error); | ||
| 1441 | return; | ||
| 1442 | } | ||
| 1443 | if (bio_empty_barrier(bio)) { | ||
| 1444 | bio_endio(bio, 0); | ||
| 1445 | return; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | __split_and_process_bio(md, bio); | ||
| 1449 | 2119 | ||
| 1450 | error = dm_flush(md); | 2120 | dm_flush(md); |
| 1451 | 2121 | ||
| 1452 | if (!error && md->barrier_error) | 2122 | if (!bio_empty_barrier(bio)) { |
| 1453 | error = md->barrier_error; | 2123 | __split_and_process_bio(md, bio); |
| 2124 | dm_flush(md); | ||
| 2125 | } | ||
| 1454 | 2126 | ||
| 1455 | if (md->barrier_error != DM_ENDIO_REQUEUE) | 2127 | if (md->barrier_error != DM_ENDIO_REQUEUE) |
| 1456 | bio_endio(bio, error); | 2128 | bio_endio(bio, md->barrier_error); |
| 2129 | else { | ||
| 2130 | spin_lock_irq(&md->deferred_lock); | ||
| 2131 | bio_list_add_head(&md->deferred, bio); | ||
| 2132 | spin_unlock_irq(&md->deferred_lock); | ||
| 2133 | } | ||
| 1457 | } | 2134 | } |
| 1458 | 2135 | ||
| 1459 | /* | 2136 | /* |
| @@ -1479,10 +2156,14 @@ static void dm_wq_work(struct work_struct *work) | |||
| 1479 | 2156 | ||
| 1480 | up_write(&md->io_lock); | 2157 | up_write(&md->io_lock); |
| 1481 | 2158 | ||
| 1482 | if (bio_barrier(c)) | 2159 | if (dm_request_based(md)) |
| 1483 | process_barrier(md, c); | 2160 | generic_make_request(c); |
| 1484 | else | 2161 | else { |
| 1485 | __split_and_process_bio(md, c); | 2162 | if (bio_barrier(c)) |
| 2163 | process_barrier(md, c); | ||
| 2164 | else | ||
| 2165 | __split_and_process_bio(md, c); | ||
| 2166 | } | ||
| 1486 | 2167 | ||
| 1487 | down_write(&md->io_lock); | 2168 | down_write(&md->io_lock); |
| 1488 | } | 2169 | } |
| @@ -1502,6 +2183,7 @@ static void dm_queue_flush(struct mapped_device *md) | |||
| 1502 | */ | 2183 | */ |
| 1503 | int dm_swap_table(struct mapped_device *md, struct dm_table *table) | 2184 | int dm_swap_table(struct mapped_device *md, struct dm_table *table) |
| 1504 | { | 2185 | { |
| 2186 | struct queue_limits limits; | ||
| 1505 | int r = -EINVAL; | 2187 | int r = -EINVAL; |
| 1506 | 2188 | ||
| 1507 | mutex_lock(&md->suspend_lock); | 2189 | mutex_lock(&md->suspend_lock); |
| @@ -1510,19 +2192,96 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
| 1510 | if (!dm_suspended(md)) | 2192 | if (!dm_suspended(md)) |
| 1511 | goto out; | 2193 | goto out; |
| 1512 | 2194 | ||
| 1513 | /* without bdev, the device size cannot be changed */ | 2195 | r = dm_calculate_queue_limits(table, &limits); |
| 1514 | if (!md->suspended_bdev) | 2196 | if (r) |
| 1515 | if (get_capacity(md->disk) != dm_table_get_size(table)) | 2197 | goto out; |
| 1516 | goto out; | 2198 | |
| 2199 | /* cannot change the device type, once a table is bound */ | ||
| 2200 | if (md->map && | ||
| 2201 | (dm_table_get_type(md->map) != dm_table_get_type(table))) { | ||
| 2202 | DMWARN("can't change the device type after a table is bound"); | ||
| 2203 | goto out; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | /* | ||
| 2207 | * It is enought that blk_queue_ordered() is called only once when | ||
| 2208 | * the first bio-based table is bound. | ||
| 2209 | * | ||
| 2210 | * This setting should be moved to alloc_dev() when request-based dm | ||
| 2211 | * supports barrier. | ||
| 2212 | */ | ||
| 2213 | if (!md->map && dm_table_bio_based(table)) | ||
| 2214 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN, NULL); | ||
| 1517 | 2215 | ||
| 1518 | __unbind(md); | 2216 | __unbind(md); |
| 1519 | r = __bind(md, table); | 2217 | r = __bind(md, table, &limits); |
| 1520 | 2218 | ||
| 1521 | out: | 2219 | out: |
| 1522 | mutex_unlock(&md->suspend_lock); | 2220 | mutex_unlock(&md->suspend_lock); |
| 1523 | return r; | 2221 | return r; |
| 1524 | } | 2222 | } |
| 1525 | 2223 | ||
| 2224 | static void dm_rq_invalidate_suspend_marker(struct mapped_device *md) | ||
| 2225 | { | ||
| 2226 | md->suspend_rq.special = (void *)0x1; | ||
| 2227 | } | ||
| 2228 | |||
| 2229 | static void dm_rq_abort_suspend(struct mapped_device *md, int noflush) | ||
| 2230 | { | ||
| 2231 | struct request_queue *q = md->queue; | ||
| 2232 | unsigned long flags; | ||
| 2233 | |||
| 2234 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 2235 | if (!noflush) | ||
| 2236 | dm_rq_invalidate_suspend_marker(md); | ||
| 2237 | __start_queue(q); | ||
| 2238 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | static void dm_rq_start_suspend(struct mapped_device *md, int noflush) | ||
| 2242 | { | ||
| 2243 | struct request *rq = &md->suspend_rq; | ||
| 2244 | struct request_queue *q = md->queue; | ||
| 2245 | |||
| 2246 | if (noflush) | ||
| 2247 | stop_queue(q); | ||
| 2248 | else { | ||
| 2249 | blk_rq_init(q, rq); | ||
| 2250 | blk_insert_request(q, rq, 0, NULL); | ||
| 2251 | } | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | static int dm_rq_suspend_available(struct mapped_device *md, int noflush) | ||
| 2255 | { | ||
| 2256 | int r = 1; | ||
| 2257 | struct request *rq = &md->suspend_rq; | ||
| 2258 | struct request_queue *q = md->queue; | ||
| 2259 | unsigned long flags; | ||
| 2260 | |||
| 2261 | if (noflush) | ||
| 2262 | return r; | ||
| 2263 | |||
| 2264 | /* The marker must be protected by queue lock if it is in use */ | ||
| 2265 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 2266 | if (unlikely(rq->ref_count)) { | ||
| 2267 | /* | ||
| 2268 | * This can happen, when the previous flush suspend was | ||
| 2269 | * interrupted, the marker is still in the queue and | ||
| 2270 | * this flush suspend has been invoked, because we don't | ||
| 2271 | * remove the marker at the time of suspend interruption. | ||
| 2272 | * We have only one marker per mapped_device, so we can't | ||
| 2273 | * start another flush suspend while it is in use. | ||
| 2274 | */ | ||
| 2275 | BUG_ON(!rq->special); /* The marker should be invalidated */ | ||
| 2276 | DMWARN("Invalidating the previous flush suspend is still in" | ||
| 2277 | " progress. Please retry later."); | ||
| 2278 | r = 0; | ||
| 2279 | } | ||
| 2280 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 2281 | |||
| 2282 | return r; | ||
| 2283 | } | ||
| 2284 | |||
| 1526 | /* | 2285 | /* |
| 1527 | * Functions to lock and unlock any filesystem running on the | 2286 | * Functions to lock and unlock any filesystem running on the |
| 1528 | * device. | 2287 | * device. |
| @@ -1533,7 +2292,7 @@ static int lock_fs(struct mapped_device *md) | |||
| 1533 | 2292 | ||
| 1534 | WARN_ON(md->frozen_sb); | 2293 | WARN_ON(md->frozen_sb); |
| 1535 | 2294 | ||
| 1536 | md->frozen_sb = freeze_bdev(md->suspended_bdev); | 2295 | md->frozen_sb = freeze_bdev(md->bdev); |
| 1537 | if (IS_ERR(md->frozen_sb)) { | 2296 | if (IS_ERR(md->frozen_sb)) { |
| 1538 | r = PTR_ERR(md->frozen_sb); | 2297 | r = PTR_ERR(md->frozen_sb); |
| 1539 | md->frozen_sb = NULL; | 2298 | md->frozen_sb = NULL; |
| @@ -1542,9 +2301,6 @@ static int lock_fs(struct mapped_device *md) | |||
| 1542 | 2301 | ||
| 1543 | set_bit(DMF_FROZEN, &md->flags); | 2302 | set_bit(DMF_FROZEN, &md->flags); |
| 1544 | 2303 | ||
| 1545 | /* don't bdput right now, we don't want the bdev | ||
| 1546 | * to go away while it is locked. | ||
| 1547 | */ | ||
| 1548 | return 0; | 2304 | return 0; |
| 1549 | } | 2305 | } |
| 1550 | 2306 | ||
| @@ -1553,7 +2309,7 @@ static void unlock_fs(struct mapped_device *md) | |||
| 1553 | if (!test_bit(DMF_FROZEN, &md->flags)) | 2309 | if (!test_bit(DMF_FROZEN, &md->flags)) |
| 1554 | return; | 2310 | return; |
| 1555 | 2311 | ||
| 1556 | thaw_bdev(md->suspended_bdev, md->frozen_sb); | 2312 | thaw_bdev(md->bdev, md->frozen_sb); |
| 1557 | md->frozen_sb = NULL; | 2313 | md->frozen_sb = NULL; |
| 1558 | clear_bit(DMF_FROZEN, &md->flags); | 2314 | clear_bit(DMF_FROZEN, &md->flags); |
| 1559 | } | 2315 | } |
| @@ -1565,6 +2321,53 @@ static void unlock_fs(struct mapped_device *md) | |||
| 1565 | * dm_bind_table, dm_suspend must be called to flush any in | 2321 | * dm_bind_table, dm_suspend must be called to flush any in |
| 1566 | * flight bios and ensure that any further io gets deferred. | 2322 | * flight bios and ensure that any further io gets deferred. |
| 1567 | */ | 2323 | */ |
| 2324 | /* | ||
| 2325 | * Suspend mechanism in request-based dm. | ||
| 2326 | * | ||
| 2327 | * After the suspend starts, further incoming requests are kept in | ||
| 2328 | * the request_queue and deferred. | ||
| 2329 | * Remaining requests in the request_queue at the start of suspend are flushed | ||
| 2330 | * if it is flush suspend. | ||
| 2331 | * The suspend completes when the following conditions have been satisfied, | ||
| 2332 | * so wait for it: | ||
| 2333 | * 1. q->in_flight is 0 (which means no in_flight request) | ||
| 2334 | * 2. queue has been stopped (which means no request dispatching) | ||
| 2335 | * | ||
| 2336 | * | ||
| 2337 | * Noflush suspend | ||
| 2338 | * --------------- | ||
| 2339 | * Noflush suspend doesn't need to dispatch remaining requests. | ||
| 2340 | * So stop the queue immediately. Then, wait for all in_flight requests | ||
| 2341 | * to be completed or requeued. | ||
| 2342 | * | ||
| 2343 | * To abort noflush suspend, start the queue. | ||
| 2344 | * | ||
| 2345 | * | ||
| 2346 | * Flush suspend | ||
| 2347 | * ------------- | ||
| 2348 | * Flush suspend needs to dispatch remaining requests. So stop the queue | ||
| 2349 | * after the remaining requests are completed. (Requeued request must be also | ||
| 2350 | * re-dispatched and completed. Until then, we can't stop the queue.) | ||
| 2351 | * | ||
| 2352 | * During flushing the remaining requests, further incoming requests are also | ||
| 2353 | * inserted to the same queue. To distinguish which requests are to be | ||
| 2354 | * flushed, we insert a marker request to the queue at the time of starting | ||
| 2355 | * flush suspend, like a barrier. | ||
| 2356 | * The dispatching is blocked when the marker is found on the top of the queue. | ||
| 2357 | * And the queue is stopped when all in_flight requests are completed, since | ||
| 2358 | * that means the remaining requests are completely flushed. | ||
| 2359 | * Then, the marker is removed from the queue. | ||
| 2360 | * | ||
| 2361 | * To abort flush suspend, we also need to take care of the marker, not only | ||
| 2362 | * starting the queue. | ||
| 2363 | * We don't remove the marker forcibly from the queue since it's against | ||
| 2364 | * the block-layer manner. Instead, we put a invalidated mark on the marker. | ||
| 2365 | * When the invalidated marker is found on the top of the queue, it is | ||
| 2366 | * immediately removed from the queue, so it doesn't block dispatching. | ||
| 2367 | * Because we have only one marker per mapped_device, we can't start another | ||
| 2368 | * flush suspend until the invalidated marker is removed from the queue. | ||
| 2369 | * So fail and return with -EBUSY in such a case. | ||
| 2370 | */ | ||
| 1568 | int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | 2371 | int dm_suspend(struct mapped_device *md, unsigned suspend_flags) |
| 1569 | { | 2372 | { |
| 1570 | struct dm_table *map = NULL; | 2373 | struct dm_table *map = NULL; |
| @@ -1579,6 +2382,11 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1579 | goto out_unlock; | 2382 | goto out_unlock; |
| 1580 | } | 2383 | } |
| 1581 | 2384 | ||
| 2385 | if (dm_request_based(md) && !dm_rq_suspend_available(md, noflush)) { | ||
| 2386 | r = -EBUSY; | ||
| 2387 | goto out_unlock; | ||
| 2388 | } | ||
| 2389 | |||
| 1582 | map = dm_get_table(md); | 2390 | map = dm_get_table(md); |
| 1583 | 2391 | ||
| 1584 | /* | 2392 | /* |
| @@ -1591,24 +2399,14 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1591 | /* This does not get reverted if there's an error later. */ | 2399 | /* This does not get reverted if there's an error later. */ |
| 1592 | dm_table_presuspend_targets(map); | 2400 | dm_table_presuspend_targets(map); |
| 1593 | 2401 | ||
| 1594 | /* bdget() can stall if the pending I/Os are not flushed */ | 2402 | /* |
| 1595 | if (!noflush) { | 2403 | * Flush I/O to the device. noflush supersedes do_lockfs, |
| 1596 | md->suspended_bdev = bdget_disk(md->disk, 0); | 2404 | * because lock_fs() needs to flush I/Os. |
| 1597 | if (!md->suspended_bdev) { | 2405 | */ |
| 1598 | DMWARN("bdget failed in dm_suspend"); | 2406 | if (!noflush && do_lockfs) { |
| 1599 | r = -ENOMEM; | 2407 | r = lock_fs(md); |
| 2408 | if (r) | ||
| 1600 | goto out; | 2409 | goto out; |
| 1601 | } | ||
| 1602 | |||
| 1603 | /* | ||
| 1604 | * Flush I/O to the device. noflush supersedes do_lockfs, | ||
| 1605 | * because lock_fs() needs to flush I/Os. | ||
| 1606 | */ | ||
| 1607 | if (do_lockfs) { | ||
| 1608 | r = lock_fs(md); | ||
| 1609 | if (r) | ||
| 1610 | goto out; | ||
| 1611 | } | ||
| 1612 | } | 2410 | } |
| 1613 | 2411 | ||
| 1614 | /* | 2412 | /* |
| @@ -1634,6 +2432,9 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1634 | 2432 | ||
| 1635 | flush_workqueue(md->wq); | 2433 | flush_workqueue(md->wq); |
| 1636 | 2434 | ||
| 2435 | if (dm_request_based(md)) | ||
| 2436 | dm_rq_start_suspend(md, noflush); | ||
| 2437 | |||
| 1637 | /* | 2438 | /* |
| 1638 | * At this point no more requests are entering target request routines. | 2439 | * At this point no more requests are entering target request routines. |
| 1639 | * We call dm_wait_for_completion to wait for all existing requests | 2440 | * We call dm_wait_for_completion to wait for all existing requests |
| @@ -1650,6 +2451,9 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1650 | if (r < 0) { | 2451 | if (r < 0) { |
| 1651 | dm_queue_flush(md); | 2452 | dm_queue_flush(md); |
| 1652 | 2453 | ||
| 2454 | if (dm_request_based(md)) | ||
| 2455 | dm_rq_abort_suspend(md, noflush); | ||
| 2456 | |||
| 1653 | unlock_fs(md); | 2457 | unlock_fs(md); |
| 1654 | goto out; /* pushback list is already flushed, so skip flush */ | 2458 | goto out; /* pushback list is already flushed, so skip flush */ |
| 1655 | } | 2459 | } |
| @@ -1665,11 +2469,6 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1665 | set_bit(DMF_SUSPENDED, &md->flags); | 2469 | set_bit(DMF_SUSPENDED, &md->flags); |
| 1666 | 2470 | ||
| 1667 | out: | 2471 | out: |
| 1668 | if (r && md->suspended_bdev) { | ||
| 1669 | bdput(md->suspended_bdev); | ||
| 1670 | md->suspended_bdev = NULL; | ||
| 1671 | } | ||
| 1672 | |||
| 1673 | dm_table_put(map); | 2472 | dm_table_put(map); |
| 1674 | 2473 | ||
| 1675 | out_unlock: | 2474 | out_unlock: |
| @@ -1696,21 +2495,20 @@ int dm_resume(struct mapped_device *md) | |||
| 1696 | 2495 | ||
| 1697 | dm_queue_flush(md); | 2496 | dm_queue_flush(md); |
| 1698 | 2497 | ||
| 1699 | unlock_fs(md); | 2498 | /* |
| 2499 | * Flushing deferred I/Os must be done after targets are resumed | ||
| 2500 | * so that mapping of targets can work correctly. | ||
| 2501 | * Request-based dm is queueing the deferred I/Os in its request_queue. | ||
| 2502 | */ | ||
| 2503 | if (dm_request_based(md)) | ||
| 2504 | start_queue(md->queue); | ||
| 1700 | 2505 | ||
| 1701 | if (md->suspended_bdev) { | 2506 | unlock_fs(md); |
| 1702 | bdput(md->suspended_bdev); | ||
| 1703 | md->suspended_bdev = NULL; | ||
| 1704 | } | ||
| 1705 | 2507 | ||
| 1706 | clear_bit(DMF_SUSPENDED, &md->flags); | 2508 | clear_bit(DMF_SUSPENDED, &md->flags); |
| 1707 | 2509 | ||
| 1708 | dm_table_unplug_all(map); | 2510 | dm_table_unplug_all(map); |
| 1709 | |||
| 1710 | dm_kobject_uevent(md); | ||
| 1711 | |||
| 1712 | r = 0; | 2511 | r = 0; |
| 1713 | |||
| 1714 | out: | 2512 | out: |
| 1715 | dm_table_put(map); | 2513 | dm_table_put(map); |
| 1716 | mutex_unlock(&md->suspend_lock); | 2514 | mutex_unlock(&md->suspend_lock); |
| @@ -1721,9 +2519,19 @@ out: | |||
| 1721 | /*----------------------------------------------------------------- | 2519 | /*----------------------------------------------------------------- |
| 1722 | * Event notification. | 2520 | * Event notification. |
| 1723 | *---------------------------------------------------------------*/ | 2521 | *---------------------------------------------------------------*/ |
| 1724 | void dm_kobject_uevent(struct mapped_device *md) | 2522 | void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, |
| 1725 | { | 2523 | unsigned cookie) |
| 1726 | kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE); | 2524 | { |
| 2525 | char udev_cookie[DM_COOKIE_LENGTH]; | ||
| 2526 | char *envp[] = { udev_cookie, NULL }; | ||
| 2527 | |||
| 2528 | if (!cookie) | ||
| 2529 | kobject_uevent(&disk_to_dev(md->disk)->kobj, action); | ||
| 2530 | else { | ||
| 2531 | snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u", | ||
| 2532 | DM_COOKIE_ENV_VAR_NAME, cookie); | ||
| 2533 | kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp); | ||
| 2534 | } | ||
| 1727 | } | 2535 | } |
| 1728 | 2536 | ||
| 1729 | uint32_t dm_next_uevent_seq(struct mapped_device *md) | 2537 | uint32_t dm_next_uevent_seq(struct mapped_device *md) |
| @@ -1777,6 +2585,10 @@ struct mapped_device *dm_get_from_kobject(struct kobject *kobj) | |||
| 1777 | if (&md->kobj != kobj) | 2585 | if (&md->kobj != kobj) |
| 1778 | return NULL; | 2586 | return NULL; |
| 1779 | 2587 | ||
| 2588 | if (test_bit(DMF_FREEING, &md->flags) || | ||
| 2589 | test_bit(DMF_DELETING, &md->flags)) | ||
| 2590 | return NULL; | ||
| 2591 | |||
| 1780 | dm_get(md); | 2592 | dm_get(md); |
| 1781 | return md; | 2593 | return md; |
| 1782 | } | 2594 | } |
| @@ -1797,6 +2609,61 @@ int dm_noflush_suspending(struct dm_target *ti) | |||
| 1797 | } | 2609 | } |
| 1798 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); | 2610 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); |
| 1799 | 2611 | ||
| 2612 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type) | ||
| 2613 | { | ||
| 2614 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); | ||
| 2615 | |||
| 2616 | if (!pools) | ||
| 2617 | return NULL; | ||
| 2618 | |||
| 2619 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? | ||
| 2620 | mempool_create_slab_pool(MIN_IOS, _io_cache) : | ||
| 2621 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); | ||
| 2622 | if (!pools->io_pool) | ||
| 2623 | goto free_pools_and_out; | ||
| 2624 | |||
| 2625 | pools->tio_pool = (type == DM_TYPE_BIO_BASED) ? | ||
| 2626 | mempool_create_slab_pool(MIN_IOS, _tio_cache) : | ||
| 2627 | mempool_create_slab_pool(MIN_IOS, _rq_tio_cache); | ||
| 2628 | if (!pools->tio_pool) | ||
| 2629 | goto free_io_pool_and_out; | ||
| 2630 | |||
| 2631 | pools->bs = (type == DM_TYPE_BIO_BASED) ? | ||
| 2632 | bioset_create(16, 0) : bioset_create(MIN_IOS, 0); | ||
| 2633 | if (!pools->bs) | ||
| 2634 | goto free_tio_pool_and_out; | ||
| 2635 | |||
| 2636 | return pools; | ||
| 2637 | |||
| 2638 | free_tio_pool_and_out: | ||
| 2639 | mempool_destroy(pools->tio_pool); | ||
| 2640 | |||
| 2641 | free_io_pool_and_out: | ||
| 2642 | mempool_destroy(pools->io_pool); | ||
| 2643 | |||
| 2644 | free_pools_and_out: | ||
| 2645 | kfree(pools); | ||
| 2646 | |||
| 2647 | return NULL; | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | void dm_free_md_mempools(struct dm_md_mempools *pools) | ||
| 2651 | { | ||
| 2652 | if (!pools) | ||
| 2653 | return; | ||
| 2654 | |||
| 2655 | if (pools->io_pool) | ||
| 2656 | mempool_destroy(pools->io_pool); | ||
| 2657 | |||
| 2658 | if (pools->tio_pool) | ||
| 2659 | mempool_destroy(pools->tio_pool); | ||
| 2660 | |||
| 2661 | if (pools->bs) | ||
| 2662 | bioset_free(pools->bs); | ||
| 2663 | |||
| 2664 | kfree(pools); | ||
| 2665 | } | ||
| 2666 | |||
| 1800 | static struct block_device_operations dm_blk_dops = { | 2667 | static struct block_device_operations dm_blk_dops = { |
| 1801 | .open = dm_blk_open, | 2668 | .open = dm_blk_open, |
| 1802 | .release = dm_blk_close, | 2669 | .release = dm_blk_close, |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index a31506d93e91..23278ae80f08 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
| @@ -23,6 +23,13 @@ | |||
| 23 | #define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) | 23 | #define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) |
| 24 | 24 | ||
| 25 | /* | 25 | /* |
| 26 | * Type of table and mapped_device's mempool | ||
| 27 | */ | ||
| 28 | #define DM_TYPE_NONE 0 | ||
| 29 | #define DM_TYPE_BIO_BASED 1 | ||
| 30 | #define DM_TYPE_REQUEST_BASED 2 | ||
| 31 | |||
| 32 | /* | ||
| 26 | * List of devices that a metadevice uses and should open/close. | 33 | * List of devices that a metadevice uses and should open/close. |
| 27 | */ | 34 | */ |
| 28 | struct dm_dev_internal { | 35 | struct dm_dev_internal { |
| @@ -32,6 +39,7 @@ struct dm_dev_internal { | |||
| 32 | }; | 39 | }; |
| 33 | 40 | ||
| 34 | struct dm_table; | 41 | struct dm_table; |
| 42 | struct dm_md_mempools; | ||
| 35 | 43 | ||
| 36 | /*----------------------------------------------------------------- | 44 | /*----------------------------------------------------------------- |
| 37 | * Internal table functions. | 45 | * Internal table functions. |
| @@ -41,18 +49,34 @@ void dm_table_event_callback(struct dm_table *t, | |||
| 41 | void (*fn)(void *), void *context); | 49 | void (*fn)(void *), void *context); |
| 42 | struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); | 50 | struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); |
| 43 | struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); | 51 | struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); |
| 44 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); | 52 | int dm_calculate_queue_limits(struct dm_table *table, |
| 53 | struct queue_limits *limits); | ||
| 54 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | ||
| 55 | struct queue_limits *limits); | ||
| 45 | struct list_head *dm_table_get_devices(struct dm_table *t); | 56 | struct list_head *dm_table_get_devices(struct dm_table *t); |
| 46 | void dm_table_presuspend_targets(struct dm_table *t); | 57 | void dm_table_presuspend_targets(struct dm_table *t); |
| 47 | void dm_table_postsuspend_targets(struct dm_table *t); | 58 | void dm_table_postsuspend_targets(struct dm_table *t); |
| 48 | int dm_table_resume_targets(struct dm_table *t); | 59 | int dm_table_resume_targets(struct dm_table *t); |
| 49 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); | 60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); |
| 61 | int dm_table_any_busy_target(struct dm_table *t); | ||
| 62 | int dm_table_set_type(struct dm_table *t); | ||
| 63 | unsigned dm_table_get_type(struct dm_table *t); | ||
| 64 | bool dm_table_bio_based(struct dm_table *t); | ||
| 65 | bool dm_table_request_based(struct dm_table *t); | ||
| 66 | int dm_table_alloc_md_mempools(struct dm_table *t); | ||
| 67 | void dm_table_free_md_mempools(struct dm_table *t); | ||
| 68 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); | ||
| 50 | 69 | ||
| 51 | /* | 70 | /* |
| 52 | * To check the return value from dm_table_find_target(). | 71 | * To check the return value from dm_table_find_target(). |
| 53 | */ | 72 | */ |
| 54 | #define dm_target_is_valid(t) ((t)->table) | 73 | #define dm_target_is_valid(t) ((t)->table) |
| 55 | 74 | ||
| 75 | /* | ||
| 76 | * To check whether the target type is request-based or not (bio-based). | ||
| 77 | */ | ||
| 78 | #define dm_target_request_based(t) ((t)->type->map_rq != NULL) | ||
| 79 | |||
| 56 | /*----------------------------------------------------------------- | 80 | /*----------------------------------------------------------------- |
| 57 | * A registry of target types. | 81 | * A registry of target types. |
| 58 | *---------------------------------------------------------------*/ | 82 | *---------------------------------------------------------------*/ |
| @@ -92,9 +116,16 @@ void dm_stripe_exit(void); | |||
| 92 | int dm_open_count(struct mapped_device *md); | 116 | int dm_open_count(struct mapped_device *md); |
| 93 | int dm_lock_for_deletion(struct mapped_device *md); | 117 | int dm_lock_for_deletion(struct mapped_device *md); |
| 94 | 118 | ||
| 95 | void dm_kobject_uevent(struct mapped_device *md); | 119 | void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, |
| 120 | unsigned cookie); | ||
| 96 | 121 | ||
| 97 | int dm_kcopyd_init(void); | 122 | int dm_kcopyd_init(void); |
| 98 | void dm_kcopyd_exit(void); | 123 | void dm_kcopyd_exit(void); |
| 99 | 124 | ||
| 125 | /* | ||
| 126 | * Mempool operations | ||
| 127 | */ | ||
| 128 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type); | ||
| 129 | void dm_free_md_mempools(struct dm_md_mempools *pools); | ||
| 130 | |||
| 100 | #endif | 131 | #endif |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 15c8b7b25a9b..5810fa906af0 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
| @@ -166,8 +166,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
| 166 | rdev->sectors = sectors * mddev->chunk_sectors; | 166 | rdev->sectors = sectors * mddev->chunk_sectors; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | blk_queue_stack_limits(mddev->queue, | 169 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
| 170 | rdev->bdev->bd_disk->queue); | 170 | rdev->data_offset << 9); |
| 171 | /* as we don't honour merge_bvec_fn, we must never risk | 171 | /* as we don't honour merge_bvec_fn, we must never risk |
| 172 | * violating it, so limit ->max_sector to one PAGE, as | 172 | * violating it, so limit ->max_sector to one PAGE, as |
| 173 | * a one page request is never in violation. | 173 | * a one page request is never in violation. |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 09be637d52cb..d4351ff0849f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1756,9 +1756,10 @@ static void print_sb_1(struct mdp_superblock_1 *sb) | |||
| 1756 | __u8 *uuid; | 1756 | __u8 *uuid; |
| 1757 | 1757 | ||
| 1758 | uuid = sb->set_uuid; | 1758 | uuid = sb->set_uuid; |
| 1759 | printk(KERN_INFO "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" | 1759 | printk(KERN_INFO |
| 1760 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" | 1760 | "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" |
| 1761 | KERN_INFO "md: Name: \"%s\" CT:%llu\n", | 1761 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" |
| 1762 | "md: Name: \"%s\" CT:%llu\n", | ||
| 1762 | le32_to_cpu(sb->major_version), | 1763 | le32_to_cpu(sb->major_version), |
| 1763 | le32_to_cpu(sb->feature_map), | 1764 | le32_to_cpu(sb->feature_map), |
| 1764 | uuid[0], uuid[1], uuid[2], uuid[3], | 1765 | uuid[0], uuid[1], uuid[2], uuid[3], |
| @@ -1770,12 +1771,13 @@ static void print_sb_1(struct mdp_superblock_1 *sb) | |||
| 1770 | & MD_SUPERBLOCK_1_TIME_SEC_MASK); | 1771 | & MD_SUPERBLOCK_1_TIME_SEC_MASK); |
| 1771 | 1772 | ||
| 1772 | uuid = sb->device_uuid; | 1773 | uuid = sb->device_uuid; |
| 1773 | printk(KERN_INFO "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" | 1774 | printk(KERN_INFO |
| 1775 | "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" | ||
| 1774 | " RO:%llu\n" | 1776 | " RO:%llu\n" |
| 1775 | KERN_INFO "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" | 1777 | "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" |
| 1776 | ":%02x%02x%02x%02x%02x%02x\n" | 1778 | ":%02x%02x%02x%02x%02x%02x\n" |
| 1777 | KERN_INFO "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" | 1779 | "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" |
| 1778 | KERN_INFO "md: (MaxDev:%u) \n", | 1780 | "md: (MaxDev:%u) \n", |
| 1779 | le32_to_cpu(sb->level), | 1781 | le32_to_cpu(sb->level), |
| 1780 | (unsigned long long)le64_to_cpu(sb->size), | 1782 | (unsigned long long)le64_to_cpu(sb->size), |
| 1781 | le32_to_cpu(sb->raid_disks), | 1783 | le32_to_cpu(sb->raid_disks), |
| @@ -3573,7 +3575,8 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3573 | char *e; | 3575 | char *e; |
| 3574 | unsigned long long new = simple_strtoull(buf, &e, 10); | 3576 | unsigned long long new = simple_strtoull(buf, &e, 10); |
| 3575 | 3577 | ||
| 3576 | if (mddev->pers->quiesce == NULL) | 3578 | if (mddev->pers == NULL || |
| 3579 | mddev->pers->quiesce == NULL) | ||
| 3577 | return -EINVAL; | 3580 | return -EINVAL; |
| 3578 | if (buf == e || (*e && *e != '\n')) | 3581 | if (buf == e || (*e && *e != '\n')) |
| 3579 | return -EINVAL; | 3582 | return -EINVAL; |
| @@ -3601,7 +3604,8 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3601 | char *e; | 3604 | char *e; |
| 3602 | unsigned long long new = simple_strtoull(buf, &e, 10); | 3605 | unsigned long long new = simple_strtoull(buf, &e, 10); |
| 3603 | 3606 | ||
| 3604 | if (mddev->pers->quiesce == NULL) | 3607 | if (mddev->pers == NULL || |
| 3608 | mddev->pers->quiesce == NULL) | ||
| 3605 | return -EINVAL; | 3609 | return -EINVAL; |
| 3606 | if (buf == e || (*e && *e != '\n')) | 3610 | if (buf == e || (*e && *e != '\n')) |
| 3607 | return -EINVAL; | 3611 | return -EINVAL; |
| @@ -3844,11 +3848,9 @@ static int md_alloc(dev_t dev, char *name) | |||
| 3844 | flush_scheduled_work(); | 3848 | flush_scheduled_work(); |
| 3845 | 3849 | ||
| 3846 | mutex_lock(&disks_mutex); | 3850 | mutex_lock(&disks_mutex); |
| 3847 | if (mddev->gendisk) { | 3851 | error = -EEXIST; |
| 3848 | mutex_unlock(&disks_mutex); | 3852 | if (mddev->gendisk) |
| 3849 | mddev_put(mddev); | 3853 | goto abort; |
| 3850 | return -EEXIST; | ||
| 3851 | } | ||
| 3852 | 3854 | ||
| 3853 | if (name) { | 3855 | if (name) { |
| 3854 | /* Need to ensure that 'name' is not a duplicate. | 3856 | /* Need to ensure that 'name' is not a duplicate. |
| @@ -3860,17 +3862,15 @@ static int md_alloc(dev_t dev, char *name) | |||
| 3860 | if (mddev2->gendisk && | 3862 | if (mddev2->gendisk && |
| 3861 | strcmp(mddev2->gendisk->disk_name, name) == 0) { | 3863 | strcmp(mddev2->gendisk->disk_name, name) == 0) { |
| 3862 | spin_unlock(&all_mddevs_lock); | 3864 | spin_unlock(&all_mddevs_lock); |
| 3863 | return -EEXIST; | 3865 | goto abort; |
| 3864 | } | 3866 | } |
| 3865 | spin_unlock(&all_mddevs_lock); | 3867 | spin_unlock(&all_mddevs_lock); |
| 3866 | } | 3868 | } |
| 3867 | 3869 | ||
| 3870 | error = -ENOMEM; | ||
| 3868 | mddev->queue = blk_alloc_queue(GFP_KERNEL); | 3871 | mddev->queue = blk_alloc_queue(GFP_KERNEL); |
| 3869 | if (!mddev->queue) { | 3872 | if (!mddev->queue) |
| 3870 | mutex_unlock(&disks_mutex); | 3873 | goto abort; |
| 3871 | mddev_put(mddev); | ||
| 3872 | return -ENOMEM; | ||
| 3873 | } | ||
| 3874 | mddev->queue->queuedata = mddev; | 3874 | mddev->queue->queuedata = mddev; |
| 3875 | 3875 | ||
| 3876 | /* Can be unlocked because the queue is new: no concurrency */ | 3876 | /* Can be unlocked because the queue is new: no concurrency */ |
| @@ -3880,11 +3880,9 @@ static int md_alloc(dev_t dev, char *name) | |||
| 3880 | 3880 | ||
| 3881 | disk = alloc_disk(1 << shift); | 3881 | disk = alloc_disk(1 << shift); |
| 3882 | if (!disk) { | 3882 | if (!disk) { |
| 3883 | mutex_unlock(&disks_mutex); | ||
| 3884 | blk_cleanup_queue(mddev->queue); | 3883 | blk_cleanup_queue(mddev->queue); |
| 3885 | mddev->queue = NULL; | 3884 | mddev->queue = NULL; |
| 3886 | mddev_put(mddev); | 3885 | goto abort; |
| 3887 | return -ENOMEM; | ||
| 3888 | } | 3886 | } |
| 3889 | disk->major = MAJOR(mddev->unit); | 3887 | disk->major = MAJOR(mddev->unit); |
| 3890 | disk->first_minor = unit << shift; | 3888 | disk->first_minor = unit << shift; |
| @@ -3906,16 +3904,22 @@ static int md_alloc(dev_t dev, char *name) | |||
| 3906 | mddev->gendisk = disk; | 3904 | mddev->gendisk = disk; |
| 3907 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, | 3905 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, |
| 3908 | &disk_to_dev(disk)->kobj, "%s", "md"); | 3906 | &disk_to_dev(disk)->kobj, "%s", "md"); |
| 3909 | mutex_unlock(&disks_mutex); | 3907 | if (error) { |
| 3910 | if (error) | 3908 | /* This isn't possible, but as kobject_init_and_add is marked |
| 3909 | * __must_check, we must do something with the result | ||
| 3910 | */ | ||
| 3911 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", | 3911 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", |
| 3912 | disk->disk_name); | 3912 | disk->disk_name); |
| 3913 | else { | 3913 | error = 0; |
| 3914 | } | ||
| 3915 | abort: | ||
| 3916 | mutex_unlock(&disks_mutex); | ||
| 3917 | if (!error) { | ||
| 3914 | kobject_uevent(&mddev->kobj, KOBJ_ADD); | 3918 | kobject_uevent(&mddev->kobj, KOBJ_ADD); |
| 3915 | mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); | 3919 | mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); |
| 3916 | } | 3920 | } |
| 3917 | mddev_put(mddev); | 3921 | mddev_put(mddev); |
| 3918 | return 0; | 3922 | return error; |
| 3919 | } | 3923 | } |
| 3920 | 3924 | ||
| 3921 | static struct kobject *md_probe(dev_t dev, int *part, void *data) | 3925 | static struct kobject *md_probe(dev_t dev, int *part, void *data) |
| @@ -6334,10 +6338,16 @@ void md_do_sync(mddev_t *mddev) | |||
| 6334 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 6338 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
| 6335 | } | 6339 | } |
| 6336 | 6340 | ||
| 6337 | if (j >= mddev->resync_max) | 6341 | while (j >= mddev->resync_max && !kthread_should_stop()) { |
| 6338 | wait_event(mddev->recovery_wait, | 6342 | /* As this condition is controlled by user-space, |
| 6339 | mddev->resync_max > j | 6343 | * we can block indefinitely, so use '_interruptible' |
| 6340 | || kthread_should_stop()); | 6344 | * to avoid triggering warnings. |
| 6345 | */ | ||
| 6346 | flush_signals(current); /* just in case */ | ||
| 6347 | wait_event_interruptible(mddev->recovery_wait, | ||
| 6348 | mddev->resync_max > j | ||
| 6349 | || kthread_should_stop()); | ||
| 6350 | } | ||
| 6341 | 6351 | ||
| 6342 | if (kthread_should_stop()) | 6352 | if (kthread_should_stop()) |
| 6343 | goto interrupted; | 6353 | goto interrupted; |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index cbe368fa6598..237fe3fd235c 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
| @@ -294,7 +294,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 294 | for (path = first; path <= last; path++) | 294 | for (path = first; path <= last; path++) |
| 295 | if ((p=conf->multipaths+path)->rdev == NULL) { | 295 | if ((p=conf->multipaths+path)->rdev == NULL) { |
| 296 | q = rdev->bdev->bd_disk->queue; | 296 | q = rdev->bdev->bd_disk->queue; |
| 297 | blk_queue_stack_limits(mddev->queue, q); | 297 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
| 298 | rdev->data_offset << 9); | ||
| 298 | 299 | ||
| 299 | /* as we don't honour merge_bvec_fn, we must never risk | 300 | /* as we don't honour merge_bvec_fn, we must never risk |
| 300 | * violating it, so limit ->max_sector to one PAGE, as | 301 | * violating it, so limit ->max_sector to one PAGE, as |
| @@ -463,9 +464,9 @@ static int multipath_run (mddev_t *mddev) | |||
| 463 | 464 | ||
| 464 | disk = conf->multipaths + disk_idx; | 465 | disk = conf->multipaths + disk_idx; |
| 465 | disk->rdev = rdev; | 466 | disk->rdev = rdev; |
| 467 | disk_stack_limits(mddev->gendisk, rdev->bdev, | ||
| 468 | rdev->data_offset << 9); | ||
| 466 | 469 | ||
| 467 | blk_queue_stack_limits(mddev->queue, | ||
| 468 | rdev->bdev->bd_disk->queue); | ||
| 469 | /* as we don't honour merge_bvec_fn, we must never risk | 470 | /* as we don't honour merge_bvec_fn, we must never risk |
| 470 | * violating it, not that we ever expect a device with | 471 | * violating it, not that we ever expect a device with |
| 471 | * a merge_bvec_fn to be involved in multipath */ | 472 | * a merge_bvec_fn to be involved in multipath */ |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index ab4a489d8695..335f490dcad6 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
| @@ -170,8 +170,8 @@ static int create_strip_zones(mddev_t *mddev) | |||
| 170 | } | 170 | } |
| 171 | dev[j] = rdev1; | 171 | dev[j] = rdev1; |
| 172 | 172 | ||
| 173 | blk_queue_stack_limits(mddev->queue, | 173 | disk_stack_limits(mddev->gendisk, rdev1->bdev, |
| 174 | rdev1->bdev->bd_disk->queue); | 174 | rdev1->data_offset << 9); |
| 175 | /* as we don't honour merge_bvec_fn, we must never risk | 175 | /* as we don't honour merge_bvec_fn, we must never risk |
| 176 | * violating it, so limit ->max_sector to one PAGE, as | 176 | * violating it, so limit ->max_sector to one PAGE, as |
| 177 | * a one page request is never in violation. | 177 | * a one page request is never in violation. |
| @@ -250,6 +250,11 @@ static int create_strip_zones(mddev_t *mddev) | |||
| 250 | mddev->chunk_sectors << 9); | 250 | mddev->chunk_sectors << 9); |
| 251 | goto abort; | 251 | goto abort; |
| 252 | } | 252 | } |
| 253 | |||
| 254 | blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); | ||
| 255 | blk_queue_io_opt(mddev->queue, | ||
| 256 | (mddev->chunk_sectors << 9) * mddev->raid_disks); | ||
| 257 | |||
| 253 | printk(KERN_INFO "raid0: done.\n"); | 258 | printk(KERN_INFO "raid0: done.\n"); |
| 254 | mddev->private = conf; | 259 | mddev->private = conf; |
| 255 | return 0; | 260 | return 0; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 89939a7aef57..0569efba0c02 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -1123,8 +1123,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1123 | for (mirror = first; mirror <= last; mirror++) | 1123 | for (mirror = first; mirror <= last; mirror++) |
| 1124 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1124 | if ( !(p=conf->mirrors+mirror)->rdev) { |
| 1125 | 1125 | ||
| 1126 | blk_queue_stack_limits(mddev->queue, | 1126 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
| 1127 | rdev->bdev->bd_disk->queue); | 1127 | rdev->data_offset << 9); |
| 1128 | /* as we don't honour merge_bvec_fn, we must never risk | 1128 | /* as we don't honour merge_bvec_fn, we must never risk |
| 1129 | * violating it, so limit ->max_sector to one PAGE, as | 1129 | * violating it, so limit ->max_sector to one PAGE, as |
| 1130 | * a one page request is never in violation. | 1130 | * a one page request is never in violation. |
| @@ -1988,9 +1988,8 @@ static int run(mddev_t *mddev) | |||
| 1988 | disk = conf->mirrors + disk_idx; | 1988 | disk = conf->mirrors + disk_idx; |
| 1989 | 1989 | ||
| 1990 | disk->rdev = rdev; | 1990 | disk->rdev = rdev; |
| 1991 | 1991 | disk_stack_limits(mddev->gendisk, rdev->bdev, | |
| 1992 | blk_queue_stack_limits(mddev->queue, | 1992 | rdev->data_offset << 9); |
| 1993 | rdev->bdev->bd_disk->queue); | ||
| 1994 | /* as we don't honour merge_bvec_fn, we must never risk | 1993 | /* as we don't honour merge_bvec_fn, we must never risk |
| 1995 | * violating it, so limit ->max_sector to one PAGE, as | 1994 | * violating it, so limit ->max_sector to one PAGE, as |
| 1996 | * a one page request is never in violation. | 1995 | * a one page request is never in violation. |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ae12ceafe10c..7298a5e5a183 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -1151,8 +1151,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1151 | for ( ; mirror <= last ; mirror++) | 1151 | for ( ; mirror <= last ; mirror++) |
| 1152 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1152 | if ( !(p=conf->mirrors+mirror)->rdev) { |
| 1153 | 1153 | ||
| 1154 | blk_queue_stack_limits(mddev->queue, | 1154 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
| 1155 | rdev->bdev->bd_disk->queue); | 1155 | rdev->data_offset << 9); |
| 1156 | /* as we don't honour merge_bvec_fn, we must never risk | 1156 | /* as we don't honour merge_bvec_fn, we must never risk |
| 1157 | * violating it, so limit ->max_sector to one PAGE, as | 1157 | * violating it, so limit ->max_sector to one PAGE, as |
| 1158 | * a one page request is never in violation. | 1158 | * a one page request is never in violation. |
| @@ -2044,7 +2044,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
| 2044 | static int run(mddev_t *mddev) | 2044 | static int run(mddev_t *mddev) |
| 2045 | { | 2045 | { |
| 2046 | conf_t *conf; | 2046 | conf_t *conf; |
| 2047 | int i, disk_idx; | 2047 | int i, disk_idx, chunk_size; |
| 2048 | mirror_info_t *disk; | 2048 | mirror_info_t *disk; |
| 2049 | mdk_rdev_t *rdev; | 2049 | mdk_rdev_t *rdev; |
| 2050 | int nc, fc, fo; | 2050 | int nc, fc, fo; |
| @@ -2130,6 +2130,14 @@ static int run(mddev_t *mddev) | |||
| 2130 | spin_lock_init(&conf->device_lock); | 2130 | spin_lock_init(&conf->device_lock); |
| 2131 | mddev->queue->queue_lock = &conf->device_lock; | 2131 | mddev->queue->queue_lock = &conf->device_lock; |
| 2132 | 2132 | ||
| 2133 | chunk_size = mddev->chunk_sectors << 9; | ||
| 2134 | blk_queue_io_min(mddev->queue, chunk_size); | ||
| 2135 | if (conf->raid_disks % conf->near_copies) | ||
| 2136 | blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks); | ||
| 2137 | else | ||
| 2138 | blk_queue_io_opt(mddev->queue, chunk_size * | ||
| 2139 | (conf->raid_disks / conf->near_copies)); | ||
| 2140 | |||
| 2133 | list_for_each_entry(rdev, &mddev->disks, same_set) { | 2141 | list_for_each_entry(rdev, &mddev->disks, same_set) { |
| 2134 | disk_idx = rdev->raid_disk; | 2142 | disk_idx = rdev->raid_disk; |
| 2135 | if (disk_idx >= mddev->raid_disks | 2143 | if (disk_idx >= mddev->raid_disks |
| @@ -2138,9 +2146,8 @@ static int run(mddev_t *mddev) | |||
| 2138 | disk = conf->mirrors + disk_idx; | 2146 | disk = conf->mirrors + disk_idx; |
| 2139 | 2147 | ||
| 2140 | disk->rdev = rdev; | 2148 | disk->rdev = rdev; |
| 2141 | 2149 | disk_stack_limits(mddev->gendisk, rdev->bdev, | |
| 2142 | blk_queue_stack_limits(mddev->queue, | 2150 | rdev->data_offset << 9); |
| 2143 | rdev->bdev->bd_disk->queue); | ||
| 2144 | /* as we don't honour merge_bvec_fn, we must never risk | 2151 | /* as we don't honour merge_bvec_fn, we must never risk |
| 2145 | * violating it, so limit ->max_sector to one PAGE, as | 2152 | * violating it, so limit ->max_sector to one PAGE, as |
| 2146 | * a one page request is never in violation. | 2153 | * a one page request is never in violation. |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9f991e6e138..37835538b58e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -3699,13 +3699,21 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
| 3699 | goto retry; | 3699 | goto retry; |
| 3700 | } | 3700 | } |
| 3701 | } | 3701 | } |
| 3702 | /* FIXME what if we get a false positive because these | 3702 | |
| 3703 | * are being updated. | 3703 | if (bio_data_dir(bi) == WRITE && |
| 3704 | */ | 3704 | logical_sector >= mddev->suspend_lo && |
| 3705 | if (logical_sector >= mddev->suspend_lo && | ||
| 3706 | logical_sector < mddev->suspend_hi) { | 3705 | logical_sector < mddev->suspend_hi) { |
| 3707 | release_stripe(sh); | 3706 | release_stripe(sh); |
| 3708 | schedule(); | 3707 | /* As the suspend_* range is controlled by |
| 3708 | * userspace, we want an interruptible | ||
| 3709 | * wait. | ||
| 3710 | */ | ||
| 3711 | flush_signals(current); | ||
| 3712 | prepare_to_wait(&conf->wait_for_overlap, | ||
| 3713 | &w, TASK_INTERRUPTIBLE); | ||
| 3714 | if (logical_sector >= mddev->suspend_lo && | ||
| 3715 | logical_sector < mddev->suspend_hi) | ||
| 3716 | schedule(); | ||
| 3709 | goto retry; | 3717 | goto retry; |
| 3710 | } | 3718 | } |
| 3711 | 3719 | ||
| @@ -4452,7 +4460,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) | |||
| 4452 | static int run(mddev_t *mddev) | 4460 | static int run(mddev_t *mddev) |
| 4453 | { | 4461 | { |
| 4454 | raid5_conf_t *conf; | 4462 | raid5_conf_t *conf; |
| 4455 | int working_disks = 0; | 4463 | int working_disks = 0, chunk_size; |
| 4456 | mdk_rdev_t *rdev; | 4464 | mdk_rdev_t *rdev; |
| 4457 | 4465 | ||
| 4458 | if (mddev->recovery_cp != MaxSector) | 4466 | if (mddev->recovery_cp != MaxSector) |
| @@ -4607,6 +4615,14 @@ static int run(mddev_t *mddev) | |||
| 4607 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); | 4615 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); |
| 4608 | 4616 | ||
| 4609 | blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); | 4617 | blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); |
| 4618 | chunk_size = mddev->chunk_sectors << 9; | ||
| 4619 | blk_queue_io_min(mddev->queue, chunk_size); | ||
| 4620 | blk_queue_io_opt(mddev->queue, chunk_size * | ||
| 4621 | (conf->raid_disks - conf->max_degraded)); | ||
| 4622 | |||
| 4623 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
| 4624 | disk_stack_limits(mddev->gendisk, rdev->bdev, | ||
| 4625 | rdev->data_offset << 9); | ||
| 4610 | 4626 | ||
| 4611 | return 0; | 4627 | return 0; |
| 4612 | abort: | 4628 | abort: |
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index b6da9c3873fe..aa20ce8cc668 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
| @@ -1096,8 +1096,19 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
| 1096 | } | 1096 | } |
| 1097 | 1097 | ||
| 1098 | /* All S-code tables need a 200kHz shift */ | 1098 | /* All S-code tables need a 200kHz shift */ |
| 1099 | if (priv->ctrl.demod) | 1099 | if (priv->ctrl.demod) { |
| 1100 | demod = priv->ctrl.demod + 200; | 1100 | demod = priv->ctrl.demod + 200; |
| 1101 | /* | ||
| 1102 | * The DTV7 S-code table needs a 700 kHz shift. | ||
| 1103 | * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this | ||
| 1104 | * | ||
| 1105 | * DTV7 is only used in Australia. Germany or Italy may also | ||
| 1106 | * use this firmware after initialization, but a tune to a UHF | ||
| 1107 | * channel should then cause DTV78 to be used. | ||
| 1108 | */ | ||
| 1109 | if (type & DTV7) | ||
| 1110 | demod += 500; | ||
| 1111 | } | ||
| 1101 | 1112 | ||
| 1102 | return generic_set_freq(fe, p->frequency, | 1113 | return generic_set_freq(fe, p->frequency, |
| 1103 | T_DIGITAL_TV, type, 0, demod); | 1114 | T_DIGITAL_TV, type, 0, demod); |
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 4601b059b2b2..0e246eaad05a 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/smp_lock.h> | ||
| 24 | #include <linux/string.h> | 25 | #include <linux/string.h> |
| 25 | #include <linux/dvb/ca.h> | 26 | #include <linux/dvb/ca.h> |
| 26 | #include "dvbdev.h" | 27 | #include "dvbdev.h" |
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 79927305e84d..487919bea7ae 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
| 28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
| 30 | #include <linux/smp_lock.h> | ||
| 31 | 30 | ||
| 32 | #define DVB_MAJOR 212 | 31 | #define DVB_MAJOR 212 |
| 33 | 32 | ||
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 68eb4493f991..d8d4214fd65f 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config TTPCI_EEPROM | 1 | config TTPCI_EEPROM |
| 2 | tristate | 2 | tristate |
| 3 | depends on I2C | ||
| 3 | default n | 4 | default n |
| 4 | 5 | ||
| 5 | config DVB_AV7110 | 6 | config DVB_AV7110 |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d1d959ed37b7..8d65c652ba50 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
| 37 | #include <linux/timer.h> | 37 | #include <linux/timer.h> |
| 38 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
| 39 | #include <linux/smp_lock.h> | ||
| 40 | 39 | ||
| 41 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
| 42 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 837467f93805..575bf9d89419 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/module.h> | 58 | #include <linux/module.h> |
| 59 | #include <linux/init.h> | 59 | #include <linux/init.h> |
| 60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
| 61 | #include <linux/smp_lock.h> | ||
| 61 | #include <linux/input.h> | 62 | #include <linux/input.h> |
| 62 | #include <linux/videodev2.h> | 63 | #include <linux/videodev2.h> |
| 63 | #include <media/v4l2-device.h> | 64 | #include <media/v4l2-device.h> |
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 640421ceb24a..e85f318b4d2b 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
| @@ -127,6 +127,7 @@ | |||
| 127 | #include <linux/module.h> | 127 | #include <linux/module.h> |
| 128 | #include <linux/init.h> | 128 | #include <linux/init.h> |
| 129 | #include <linux/slab.h> | 129 | #include <linux/slab.h> |
| 130 | #include <linux/smp_lock.h> | ||
| 130 | #include <linux/input.h> | 131 | #include <linux/input.h> |
| 131 | #include <linux/usb.h> | 132 | #include <linux/usb.h> |
| 132 | #include <linux/hid.h> | 133 | #include <linux/hid.h> |
| @@ -1200,7 +1201,7 @@ static int si470x_fops_release(struct file *file) | |||
| 1200 | video_unregister_device(radio->videodev); | 1201 | video_unregister_device(radio->videodev); |
| 1201 | kfree(radio->buffer); | 1202 | kfree(radio->buffer); |
| 1202 | kfree(radio); | 1203 | kfree(radio); |
| 1203 | goto done; | 1204 | goto unlock; |
| 1204 | } | 1205 | } |
| 1205 | 1206 | ||
| 1206 | /* stop rds reception */ | 1207 | /* stop rds reception */ |
| @@ -1213,9 +1214,8 @@ static int si470x_fops_release(struct file *file) | |||
| 1213 | retval = si470x_stop(radio); | 1214 | retval = si470x_stop(radio); |
| 1214 | usb_autopm_put_interface(radio->intf); | 1215 | usb_autopm_put_interface(radio->intf); |
| 1215 | } | 1216 | } |
| 1216 | 1217 | unlock: | |
| 1217 | mutex_unlock(&radio->disconnect_lock); | 1218 | mutex_unlock(&radio->disconnect_lock); |
| 1218 | |||
| 1219 | done: | 1219 | done: |
| 1220 | return retval; | 1220 | return retval; |
| 1221 | } | 1221 | } |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 061e147f6f26..84b6fc15519d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -312,6 +312,14 @@ config VIDEO_OV7670 | |||
| 312 | OV7670 VGA camera. It currently only works with the M88ALP01 | 312 | OV7670 VGA camera. It currently only works with the M88ALP01 |
| 313 | controller. | 313 | controller. |
| 314 | 314 | ||
| 315 | config VIDEO_MT9V011 | ||
| 316 | tristate "Micron mt9v011 sensor support" | ||
| 317 | depends on I2C && VIDEO_V4L2 | ||
| 318 | ---help--- | ||
| 319 | This is a Video4Linux2 sensor-level driver for the Micron | ||
| 320 | mt0v011 1.3 Mpixel camera. It currently only works with the | ||
| 321 | em28xx driver. | ||
| 322 | |||
| 315 | config VIDEO_TCM825X | 323 | config VIDEO_TCM825X |
| 316 | tristate "TCM825x camera sensor support" | 324 | tristate "TCM825x camera sensor support" |
| 317 | depends on I2C && VIDEO_V4L2 | 325 | depends on I2C && VIDEO_V4L2 |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7fb3add1b387..9f2e3214a482 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
| @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | |||
| 69 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | 69 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o |
| 70 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | 70 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
| 71 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 71 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
| 72 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | ||
| 72 | 73 | ||
| 73 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 74 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
| 74 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | 75 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 5eb1464af670..d147d29bb0d3 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/fs.h> | 41 | #include <linux/fs.h> |
| 42 | #include <linux/kernel.h> | 42 | #include <linux/kernel.h> |
| 43 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
| 44 | #include <linux/smp_lock.h> | ||
| 44 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
| 45 | #include <linux/kdev_t.h> | 46 | #include <linux/kdev_t.h> |
| 46 | #include "bttvp.h" | 47 | #include "bttvp.h" |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index c92a25036f0e..36f2d76006fd 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
| @@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { | |||
| 198 | 198 | ||
| 199 | static const struct cx18_card cx18_card_mpc718 = { | 199 | static const struct cx18_card cx18_card_mpc718 = { |
| 200 | .type = CX18_CARD_YUAN_MPC718, | 200 | .type = CX18_CARD_YUAN_MPC718, |
| 201 | .name = "Yuan MPC718", | 201 | .name = "Yuan MPC718 MiniPCI DVB-T/Analog", |
| 202 | .comment = "Analog video capture works; some audio line in may not.\n", | 202 | .comment = "Experimenters needed for device to work well.\n" |
| 203 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
| 203 | .v4l2_capabilities = CX18_CAP_ENCODER, | 204 | .v4l2_capabilities = CX18_CAP_ENCODER, |
| 204 | .hw_audio_ctrl = CX18_HW_418_AV, | 205 | .hw_audio_ctrl = CX18_HW_418_AV, |
| 205 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, | 206 | .hw_muxer = CX18_HW_GPIO_MUX, |
| 207 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | | ||
| 208 | CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, | ||
| 206 | .video_inputs = { | 209 | .video_inputs = { |
| 207 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, | 210 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
| 208 | { CX18_CARD_INPUT_SVIDEO1, 1, | 211 | { CX18_CARD_INPUT_SVIDEO1, 1, |
| @@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
| 211 | { CX18_CARD_INPUT_SVIDEO2, 2, | 214 | { CX18_CARD_INPUT_SVIDEO2, 2, |
| 212 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, | 215 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, |
| 213 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, | 216 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, |
| 214 | { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, | ||
| 215 | }, | 217 | }, |
| 216 | .audio_inputs = { | 218 | .audio_inputs = { |
| 217 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | 219 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
| 218 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, | 220 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, |
| 219 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 }, | 221 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, |
| 220 | }, | 222 | }, |
| 221 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 }, | ||
| 222 | .tuners = { | 223 | .tuners = { |
| 223 | /* XC3028 tuner */ | 224 | /* XC3028 tuner */ |
| 224 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 225 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
| 225 | }, | 226 | }, |
| 227 | /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ | ||
| 228 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, | ||
| 226 | .ddr = { | 229 | .ddr = { |
| 227 | /* Probably Samsung K4D263238G-VC33 memory */ | 230 | /* Hynix HY5DU283222B DDR RAM */ |
| 228 | .chip_config = 0x003, | 231 | .chip_config = 0x303, |
| 229 | .refresh = 0x30c, | 232 | .refresh = 0x3bd, |
| 230 | .timing1 = 0x23230b73, | 233 | .timing1 = 0x36320966, |
| 231 | .timing2 = 0x08, | 234 | .timing2 = 0x1f, |
| 232 | .tune_lane = 0, | 235 | .tune_lane = 0, |
| 233 | .initial_emrs = 2, | 236 | .initial_emrs = 2, |
| 234 | }, | 237 | }, |
| 238 | .gpio_init.initial_value = 0x1, | ||
| 239 | .gpio_init.direction = 0x3, | ||
| 240 | /* FIXME - these GPIO's are just guesses */ | ||
| 241 | .gpio_audio_input = { .mask = 0x3, | ||
| 242 | .tuner = 0x1, | ||
| 243 | .linein = 0x3, | ||
| 244 | .radio = 0x1 }, | ||
| 235 | .xceive_pin = 0, | 245 | .xceive_pin = 0, |
| 236 | .pci_list = cx18_pci_mpc718, | 246 | .pci_list = cx18_pci_mpc718, |
| 237 | .i2c = &cx18_i2c_std, | 247 | .i2c = &cx18_i2c_std, |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623ef4..51a0c33b25b7 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
| @@ -30,6 +30,10 @@ | |||
| 30 | #include "s5h1409.h" | 30 | #include "s5h1409.h" |
| 31 | #include "mxl5005s.h" | 31 | #include "mxl5005s.h" |
| 32 | #include "zl10353.h" | 32 | #include "zl10353.h" |
| 33 | |||
| 34 | #include <linux/firmware.h> | ||
| 35 | #include "mt352.h" | ||
| 36 | #include "mt352_priv.h" | ||
| 33 | #include "tuner-xc2028.h" | 37 | #include "tuner-xc2028.h" |
| 34 | 38 | ||
| 35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 39 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| @@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 38 | #define CX18_CLOCK_ENABLE2 0xc71024 | 42 | #define CX18_CLOCK_ENABLE2 0xc71024 |
| 39 | #define CX18_DMUX_CLK_MASK 0x0080 | 43 | #define CX18_DMUX_CLK_MASK 0x0080 |
| 40 | 44 | ||
| 45 | /* | ||
| 46 | * CX18_CARD_HVR_1600_ESMT | ||
| 47 | * CX18_CARD_HVR_1600_SAMSUNG | ||
| 48 | */ | ||
| 49 | |||
| 41 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { | 50 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { |
| 42 | .i2c_address = 0xC6 >> 1, | 51 | .i2c_address = 0xC6 >> 1, |
| 43 | .if_freq = IF_FREQ_5380000HZ, | 52 | .if_freq = IF_FREQ_5380000HZ, |
| @@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
| 65 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 74 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
| 66 | }; | 75 | }; |
| 67 | 76 | ||
| 77 | /* | ||
| 78 | * CX18_CARD_LEADTEK_DVR3100H | ||
| 79 | */ | ||
| 68 | /* Information/confirmation of proper config values provided by Terry Wu */ | 80 | /* Information/confirmation of proper config values provided by Terry Wu */ |
| 69 | static struct zl10353_config leadtek_dvr3100h_demod = { | 81 | static struct zl10353_config leadtek_dvr3100h_demod = { |
| 70 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | 82 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ |
| @@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { | |||
| 74 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | 86 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ |
| 75 | }; | 87 | }; |
| 76 | 88 | ||
| 89 | /* | ||
| 90 | * CX18_CARD_YUAN_MPC718 | ||
| 91 | */ | ||
| 92 | /* | ||
| 93 | * Due to | ||
| 94 | * | ||
| 95 | * 1. an absence of information on how to prgram the MT352 | ||
| 96 | * 2. the Linux mt352 module pushing MT352 initialzation off onto us here | ||
| 97 | * | ||
| 98 | * We have to use an init sequence that *you* must extract from the Windows | ||
| 99 | * driver (yuanrap.sys) and which we load as a firmware. | ||
| 100 | * | ||
| 101 | * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual | ||
| 102 | * with chip programming details, then I can remove this annoyance. | ||
| 103 | */ | ||
| 104 | static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, | ||
| 105 | const struct firmware **fw) | ||
| 106 | { | ||
| 107 | struct cx18 *cx = stream->cx; | ||
| 108 | const char *fn = "dvb-cx18-mpc718-mt352.fw"; | ||
| 109 | int ret; | ||
| 110 | |||
| 111 | ret = request_firmware(fw, fn, &cx->pci_dev->dev); | ||
| 112 | if (ret) | ||
| 113 | CX18_ERR("Unable to open firmware file %s\n", fn); | ||
| 114 | else { | ||
| 115 | size_t sz = (*fw)->size; | ||
| 116 | if (sz < 2 || sz > 64 || (sz % 2) != 0) { | ||
| 117 | CX18_ERR("Firmware %s has a bad size: %lu bytes\n", | ||
| 118 | fn, (unsigned long) sz); | ||
| 119 | ret = -EILSEQ; | ||
| 120 | release_firmware(*fw); | ||
| 121 | *fw = NULL; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | if (ret) { | ||
| 126 | CX18_ERR("The MPC718 board variant with the MT352 DVB-T" | ||
| 127 | "demodualtor will not work without it\n"); | ||
| 128 | CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " | ||
| 129 | "mpc718' if you need the firmware\n"); | ||
| 130 | } | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) | ||
| 135 | { | ||
| 136 | struct cx18_dvb *dvb = container_of(fe->dvb, | ||
| 137 | struct cx18_dvb, dvb_adapter); | ||
| 138 | struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); | ||
| 139 | const struct firmware *fw = NULL; | ||
| 140 | int ret; | ||
| 141 | int i; | ||
| 142 | u8 buf[3]; | ||
| 143 | |||
| 144 | ret = yuan_mpc718_mt352_reqfw(stream, &fw); | ||
| 145 | if (ret) | ||
| 146 | return ret; | ||
| 147 | |||
| 148 | /* Loop through all the register-value pairs in the firmware file */ | ||
| 149 | for (i = 0; i < fw->size; i += 2) { | ||
| 150 | buf[0] = fw->data[i]; | ||
| 151 | /* Intercept a few registers we want to set ourselves */ | ||
| 152 | switch (buf[0]) { | ||
| 153 | case TRL_NOMINAL_RATE_0: | ||
| 154 | /* Set our custom OFDM bandwidth in the case below */ | ||
| 155 | break; | ||
| 156 | case TRL_NOMINAL_RATE_1: | ||
| 157 | /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ | ||
| 158 | /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ | ||
| 159 | /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ | ||
| 160 | buf[1] = 0x72; | ||
| 161 | buf[2] = 0x49; | ||
| 162 | mt352_write(fe, buf, 3); | ||
| 163 | break; | ||
| 164 | case INPUT_FREQ_0: | ||
| 165 | /* Set our custom IF in the case below */ | ||
| 166 | break; | ||
| 167 | case INPUT_FREQ_1: | ||
| 168 | /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ | ||
| 169 | buf[1] = 0x31; | ||
| 170 | buf[2] = 0xc0; | ||
| 171 | mt352_write(fe, buf, 3); | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | /* Pass through the register-value pair from the fw */ | ||
| 175 | buf[1] = fw->data[i+1]; | ||
| 176 | mt352_write(fe, buf, 2); | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | buf[0] = (u8) TUNER_GO; | ||
| 182 | buf[1] = 0x01; /* Go */ | ||
| 183 | mt352_write(fe, buf, 2); | ||
| 184 | release_firmware(fw); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static struct mt352_config yuan_mpc718_mt352_demod = { | ||
| 189 | .demod_address = 0x1e >> 1, | ||
| 190 | .adc_clock = 20480, /* 20.480 MHz */ | ||
| 191 | .if2 = 4560, /* 4.560 MHz */ | ||
| 192 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
| 193 | .demod_init = yuan_mpc718_mt352_init, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static struct zl10353_config yuan_mpc718_zl10353_demod = { | ||
| 197 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | ||
| 198 | .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ | ||
| 199 | .parallel_ts = 1, /* Not a serial TS */ | ||
| 200 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
| 201 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | ||
| 202 | }; | ||
| 203 | |||
| 77 | static int dvb_register(struct cx18_stream *stream); | 204 | static int dvb_register(struct cx18_stream *stream); |
| 78 | 205 | ||
| 79 | /* Kernel DVB framework calls this when the feed needs to start. | 206 | /* Kernel DVB framework calls this when the feed needs to start. |
| @@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
| 113 | break; | 240 | break; |
| 114 | 241 | ||
| 115 | case CX18_CARD_LEADTEK_DVR3100H: | 242 | case CX18_CARD_LEADTEK_DVR3100H: |
| 243 | case CX18_CARD_YUAN_MPC718: | ||
| 116 | default: | 244 | default: |
| 117 | /* Assumption - Parallel transport - Signalling | 245 | /* Assumption - Parallel transport - Signalling |
| 118 | * undefined or default. | 246 | * undefined or default. |
| @@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) | |||
| 326 | fe->ops.tuner_ops.set_config(fe, &ctrl); | 454 | fe->ops.tuner_ops.set_config(fe, &ctrl); |
| 327 | } | 455 | } |
| 328 | break; | 456 | break; |
| 457 | case CX18_CARD_YUAN_MPC718: | ||
| 458 | /* | ||
| 459 | * TODO | ||
| 460 | * Apparently, these cards also could instead have a | ||
| 461 | * DiBcom demod supported by one of the db7000 drivers | ||
| 462 | */ | ||
| 463 | dvb->fe = dvb_attach(mt352_attach, | ||
| 464 | &yuan_mpc718_mt352_demod, | ||
| 465 | &cx->i2c_adap[1]); | ||
| 466 | if (dvb->fe == NULL) | ||
| 467 | dvb->fe = dvb_attach(zl10353_attach, | ||
| 468 | &yuan_mpc718_zl10353_demod, | ||
| 469 | &cx->i2c_adap[1]); | ||
| 470 | if (dvb->fe != NULL) { | ||
| 471 | struct dvb_frontend *fe; | ||
| 472 | struct xc2028_config cfg = { | ||
| 473 | .i2c_adap = &cx->i2c_adap[1], | ||
| 474 | .i2c_addr = 0xc2 >> 1, | ||
| 475 | .ctrl = NULL, | ||
| 476 | }; | ||
| 477 | static struct xc2028_ctrl ctrl = { | ||
| 478 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 479 | .max_len = 64, | ||
| 480 | .demod = XC3028_FE_ZARLINK456, | ||
| 481 | .type = XC2028_AUTO, | ||
| 482 | }; | ||
| 483 | |||
| 484 | fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); | ||
| 485 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
| 486 | fe->ops.tuner_ops.set_config(fe, &ctrl); | ||
| 487 | } | ||
| 488 | break; | ||
| 329 | default: | 489 | default: |
| 330 | /* No Digital Tv Support */ | 490 | /* No Digital Tv Support */ |
| 331 | break; | 491 | break; |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 2943bfd32a94..428f0c45e6b7 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
| 32 | #include <linux/device.h> | 32 | #include <linux/device.h> |
| 33 | #include <linux/firmware.h> | 33 | #include <linux/firmware.h> |
| 34 | #include <linux/smp_lock.h> | ||
| 34 | #include <media/v4l2-common.h> | 35 | #include <media/v4l2-common.h> |
| 35 | #include <media/v4l2-ioctl.h> | 36 | #include <media/v4l2-ioctl.h> |
| 36 | #include <media/cx2341x.h> | 37 | #include <media/cx2341x.h> |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 48a975134ac5..86ac529e62be 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
| @@ -463,6 +463,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = { | |||
| 463 | .if_khz = 5380, | 463 | .if_khz = 5380, |
| 464 | }; | 464 | }; |
| 465 | 465 | ||
| 466 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, | ||
| 467 | struct dvb_frontend_parameters *param) | ||
| 468 | { | ||
| 469 | struct cx23885_tsport *port = fe->dvb->priv; | ||
| 470 | struct cx23885_dev *dev = port->dev; | ||
| 471 | |||
| 472 | switch (dev->board) { | ||
| 473 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | ||
| 474 | switch (param->u.vsb.modulation) { | ||
| 475 | case VSB_8: | ||
| 476 | cx23885_gpio_clear(dev, GPIO_5); | ||
| 477 | break; | ||
| 478 | case QAM_64: | ||
| 479 | case QAM_256: | ||
| 480 | default: | ||
| 481 | cx23885_gpio_set(dev, GPIO_5); | ||
| 482 | break; | ||
| 483 | } | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | return (port->set_frontend_save) ? | ||
| 487 | port->set_frontend_save(fe, param) : -ENODEV; | ||
| 488 | } | ||
| 489 | |||
| 466 | static int dvb_register(struct cx23885_tsport *port) | 490 | static int dvb_register(struct cx23885_tsport *port) |
| 467 | { | 491 | { |
| 468 | struct cx23885_dev *dev = port->dev; | 492 | struct cx23885_dev *dev = port->dev; |
| @@ -502,6 +526,12 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 502 | 0x60, &dev->i2c_bus[1].i2c_adap, | 526 | 0x60, &dev->i2c_bus[1].i2c_adap, |
| 503 | &hauppauge_hvr127x_config); | 527 | &hauppauge_hvr127x_config); |
| 504 | } | 528 | } |
| 529 | |||
| 530 | /* FIXME: temporary hack */ | ||
| 531 | /* define bridge override to set_frontend */ | ||
| 532 | port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; | ||
| 533 | fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; | ||
| 534 | |||
| 505 | break; | 535 | break; |
| 506 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 536 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
| 507 | i2c_bus = &dev->i2c_bus[0]; | 537 | i2c_bus = &dev->i2c_bus[0]; |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 70836af3ab48..5d6093336300 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/kmod.h> | 26 | #include <linux/kmod.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
| 30 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
| 31 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 1a2ac518a3f1..214a55e943b7 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
| @@ -288,6 +288,10 @@ struct cx23885_tsport { | |||
| 288 | /* Allow a single tsport to have multiple frontends */ | 288 | /* Allow a single tsport to have multiple frontends */ |
| 289 | u32 num_frontends; | 289 | u32 num_frontends; |
| 290 | void *port_priv; | 290 | void *port_priv; |
| 291 | |||
| 292 | /* FIXME: temporary hack */ | ||
| 293 | int (*set_frontend_save) (struct dvb_frontend *, | ||
| 294 | struct dvb_frontend_parameters *); | ||
| 291 | }; | 295 | }; |
| 292 | 296 | ||
| 293 | struct cx23885_dev { | 297 | struct cx23885_dev { |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 44eacfb0d0d6..356d6896da3f 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/device.h> | 33 | #include <linux/device.h> |
| 34 | #include <linux/firmware.h> | 34 | #include <linux/firmware.h> |
| 35 | #include <linux/smp_lock.h> | ||
| 35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 36 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
| 37 | #include <media/cx2341x.h> | 38 | #include <media/cx2341x.h> |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index b12770848c00..2bb54c3ef5cd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/kmod.h> | 31 | #include <linux/kmod.h> |
| 32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/smp_lock.h> | ||
| 34 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
| 35 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
| 36 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index ec2f45dde164..0664d111085f 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/smp_lock.h> | ||
| 35 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | #include <asm/atomic.h> | 38 | #include <asm/atomic.h> |
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 16a5af30e9d1..6524b493e033 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig | |||
| @@ -8,6 +8,8 @@ config VIDEO_EM28XX | |||
| 8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
| 9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO | 9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO |
| 10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO | 10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO |
| 11 | select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO | ||
| 12 | |||
| 11 | ---help--- | 13 | ---help--- |
| 12 | This is a video4linux driver for Empia 28xx based TV cards. | 14 | This is a video4linux driver for Empia 28xx based TV cards. |
| 13 | 15 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c43fdb9bc888..ebd24a25fb85 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
| @@ -58,6 +58,8 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | |||
| 58 | module_param_array(card, int, NULL, 0444); | 58 | module_param_array(card, int, NULL, 0444); |
| 59 | MODULE_PARM_DESC(card, "card type"); | 59 | MODULE_PARM_DESC(card, "card type"); |
| 60 | 60 | ||
| 61 | #define MT9V011_VERSION 0x8243 | ||
| 62 | |||
| 61 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ | 63 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ |
| 62 | static unsigned long em28xx_devused; | 64 | static unsigned long em28xx_devused; |
| 63 | 65 | ||
| @@ -191,6 +193,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { | |||
| 191 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | 193 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, |
| 192 | { -1, -1, -1, -1}, | 194 | { -1, -1, -1, -1}, |
| 193 | }; | 195 | }; |
| 196 | |||
| 197 | static struct em28xx_reg_seq silvercrest_reg_seq[] = { | ||
| 198 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | ||
| 199 | {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, | ||
| 200 | { -1, -1, -1, -1}, | ||
| 201 | }; | ||
| 202 | |||
| 194 | /* | 203 | /* |
| 195 | * Board definitions | 204 | * Board definitions |
| 196 | */ | 205 | */ |
| @@ -438,6 +447,18 @@ struct em28xx_board em28xx_boards[] = { | |||
| 438 | .amux = EM28XX_AMUX_VIDEO, | 447 | .amux = EM28XX_AMUX_VIDEO, |
| 439 | } }, | 448 | } }, |
| 440 | }, | 449 | }, |
| 450 | [EM2820_BOARD_SILVERCREST_WEBCAM] = { | ||
| 451 | .name = "Silvercrest Webcam 1.3mpix", | ||
| 452 | .tuner_type = TUNER_ABSENT, | ||
| 453 | .is_27xx = 1, | ||
| 454 | .decoder = EM28XX_MT9V011, | ||
| 455 | .input = { { | ||
| 456 | .type = EM28XX_VMUX_COMPOSITE1, | ||
| 457 | .vmux = 0, | ||
| 458 | .amux = EM28XX_AMUX_VIDEO, | ||
| 459 | .gpio = silvercrest_reg_seq, | ||
| 460 | } }, | ||
| 461 | }, | ||
| 441 | [EM2821_BOARD_SUPERCOMP_USB_2] = { | 462 | [EM2821_BOARD_SUPERCOMP_USB_2] = { |
| 442 | .name = "Supercomp USB 2.0 TV", | 463 | .name = "Supercomp USB 2.0 TV", |
| 443 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 464 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
| @@ -826,7 +847,7 @@ struct em28xx_board em28xx_boards[] = { | |||
| 826 | .tuner_gpio = default_tuner_gpio, | 847 | .tuner_gpio = default_tuner_gpio, |
| 827 | .decoder = EM28XX_TVP5150, | 848 | .decoder = EM28XX_TVP5150, |
| 828 | .has_dvb = 1, | 849 | .has_dvb = 1, |
| 829 | .dvb_gpio = default_analog, | 850 | .dvb_gpio = default_digital, |
| 830 | .input = { { | 851 | .input = { { |
| 831 | .type = EM28XX_VMUX_TELEVISION, | 852 | .type = EM28XX_VMUX_TELEVISION, |
| 832 | .vmux = TVP5150_COMPOSITE0, | 853 | .vmux = TVP5150_COMPOSITE0, |
| @@ -1639,6 +1660,11 @@ static unsigned short tvp5150_addrs[] = { | |||
| 1639 | I2C_CLIENT_END | 1660 | I2C_CLIENT_END |
| 1640 | }; | 1661 | }; |
| 1641 | 1662 | ||
| 1663 | static unsigned short mt9v011_addrs[] = { | ||
| 1664 | 0xba >> 1, | ||
| 1665 | I2C_CLIENT_END | ||
| 1666 | }; | ||
| 1667 | |||
| 1642 | static unsigned short msp3400_addrs[] = { | 1668 | static unsigned short msp3400_addrs[] = { |
| 1643 | 0x80 >> 1, | 1669 | 0x80 >> 1, |
| 1644 | 0x88 >> 1, | 1670 | 0x88 >> 1, |
| @@ -1678,6 +1704,46 @@ static inline void em28xx_set_model(struct em28xx *dev) | |||
| 1678 | EM28XX_I2C_FREQ_100_KHZ; | 1704 | EM28XX_I2C_FREQ_100_KHZ; |
| 1679 | } | 1705 | } |
| 1680 | 1706 | ||
| 1707 | /* HINT method: webcam I2C chips | ||
| 1708 | * | ||
| 1709 | * This method work for webcams with Micron sensors | ||
| 1710 | */ | ||
| 1711 | static int em28xx_hint_sensor(struct em28xx *dev) | ||
| 1712 | { | ||
| 1713 | int rc; | ||
| 1714 | char *sensor_name; | ||
| 1715 | unsigned char cmd; | ||
| 1716 | __be16 version_be; | ||
| 1717 | u16 version; | ||
| 1718 | |||
| 1719 | if (dev->model != EM2820_BOARD_UNKNOWN) | ||
| 1720 | return 0; | ||
| 1721 | |||
| 1722 | dev->i2c_client.addr = 0xba >> 1; | ||
| 1723 | cmd = 0; | ||
| 1724 | i2c_master_send(&dev->i2c_client, &cmd, 1); | ||
| 1725 | rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); | ||
| 1726 | if (rc != 2) | ||
| 1727 | return -EINVAL; | ||
| 1728 | |||
| 1729 | version = be16_to_cpu(version_be); | ||
| 1730 | |||
| 1731 | switch (version) { | ||
| 1732 | case MT9V011_VERSION: | ||
| 1733 | dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; | ||
| 1734 | sensor_name = "mt9v011"; | ||
| 1735 | break; | ||
| 1736 | default: | ||
| 1737 | printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); | ||
| 1738 | return -EINVAL; | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", | ||
| 1742 | sensor_name, em28xx_boards[dev->model].name); | ||
| 1743 | |||
| 1744 | return 0; | ||
| 1745 | } | ||
| 1746 | |||
| 1681 | /* Since em28xx_pre_card_setup() requires a proper dev->model, | 1747 | /* Since em28xx_pre_card_setup() requires a proper dev->model, |
| 1682 | * this won't work for boards with generic PCI IDs | 1748 | * this won't work for boards with generic PCI IDs |
| 1683 | */ | 1749 | */ |
| @@ -1706,7 +1772,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
| 1706 | em28xx_info("chip ID is em2750\n"); | 1772 | em28xx_info("chip ID is em2750\n"); |
| 1707 | break; | 1773 | break; |
| 1708 | case CHIP_ID_EM2820: | 1774 | case CHIP_ID_EM2820: |
| 1709 | em28xx_info("chip ID is em2820\n"); | 1775 | if (dev->board.is_27xx) |
| 1776 | em28xx_info("chip is em2710\n"); | ||
| 1777 | else | ||
| 1778 | em28xx_info("chip ID is em2820\n"); | ||
| 1710 | break; | 1779 | break; |
| 1711 | case CHIP_ID_EM2840: | 1780 | case CHIP_ID_EM2840: |
| 1712 | em28xx_info("chip ID is em2840\n"); | 1781 | em28xx_info("chip ID is em2840\n"); |
| @@ -2158,6 +2227,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
| 2158 | before probing the i2c bus. */ | 2227 | before probing the i2c bus. */ |
| 2159 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 2228 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
| 2160 | break; | 2229 | break; |
| 2230 | case EM2820_BOARD_SILVERCREST_WEBCAM: | ||
| 2231 | /* FIXME: need to document the registers bellow */ | ||
| 2232 | em28xx_write_reg(dev, 0x0d, 0x42); | ||
| 2233 | em28xx_write_reg(dev, 0x13, 0x08); | ||
| 2161 | } | 2234 | } |
| 2162 | 2235 | ||
| 2163 | if (dev->board.has_snapshot_button) | 2236 | if (dev->board.has_snapshot_button) |
| @@ -2189,6 +2262,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
| 2189 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2262 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
| 2190 | "tvp5150", "tvp5150", tvp5150_addrs); | 2263 | "tvp5150", "tvp5150", tvp5150_addrs); |
| 2191 | 2264 | ||
| 2265 | if (dev->board.decoder == EM28XX_MT9V011) | ||
| 2266 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
| 2267 | "mt9v011", "mt9v011", mt9v011_addrs); | ||
| 2268 | |||
| 2192 | if (dev->board.adecoder == EM28XX_TVAUDIO) | 2269 | if (dev->board.adecoder == EM28XX_TVAUDIO) |
| 2193 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2270 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
| 2194 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); | 2271 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); |
| @@ -2333,6 +2410,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2333 | return errCode; | 2410 | return errCode; |
| 2334 | } | 2411 | } |
| 2335 | 2412 | ||
| 2413 | em28xx_hint_sensor(dev); | ||
| 2414 | |||
| 2336 | /* Do board specific init and eeprom reading */ | 2415 | /* Do board specific init and eeprom reading */ |
| 2337 | em28xx_card_setup(dev); | 2416 | em28xx_card_setup(dev); |
| 2338 | 2417 | ||
| @@ -2573,6 +2652,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
| 2573 | retval = em28xx_init_dev(&dev, udev, interface, nr); | 2652 | retval = em28xx_init_dev(&dev, udev, interface, nr); |
| 2574 | if (retval) { | 2653 | if (retval) { |
| 2575 | em28xx_devused &= ~(1<<dev->devno); | 2654 | em28xx_devused &= ~(1<<dev->devno); |
| 2655 | mutex_unlock(&dev->lock); | ||
| 2576 | kfree(dev); | 2656 | kfree(dev); |
| 2577 | goto err; | 2657 | goto err; |
| 2578 | } | 2658 | } |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c8d7ce8fbd36..079ab4d563a6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
| @@ -648,17 +648,28 @@ int em28xx_capture_start(struct em28xx *dev, int start) | |||
| 648 | int em28xx_set_outfmt(struct em28xx *dev) | 648 | int em28xx_set_outfmt(struct em28xx *dev) |
| 649 | { | 649 | { |
| 650 | int ret; | 650 | int ret; |
| 651 | int vinmode, vinctl, outfmt; | ||
| 652 | |||
| 653 | outfmt = dev->format->reg; | ||
| 654 | |||
| 655 | if (dev->board.is_27xx) { | ||
| 656 | vinmode = 0x0d; | ||
| 657 | vinctl = 0x00; | ||
| 658 | } else { | ||
| 659 | vinmode = 0x10; | ||
| 660 | vinctl = 0x11; | ||
| 661 | } | ||
| 651 | 662 | ||
| 652 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, | 663 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, |
| 653 | dev->format->reg | 0x20, 0x3f); | 664 | outfmt | 0x20, 0xff); |
| 654 | if (ret < 0) | 665 | if (ret < 0) |
| 655 | return ret; | 666 | return ret; |
| 656 | 667 | ||
| 657 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); | 668 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); |
| 658 | if (ret < 0) | 669 | if (ret < 0) |
| 659 | return ret; | 670 | return ret; |
| 660 | 671 | ||
| 661 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); | 672 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); |
| 662 | } | 673 | } |
| 663 | 674 | ||
| 664 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, | 675 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, |
| @@ -695,13 +706,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) | |||
| 695 | { | 706 | { |
| 696 | u8 mode; | 707 | u8 mode; |
| 697 | /* the em2800 scaler only supports scaling down to 50% */ | 708 | /* the em2800 scaler only supports scaling down to 50% */ |
| 698 | if (dev->board.is_em2800) | 709 | |
| 710 | if (dev->board.is_27xx) { | ||
| 711 | /* FIXME: Don't use the scaler yet */ | ||
| 712 | mode = 0; | ||
| 713 | } else if (dev->board.is_em2800) { | ||
| 699 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); | 714 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); |
| 700 | else { | 715 | } else { |
| 701 | u8 buf[2]; | 716 | u8 buf[2]; |
| 717 | |||
| 702 | buf[0] = h; | 718 | buf[0] = h; |
| 703 | buf[1] = h >> 8; | 719 | buf[1] = h >> 8; |
| 704 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); | 720 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); |
| 721 | |||
| 705 | buf[0] = v; | 722 | buf[0] = v; |
| 706 | buf[1] = v >> 8; | 723 | buf[1] = v >> 8; |
| 707 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); | 724 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); |
| @@ -720,8 +737,11 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
| 720 | height = norm_maxh(dev) >> 1; | 737 | height = norm_maxh(dev) >> 1; |
| 721 | 738 | ||
| 722 | em28xx_set_outfmt(dev); | 739 | em28xx_set_outfmt(dev); |
| 740 | |||
| 741 | |||
| 723 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); | 742 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); |
| 724 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); | 743 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); |
| 744 | |||
| 725 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); | 745 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); |
| 726 | } | 746 | } |
| 727 | 747 | ||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index e7b47c8da8f3..3da97c32b8fa 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
| @@ -243,6 +243,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { | |||
| 243 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 243 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
| 244 | }; | 244 | }; |
| 245 | 245 | ||
| 246 | static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { | ||
| 247 | .demod_address = (0x1e >> 1), | ||
| 248 | .no_tuner = 1, | ||
| 249 | .disable_i2c_gate_ctrl = 1, | ||
| 250 | .parallel_ts = 1, | ||
| 251 | .if2 = 45600, | ||
| 252 | }; | ||
| 253 | |||
| 246 | #ifdef EM28XX_DRX397XD_SUPPORT | 254 | #ifdef EM28XX_DRX397XD_SUPPORT |
| 247 | /* [TODO] djh - not sure yet what the device config needs to contain */ | 255 | /* [TODO] djh - not sure yet what the device config needs to contain */ |
| 248 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { | 256 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { |
| @@ -433,7 +441,6 @@ static int dvb_init(struct em28xx *dev) | |||
| 433 | } | 441 | } |
| 434 | break; | 442 | break; |
| 435 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 443 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
| 436 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
| 437 | case EM2880_BOARD_KWORLD_DVB_310U: | 444 | case EM2880_BOARD_KWORLD_DVB_310U: |
| 438 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 445 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
| 439 | dvb->frontend = dvb_attach(zl10353_attach, | 446 | dvb->frontend = dvb_attach(zl10353_attach, |
| @@ -444,6 +451,25 @@ static int dvb_init(struct em28xx *dev) | |||
| 444 | goto out_free; | 451 | goto out_free; |
| 445 | } | 452 | } |
| 446 | break; | 453 | break; |
| 454 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
| 455 | dvb->frontend = dvb_attach(zl10353_attach, | ||
| 456 | &em28xx_terratec_xs_zl10353_xc3028, | ||
| 457 | &dev->i2c_adap); | ||
| 458 | if (dvb->frontend == NULL) { | ||
| 459 | /* This board could have either a zl10353 or a mt352. | ||
| 460 | If the chip id isn't for zl10353, try mt352 */ | ||
| 461 | |||
| 462 | /* FIXME: make support for mt352 work */ | ||
| 463 | printk(KERN_ERR "version of this board with mt352 not " | ||
| 464 | "currently supported\n"); | ||
| 465 | result = -EINVAL; | ||
| 466 | goto out_free; | ||
| 467 | } | ||
| 468 | if (attach_xc3028(0x61, dev) < 0) { | ||
| 469 | result = -EINVAL; | ||
| 470 | goto out_free; | ||
| 471 | } | ||
| 472 | break; | ||
| 447 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 473 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
| 448 | case EM2882_BOARD_EVGA_INDTUBE: | 474 | case EM2882_BOARD_EVGA_INDTUBE: |
| 449 | dvb->frontend = dvb_attach(s5h1409_attach, | 475 | dvb->frontend = dvb_attach(s5h1409_attach, |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2c86fcf089f5..27e33a287dfc 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
| @@ -483,7 +483,7 @@ static char *i2c_devs[128] = { | |||
| 483 | [0xa0 >> 1] = "eeprom", | 483 | [0xa0 >> 1] = "eeprom", |
| 484 | [0xb0 >> 1] = "tda9874", | 484 | [0xb0 >> 1] = "tda9874", |
| 485 | [0xb8 >> 1] = "tvp5150a", | 485 | [0xb8 >> 1] = "tvp5150a", |
| 486 | [0xba >> 1] = "tvp5150a", | 486 | [0xba >> 1] = "webcam sensor or tvp5150a", |
| 487 | [0xc0 >> 1] = "tuner (analog)", | 487 | [0xc0 >> 1] = "tuner (analog)", |
| 488 | [0xc2 >> 1] = "tuner (analog)", | 488 | [0xc2 >> 1] = "tuner (analog)", |
| 489 | [0xc4 >> 1] = "tuner (analog)", | 489 | [0xc4 >> 1] = "tuner (analog)", |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8fe1beecfffa..14316c912179 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
| @@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | |||
| 90 | /* supported video standards */ | 90 | /* supported video standards */ |
| 91 | static struct em28xx_fmt format[] = { | 91 | static struct em28xx_fmt format[] = { |
| 92 | { | 92 | { |
| 93 | .name = "16bpp YUY2, 4:2:2, packed", | 93 | .name = "16 bpp YUY2, 4:2:2, packed", |
| 94 | .fourcc = V4L2_PIX_FMT_YUYV, | 94 | .fourcc = V4L2_PIX_FMT_YUYV, |
| 95 | .depth = 16, | 95 | .depth = 16, |
| 96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, | 96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, |
| 97 | }, { | ||
| 98 | .name = "16 bpp RGB 565, LE", | ||
| 99 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
| 100 | .depth = 16, | ||
| 101 | .reg = EM28XX_OUTFMT_RGB_16_656, | ||
| 102 | }, { | ||
| 103 | .name = "8 bpp Bayer BGBG..GRGR", | ||
| 104 | .fourcc = V4L2_PIX_FMT_SBGGR8, | ||
| 105 | .depth = 8, | ||
| 106 | .reg = EM28XX_OUTFMT_RGB_8_BGBG, | ||
| 107 | }, { | ||
| 108 | .name = "8 bpp Bayer GRGR..BGBG", | ||
| 109 | .fourcc = V4L2_PIX_FMT_SGRBG8, | ||
| 110 | .depth = 8, | ||
| 111 | .reg = EM28XX_OUTFMT_RGB_8_GRGR, | ||
| 112 | }, { | ||
| 113 | .name = "8 bpp Bayer GBGB..RGRG", | ||
| 114 | .fourcc = V4L2_PIX_FMT_SGBRG8, | ||
| 115 | .depth = 8, | ||
| 116 | .reg = EM28XX_OUTFMT_RGB_8_GBGB, | ||
| 117 | }, { | ||
| 118 | .name = "12 bpp YUV411", | ||
| 119 | .fourcc = V4L2_PIX_FMT_YUV411P, | ||
| 120 | .depth = 12, | ||
| 121 | .reg = EM28XX_OUTFMT_YUV411, | ||
| 97 | }, | 122 | }, |
| 98 | }; | 123 | }; |
| 99 | 124 | ||
| @@ -701,7 +726,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 701 | return -EINVAL; | 726 | return -EINVAL; |
| 702 | } | 727 | } |
| 703 | 728 | ||
| 704 | if (dev->board.is_em2800) { | 729 | if (dev->board.is_27xx) { |
| 730 | /* FIXME: This is the only supported fmt */ | ||
| 731 | width = 640; | ||
| 732 | height = 480; | ||
| 733 | } else if (dev->board.is_em2800) { | ||
| 705 | /* the em2800 can only scale down to 50% */ | 734 | /* the em2800 can only scale down to 50% */ |
| 706 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; | 735 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; |
| 707 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; | 736 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; |
| @@ -733,13 +762,40 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 733 | return 0; | 762 | return 0; |
| 734 | } | 763 | } |
| 735 | 764 | ||
| 765 | static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, | ||
| 766 | unsigned width, unsigned height) | ||
| 767 | { | ||
| 768 | struct em28xx_fmt *fmt; | ||
| 769 | |||
| 770 | /* FIXME: This is the only supported fmt */ | ||
| 771 | if (dev->board.is_27xx) { | ||
| 772 | width = 640; | ||
| 773 | height = 480; | ||
| 774 | } | ||
| 775 | |||
| 776 | fmt = format_by_fourcc(fourcc); | ||
| 777 | if (!fmt) | ||
| 778 | return -EINVAL; | ||
| 779 | |||
| 780 | dev->format = fmt; | ||
| 781 | dev->width = width; | ||
| 782 | dev->height = height; | ||
| 783 | |||
| 784 | /* set new image size */ | ||
| 785 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
| 786 | |||
| 787 | em28xx_set_alternate(dev); | ||
| 788 | em28xx_resolution_set(dev); | ||
| 789 | |||
| 790 | return 0; | ||
| 791 | } | ||
| 792 | |||
| 736 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 793 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
| 737 | struct v4l2_format *f) | 794 | struct v4l2_format *f) |
| 738 | { | 795 | { |
| 739 | struct em28xx_fh *fh = priv; | 796 | struct em28xx_fh *fh = priv; |
| 740 | struct em28xx *dev = fh->dev; | 797 | struct em28xx *dev = fh->dev; |
| 741 | int rc; | 798 | int rc; |
| 742 | struct em28xx_fmt *fmt; | ||
| 743 | 799 | ||
| 744 | rc = check_dev(dev); | 800 | rc = check_dev(dev); |
| 745 | if (rc < 0) | 801 | if (rc < 0) |
| @@ -749,12 +805,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 749 | 805 | ||
| 750 | vidioc_try_fmt_vid_cap(file, priv, f); | 806 | vidioc_try_fmt_vid_cap(file, priv, f); |
| 751 | 807 | ||
| 752 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
| 753 | if (!fmt) { | ||
| 754 | rc = -EINVAL; | ||
| 755 | goto out; | ||
| 756 | } | ||
| 757 | |||
| 758 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 808 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
| 759 | em28xx_errdev("%s queue busy\n", __func__); | 809 | em28xx_errdev("%s queue busy\n", __func__); |
| 760 | rc = -EBUSY; | 810 | rc = -EBUSY; |
| @@ -767,16 +817,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 767 | goto out; | 817 | goto out; |
| 768 | } | 818 | } |
| 769 | 819 | ||
| 770 | /* set new image size */ | 820 | rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, |
| 771 | dev->width = f->fmt.pix.width; | 821 | f->fmt.pix.width, f->fmt.pix.height); |
| 772 | dev->height = f->fmt.pix.height; | ||
| 773 | dev->format = fmt; | ||
| 774 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
| 775 | |||
| 776 | em28xx_set_alternate(dev); | ||
| 777 | em28xx_resolution_set(dev); | ||
| 778 | |||
| 779 | rc = 0; | ||
| 780 | 822 | ||
| 781 | out: | 823 | out: |
| 782 | mutex_unlock(&dev->lock); | 824 | mutex_unlock(&dev->lock); |
| @@ -1616,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) | |||
| 1616 | filp->private_data = fh; | 1658 | filp->private_data = fh; |
| 1617 | 1659 | ||
| 1618 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { | 1660 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { |
| 1619 | dev->width = norm_maxw(dev); | ||
| 1620 | dev->height = norm_maxh(dev); | ||
| 1621 | dev->hscale = 0; | ||
| 1622 | dev->vscale = 0; | ||
| 1623 | |||
| 1624 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 1661 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
| 1625 | em28xx_set_alternate(dev); | 1662 | em28xx_set_alternate(dev); |
| 1626 | em28xx_resolution_set(dev); | 1663 | em28xx_resolution_set(dev); |
| @@ -1962,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
| 1962 | 1999 | ||
| 1963 | /* set default norm */ | 2000 | /* set default norm */ |
| 1964 | dev->norm = em28xx_video_template.current_norm; | 2001 | dev->norm = em28xx_video_template.current_norm; |
| 1965 | dev->width = norm_maxw(dev); | ||
| 1966 | dev->height = norm_maxh(dev); | ||
| 1967 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | 2002 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; |
| 1968 | dev->hscale = 0; | ||
| 1969 | dev->vscale = 0; | ||
| 1970 | dev->ctl_input = 0; | 2003 | dev->ctl_input = 0; |
| 1971 | 2004 | ||
| 1972 | /* Analog specific initialization */ | 2005 | /* Analog specific initialization */ |
| 1973 | dev->format = &format[0]; | 2006 | dev->format = &format[0]; |
| 2007 | em28xx_set_video_format(dev, format[0].fourcc, | ||
| 2008 | norm_maxw(dev), norm_maxh(dev)); | ||
| 2009 | |||
| 1974 | video_mux(dev, dev->ctl_input); | 2010 | video_mux(dev, dev->ctl_input); |
| 1975 | 2011 | ||
| 1976 | /* Audio defaults */ | 2012 | /* Audio defaults */ |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 813ce45c2f99..d90fef463764 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
| @@ -107,6 +107,7 @@ | |||
| 107 | #define EM2860_BOARD_TERRATEC_AV350 68 | 107 | #define EM2860_BOARD_TERRATEC_AV350 68 |
| 108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 | 108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 |
| 109 | #define EM2882_BOARD_EVGA_INDTUBE 70 | 109 | #define EM2882_BOARD_EVGA_INDTUBE 70 |
| 110 | #define EM2820_BOARD_SILVERCREST_WEBCAM 71 | ||
| 110 | 111 | ||
| 111 | /* Limits minimum and default number of buffers */ | 112 | /* Limits minimum and default number of buffers */ |
| 112 | #define EM28XX_MIN_BUF 4 | 113 | #define EM28XX_MIN_BUF 4 |
| @@ -360,6 +361,7 @@ enum em28xx_decoder { | |||
| 360 | EM28XX_NODECODER, | 361 | EM28XX_NODECODER, |
| 361 | EM28XX_TVP5150, | 362 | EM28XX_TVP5150, |
| 362 | EM28XX_SAA711X, | 363 | EM28XX_SAA711X, |
| 364 | EM28XX_MT9V011, | ||
| 363 | }; | 365 | }; |
| 364 | 366 | ||
| 365 | enum em28xx_adecoder { | 367 | enum em28xx_adecoder { |
| @@ -388,6 +390,7 @@ struct em28xx_board { | |||
| 388 | unsigned int max_range_640_480:1; | 390 | unsigned int max_range_640_480:1; |
| 389 | unsigned int has_dvb:1; | 391 | unsigned int has_dvb:1; |
| 390 | unsigned int has_snapshot_button:1; | 392 | unsigned int has_snapshot_button:1; |
| 393 | unsigned int is_27xx:1; | ||
| 391 | unsigned int valid:1; | 394 | unsigned int valid:1; |
| 392 | 395 | ||
| 393 | unsigned char xclk, i2c_speed; | 396 | unsigned char xclk, i2c_speed; |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 9df7137fe67e..992ce530f138 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h | |||
| @@ -36,10 +36,6 @@ | |||
| 36 | 36 | ||
| 37 | #define STV_ISOC_ENDPOINT_ADDR 0x81 | 37 | #define STV_ISOC_ENDPOINT_ADDR 0x81 |
| 38 | 38 | ||
| 39 | #ifndef V4L2_PIX_FMT_SGRBG8 | ||
| 40 | #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #define STV_REG23 0x0423 | 39 | #define STV_REG23 0x0423 |
| 44 | 40 | ||
| 45 | /* Control registers of the STV0600 ASIC */ | 41 | /* Control registers of the STV0600 ASIC */ |
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c new file mode 100644 index 000000000000..1fe8fc9183a7 --- /dev/null +++ b/drivers/media/video/mt9v011.c | |||
| @@ -0,0 +1,431 @@ | |||
| 1 | /* | ||
| 2 | * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) | ||
| 5 | * This code is placed under the terms of the GNU General Public License v2 | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/i2c.h> | ||
| 9 | #include <linux/videodev2.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <media/v4l2-device.h> | ||
| 12 | #include "mt9v011.h" | ||
| 13 | #include <media/v4l2-i2c-drv.h> | ||
| 14 | #include <media/v4l2-chip-ident.h> | ||
| 15 | |||
| 16 | MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); | ||
| 17 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | |||
| 20 | |||
| 21 | static int debug; | ||
| 22 | module_param(debug, int, 0); | ||
| 23 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
| 24 | |||
| 25 | /* supported controls */ | ||
| 26 | static struct v4l2_queryctrl mt9v011_qctrl[] = { | ||
| 27 | { | ||
| 28 | .id = V4L2_CID_GAIN, | ||
| 29 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 30 | .name = "Gain", | ||
| 31 | .minimum = 0, | ||
| 32 | .maximum = (1 << 10) - 1, | ||
| 33 | .step = 1, | ||
| 34 | .default_value = 0x0020, | ||
| 35 | .flags = 0, | ||
| 36 | }, { | ||
| 37 | .id = V4L2_CID_RED_BALANCE, | ||
| 38 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 39 | .name = "Red Balance", | ||
| 40 | .minimum = -1 << 9, | ||
| 41 | .maximum = (1 << 9) - 1, | ||
| 42 | .step = 1, | ||
| 43 | .default_value = 0, | ||
| 44 | .flags = 0, | ||
| 45 | }, { | ||
| 46 | .id = V4L2_CID_BLUE_BALANCE, | ||
| 47 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 48 | .name = "Blue Balance", | ||
| 49 | .minimum = -1 << 9, | ||
| 50 | .maximum = (1 << 9) - 1, | ||
| 51 | .step = 1, | ||
| 52 | .default_value = 0, | ||
| 53 | .flags = 0, | ||
| 54 | }, | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct mt9v011 { | ||
| 58 | struct v4l2_subdev sd; | ||
| 59 | unsigned width, height; | ||
| 60 | |||
| 61 | u16 global_gain, red_bal, blue_bal; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) | ||
| 65 | { | ||
| 66 | return container_of(sd, struct mt9v011, sd); | ||
| 67 | } | ||
| 68 | |||
| 69 | static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) | ||
| 70 | { | ||
| 71 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
| 72 | __be16 buffer; | ||
| 73 | int rc, val; | ||
| 74 | |||
| 75 | rc = i2c_master_send(c, &addr, 1); | ||
| 76 | if (rc != 1) | ||
| 77 | v4l2_dbg(0, debug, sd, | ||
| 78 | "i2c i/o error: rc == %d (should be 1)\n", rc); | ||
| 79 | |||
| 80 | msleep(10); | ||
| 81 | |||
| 82 | rc = i2c_master_recv(c, (char *)&buffer, 2); | ||
| 83 | if (rc != 2) | ||
| 84 | v4l2_dbg(0, debug, sd, | ||
| 85 | "i2c i/o error: rc == %d (should be 2)\n", rc); | ||
| 86 | |||
| 87 | val = be16_to_cpu(buffer); | ||
| 88 | |||
| 89 | v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); | ||
| 90 | |||
| 91 | return val; | ||
| 92 | } | ||
| 93 | |||
| 94 | static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, | ||
| 95 | u16 value) | ||
| 96 | { | ||
| 97 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
| 98 | unsigned char buffer[3]; | ||
| 99 | int rc; | ||
| 100 | |||
| 101 | buffer[0] = addr; | ||
| 102 | buffer[1] = value >> 8; | ||
| 103 | buffer[2] = value & 0xff; | ||
| 104 | |||
| 105 | v4l2_dbg(2, debug, sd, | ||
| 106 | "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); | ||
| 107 | rc = i2c_master_send(c, buffer, 3); | ||
| 108 | if (rc != 3) | ||
| 109 | v4l2_dbg(0, debug, sd, | ||
| 110 | "i2c i/o error: rc == %d (should be 3)\n", rc); | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 114 | struct i2c_reg_value { | ||
| 115 | unsigned char reg; | ||
| 116 | u16 value; | ||
| 117 | }; | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Values used at the original driver | ||
| 121 | * Some values are marked as Reserved at the datasheet | ||
| 122 | */ | ||
| 123 | static const struct i2c_reg_value mt9v011_init_default[] = { | ||
| 124 | { R0D_MT9V011_RESET, 0x0001 }, | ||
| 125 | { R0D_MT9V011_RESET, 0x0000 }, | ||
| 126 | |||
| 127 | { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, | ||
| 128 | { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, | ||
| 129 | |||
| 130 | { R0A_MT9V011_CLK_SPEED, 0x0000 }, | ||
| 131 | { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, | ||
| 132 | { R20_MT9V011_READ_MODE, 0x1000 }, | ||
| 133 | |||
| 134 | { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ | ||
| 135 | }; | ||
| 136 | |||
| 137 | static void set_balance(struct v4l2_subdev *sd) | ||
| 138 | { | ||
| 139 | struct mt9v011 *core = to_mt9v011(sd); | ||
| 140 | u16 green1_gain, green2_gain, blue_gain, red_gain; | ||
| 141 | |||
| 142 | green1_gain = core->global_gain; | ||
| 143 | green2_gain = core->global_gain; | ||
| 144 | |||
| 145 | blue_gain = core->global_gain + | ||
| 146 | core->global_gain * core->blue_bal / (1 << 9); | ||
| 147 | |||
| 148 | red_gain = core->global_gain + | ||
| 149 | core->global_gain * core->blue_bal / (1 << 9); | ||
| 150 | |||
| 151 | mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain); | ||
| 152 | mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green1_gain); | ||
| 153 | mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); | ||
| 154 | mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void set_res(struct v4l2_subdev *sd) | ||
| 158 | { | ||
| 159 | struct mt9v011 *core = to_mt9v011(sd); | ||
| 160 | unsigned vstart, hstart; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * The mt9v011 doesn't have scaling. So, in order to select the desired | ||
| 164 | * resolution, we're cropping at the middle of the sensor. | ||
| 165 | * hblank and vblank should be adjusted, in order to warrant that | ||
| 166 | * we'll preserve the line timings for 30 fps, no matter what resolution | ||
| 167 | * is selected. | ||
| 168 | * NOTE: datasheet says that width (and height) should be filled with | ||
| 169 | * width-1. However, this doesn't work, since one pixel per line will | ||
| 170 | * be missing. | ||
| 171 | */ | ||
| 172 | |||
| 173 | hstart = 14 + (640 - core->width) / 2; | ||
| 174 | mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); | ||
| 175 | mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); | ||
| 176 | mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); | ||
| 177 | |||
| 178 | vstart = 8 + (640 - core->height) / 2; | ||
| 179 | mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); | ||
| 180 | mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); | ||
| 181 | mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); | ||
| 182 | }; | ||
| 183 | |||
| 184 | static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) | ||
| 185 | { | ||
| 186 | int i; | ||
| 187 | |||
| 188 | for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) | ||
| 189 | mt9v011_write(sd, mt9v011_init_default[i].reg, | ||
| 190 | mt9v011_init_default[i].value); | ||
| 191 | |||
| 192 | set_balance(sd); | ||
| 193 | set_res(sd); | ||
| 194 | |||
| 195 | return 0; | ||
| 196 | }; | ||
| 197 | |||
| 198 | static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
| 199 | { | ||
| 200 | struct mt9v011 *core = to_mt9v011(sd); | ||
| 201 | |||
| 202 | v4l2_dbg(1, debug, sd, "g_ctrl called\n"); | ||
| 203 | |||
| 204 | switch (ctrl->id) { | ||
| 205 | case V4L2_CID_GAIN: | ||
| 206 | ctrl->value = core->global_gain; | ||
| 207 | return 0; | ||
| 208 | case V4L2_CID_RED_BALANCE: | ||
| 209 | ctrl->value = core->red_bal; | ||
| 210 | return 0; | ||
| 211 | case V4L2_CID_BLUE_BALANCE: | ||
| 212 | ctrl->value = core->blue_bal; | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | return -EINVAL; | ||
| 216 | } | ||
| 217 | |||
| 218 | static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
| 219 | { | ||
| 220 | struct mt9v011 *core = to_mt9v011(sd); | ||
| 221 | u8 i, n; | ||
| 222 | n = ARRAY_SIZE(mt9v011_qctrl); | ||
| 223 | |||
| 224 | for (i = 0; i < n; i++) { | ||
| 225 | if (ctrl->id != mt9v011_qctrl[i].id) | ||
| 226 | continue; | ||
| 227 | if (ctrl->value < mt9v011_qctrl[i].minimum || | ||
| 228 | ctrl->value > mt9v011_qctrl[i].maximum) | ||
| 229 | return -ERANGE; | ||
| 230 | v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", | ||
| 231 | ctrl->id, ctrl->value); | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 235 | switch (ctrl->id) { | ||
| 236 | case V4L2_CID_GAIN: | ||
| 237 | core->global_gain = ctrl->value; | ||
| 238 | break; | ||
| 239 | case V4L2_CID_RED_BALANCE: | ||
| 240 | core->red_bal = ctrl->value; | ||
| 241 | break; | ||
| 242 | case V4L2_CID_BLUE_BALANCE: | ||
| 243 | core->blue_bal = ctrl->value; | ||
| 244 | break; | ||
| 245 | default: | ||
| 246 | return -EINVAL; | ||
| 247 | } | ||
| 248 | |||
| 249 | set_balance(sd); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) | ||
| 255 | { | ||
| 256 | if (fmt->index > 0) | ||
| 257 | return -EINVAL; | ||
| 258 | |||
| 259 | fmt->flags = 0; | ||
| 260 | strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); | ||
| 261 | fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
| 267 | { | ||
| 268 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
| 269 | |||
| 270 | if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) | ||
| 271 | return -EINVAL; | ||
| 272 | |||
| 273 | v4l_bound_align_image(&pix->width, 48, 639, 1, | ||
| 274 | &pix->height, 32, 480, 1, 0); | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
| 280 | { | ||
| 281 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
| 282 | struct mt9v011 *core = to_mt9v011(sd); | ||
| 283 | int rc; | ||
| 284 | |||
| 285 | rc = mt9v011_try_fmt(sd, fmt); | ||
| 286 | if (rc < 0) | ||
| 287 | return -EINVAL; | ||
| 288 | |||
| 289 | core->width = pix->width; | ||
| 290 | core->height = pix->height; | ||
| 291 | |||
| 292 | set_res(sd); | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | |||
| 298 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 299 | static int mt9v011_g_register(struct v4l2_subdev *sd, | ||
| 300 | struct v4l2_dbg_register *reg) | ||
| 301 | { | ||
| 302 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 303 | |||
| 304 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
| 305 | return -EINVAL; | ||
| 306 | if (!capable(CAP_SYS_ADMIN)) | ||
| 307 | return -EPERM; | ||
| 308 | |||
| 309 | reg->val = mt9v011_read(sd, reg->reg & 0xff); | ||
| 310 | reg->size = 2; | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int mt9v011_s_register(struct v4l2_subdev *sd, | ||
| 316 | struct v4l2_dbg_register *reg) | ||
| 317 | { | ||
| 318 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 319 | |||
| 320 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
| 321 | return -EINVAL; | ||
| 322 | if (!capable(CAP_SYS_ADMIN)) | ||
| 323 | return -EPERM; | ||
| 324 | |||
| 325 | mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | #endif | ||
| 330 | |||
| 331 | static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, | ||
| 332 | struct v4l2_dbg_chip_ident *chip) | ||
| 333 | { | ||
| 334 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 335 | |||
| 336 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, | ||
| 337 | MT9V011_VERSION); | ||
| 338 | } | ||
| 339 | |||
| 340 | static const struct v4l2_subdev_core_ops mt9v011_core_ops = { | ||
| 341 | .g_ctrl = mt9v011_g_ctrl, | ||
| 342 | .s_ctrl = mt9v011_s_ctrl, | ||
| 343 | .reset = mt9v011_reset, | ||
| 344 | .g_chip_ident = mt9v011_g_chip_ident, | ||
| 345 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 346 | .g_register = mt9v011_g_register, | ||
| 347 | .s_register = mt9v011_s_register, | ||
| 348 | #endif | ||
| 349 | }; | ||
| 350 | |||
| 351 | static const struct v4l2_subdev_video_ops mt9v011_video_ops = { | ||
| 352 | .enum_fmt = mt9v011_enum_fmt, | ||
| 353 | .try_fmt = mt9v011_try_fmt, | ||
| 354 | .s_fmt = mt9v011_s_fmt, | ||
| 355 | }; | ||
| 356 | |||
| 357 | static const struct v4l2_subdev_ops mt9v011_ops = { | ||
| 358 | .core = &mt9v011_core_ops, | ||
| 359 | .video = &mt9v011_video_ops, | ||
| 360 | }; | ||
| 361 | |||
| 362 | |||
| 363 | /**************************************************************************** | ||
| 364 | I2C Client & Driver | ||
| 365 | ****************************************************************************/ | ||
| 366 | |||
| 367 | static int mt9v011_probe(struct i2c_client *c, | ||
| 368 | const struct i2c_device_id *id) | ||
| 369 | { | ||
| 370 | u16 version; | ||
| 371 | struct mt9v011 *core; | ||
| 372 | struct v4l2_subdev *sd; | ||
| 373 | |||
| 374 | /* Check if the adapter supports the needed features */ | ||
| 375 | if (!i2c_check_functionality(c->adapter, | ||
| 376 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | ||
| 377 | return -EIO; | ||
| 378 | |||
| 379 | core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); | ||
| 380 | if (!core) | ||
| 381 | return -ENOMEM; | ||
| 382 | |||
| 383 | sd = &core->sd; | ||
| 384 | v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); | ||
| 385 | |||
| 386 | /* Check if the sensor is really a MT9V011 */ | ||
| 387 | version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); | ||
| 388 | if (version != MT9V011_VERSION) { | ||
| 389 | v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", | ||
| 390 | version); | ||
| 391 | kfree(core); | ||
| 392 | return -EINVAL; | ||
| 393 | } | ||
| 394 | |||
| 395 | core->global_gain = 0x0024; | ||
| 396 | core->width = 640; | ||
| 397 | core->height = 480; | ||
| 398 | |||
| 399 | v4l_info(c, "chip found @ 0x%02x (%s)\n", | ||
| 400 | c->addr << 1, c->adapter->name); | ||
| 401 | |||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int mt9v011_remove(struct i2c_client *c) | ||
| 406 | { | ||
| 407 | struct v4l2_subdev *sd = i2c_get_clientdata(c); | ||
| 408 | |||
| 409 | v4l2_dbg(1, debug, sd, | ||
| 410 | "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", | ||
| 411 | c->addr << 1); | ||
| 412 | |||
| 413 | v4l2_device_unregister_subdev(sd); | ||
| 414 | kfree(to_mt9v011(sd)); | ||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | |||
| 418 | /* ----------------------------------------------------------------------- */ | ||
| 419 | |||
| 420 | static const struct i2c_device_id mt9v011_id[] = { | ||
| 421 | { "mt9v011", 0 }, | ||
| 422 | { } | ||
| 423 | }; | ||
| 424 | MODULE_DEVICE_TABLE(i2c, mt9v011_id); | ||
| 425 | |||
| 426 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
| 427 | .name = "mt9v011", | ||
| 428 | .probe = mt9v011_probe, | ||
| 429 | .remove = mt9v011_remove, | ||
| 430 | .id_table = mt9v011_id, | ||
| 431 | }; | ||
diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h new file mode 100644 index 000000000000..9e443ee30558 --- /dev/null +++ b/drivers/media/video/mt9v011.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* | ||
| 2 | * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) | ||
| 5 | * This code is placed under the terms of the GNU General Public License v2 | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef MT9V011_H_ | ||
| 9 | #define MT9V011_H_ | ||
| 10 | |||
| 11 | #define R00_MT9V011_CHIP_VERSION 0x00 | ||
| 12 | #define R01_MT9V011_ROWSTART 0x01 | ||
| 13 | #define R02_MT9V011_COLSTART 0x02 | ||
| 14 | #define R03_MT9V011_HEIGHT 0x03 | ||
| 15 | #define R04_MT9V011_WIDTH 0x04 | ||
| 16 | #define R05_MT9V011_HBLANK 0x05 | ||
| 17 | #define R06_MT9V011_VBLANK 0x06 | ||
| 18 | #define R07_MT9V011_OUT_CTRL 0x07 | ||
| 19 | #define R09_MT9V011_SHUTTER_WIDTH 0x09 | ||
| 20 | #define R0A_MT9V011_CLK_SPEED 0x0a | ||
| 21 | #define R0B_MT9V011_RESTART 0x0b | ||
| 22 | #define R0C_MT9V011_SHUTTER_DELAY 0x0c | ||
| 23 | #define R0D_MT9V011_RESET 0x0d | ||
| 24 | #define R1E_MT9V011_DIGITAL_ZOOM 0x1e | ||
| 25 | #define R20_MT9V011_READ_MODE 0x20 | ||
| 26 | #define R2B_MT9V011_GREEN_1_GAIN 0x2b | ||
| 27 | #define R2C_MT9V011_BLUE_GAIN 0x2c | ||
| 28 | #define R2D_MT9V011_RED_GAIN 0x2d | ||
| 29 | #define R2E_MT9V011_GREEN_2_GAIN 0x2e | ||
| 30 | #define R35_MT9V011_GLOBAL_GAIN 0x35 | ||
| 31 | #define RF1_MT9V011_CHIP_ENABLE 0xf1 | ||
| 32 | |||
| 33 | #define MT9V011_VERSION 0x8243 | ||
| 34 | |||
| 35 | #endif | ||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index db25c3034c11..8d17cf613306 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #include <linux/module.h> | 62 | #include <linux/module.h> |
| 63 | #include <linux/poll.h> | 63 | #include <linux/poll.h> |
| 64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
| 65 | #include <linux/smp_lock.h> | ||
| 65 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 66 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
| 66 | #include <linux/usb/input.h> | 67 | #include <linux/usb/input.h> |
| 67 | #endif | 68 | #endif |
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 0be6f814f539..0b658dee05a4 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/wait.h> | 31 | #include <linux/wait.h> |
| 32 | #include <linux/smp_lock.h> | ||
| 33 | #include <linux/version.h> | 32 | #include <linux/version.h> |
| 34 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 35 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 6be845ccc7d7..9e3262c0ba37 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/videodev2.h> | 48 | #include <linux/videodev2.h> |
| 49 | #include <linux/version.h> | 49 | #include <linux/version.h> |
| 50 | #include <linux/mm.h> | 50 | #include <linux/mm.h> |
| 51 | #include <linux/smp_lock.h> | ||
| 51 | #include <media/videobuf-vmalloc.h> | 52 | #include <media/videobuf-vmalloc.h> |
| 52 | #include <media/v4l2-common.h> | 53 | #include <media/v4l2-common.h> |
| 53 | #include <media/v4l2-ioctl.h> | 54 | #include <media/v4l2-ioctl.h> |
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 155804b061e9..b624a4c01fdc 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
| @@ -43,7 +43,6 @@ | |||
| 43 | #include <linux/mm.h> | 43 | #include <linux/mm.h> |
| 44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
| 45 | #include <linux/i2c.h> | 45 | #include <linux/i2c.h> |
| 46 | #include <linux/smp_lock.h> | ||
| 47 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
| 48 | #include <linux/videotext.h> | 47 | #include <linux/videotext.h> |
| 49 | #include <linux/videodev2.h> | 48 | #include <linux/videodev2.h> |
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 271d6e931b75..12835fb82c95 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
| 47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
| 48 | #include <linux/i2c.h> | 48 | #include <linux/i2c.h> |
| 49 | #include <linux/smp_lock.h> | ||
| 50 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
| 51 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
| 52 | #include <linux/videotext.h> | 51 | #include <linux/videotext.h> |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index add1757f8930..296788c3bf0e 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/smp_lock.h> | ||
| 25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 26 | 27 | ||
| 27 | #include "saa7134-reg.h" | 28 | #include "saa7134-reg.h" |
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index c8f05297d0f0..85ffc2cba039 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c | |||
| @@ -31,6 +31,7 @@ static const char version[] = "0.24"; | |||
| 31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/smp_lock.h> | ||
| 34 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
| 35 | #include <linux/usb.h> | 36 | #include <linux/usb.h> |
| 36 | #include "se401.h" | 37 | #include "se401.h" |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 16f595d4337a..9f5ae8167855 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
| @@ -237,11 +237,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
| 237 | return -ENOMEM; | 237 | return -ENOMEM; |
| 238 | 238 | ||
| 239 | icd->num_user_formats = fmts; | 239 | icd->num_user_formats = fmts; |
| 240 | fmts = 0; | ||
| 241 | 240 | ||
| 242 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); | 241 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); |
| 243 | 242 | ||
| 244 | /* Second pass - actually fill data formats */ | 243 | /* Second pass - actually fill data formats */ |
| 244 | fmts = 0; | ||
| 245 | for (i = 0; i < icd->num_formats; i++) | 245 | for (i = 0; i < icd->num_formats; i++) |
| 246 | if (!ici->ops->get_formats) { | 246 | if (!ici->ops->get_formats) { |
| 247 | icd->user_formats[i].host_fmt = icd->formats + i; | 247 | icd->user_formats[i].host_fmt = icd->formats + i; |
| @@ -877,8 +877,11 @@ static int soc_camera_probe(struct device *dev) | |||
| 877 | (unsigned short)~0; | 877 | (unsigned short)~0; |
| 878 | 878 | ||
| 879 | ret = soc_camera_init_user_formats(icd); | 879 | ret = soc_camera_init_user_formats(icd); |
| 880 | if (ret < 0) | 880 | if (ret < 0) { |
| 881 | if (icd->ops->remove) | ||
| 882 | icd->ops->remove(icd); | ||
| 881 | goto eiufmt; | 883 | goto eiufmt; |
| 884 | } | ||
| 882 | 885 | ||
| 883 | icd->height = DEFAULT_HEIGHT; | 886 | icd->height = DEFAULT_HEIGHT; |
| 884 | icd->width = DEFAULT_WIDTH; | 887 | icd->width = DEFAULT_WIDTH; |
| @@ -902,8 +905,10 @@ static int soc_camera_remove(struct device *dev) | |||
| 902 | { | 905 | { |
| 903 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 906 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
| 904 | 907 | ||
| 908 | mutex_lock(&icd->video_lock); | ||
| 905 | if (icd->ops->remove) | 909 | if (icd->ops->remove) |
| 906 | icd->ops->remove(icd); | 910 | icd->ops->remove(icd); |
| 911 | mutex_unlock(&icd->video_lock); | ||
| 907 | 912 | ||
| 908 | soc_camera_free_user_formats(icd); | 913 | soc_camera_free_user_formats(icd); |
| 909 | 914 | ||
| @@ -1145,6 +1150,7 @@ evidallocd: | |||
| 1145 | } | 1150 | } |
| 1146 | EXPORT_SYMBOL(soc_camera_video_start); | 1151 | EXPORT_SYMBOL(soc_camera_video_start); |
| 1147 | 1152 | ||
| 1153 | /* Called from client .remove() methods with .video_lock held */ | ||
| 1148 | void soc_camera_video_stop(struct soc_camera_device *icd) | 1154 | void soc_camera_video_stop(struct soc_camera_device *icd) |
| 1149 | { | 1155 | { |
| 1150 | struct video_device *vdev = icd->vdev; | 1156 | struct video_device *vdev = icd->vdev; |
| @@ -1154,10 +1160,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd) | |||
| 1154 | if (!icd->dev.parent || !vdev) | 1160 | if (!icd->dev.parent || !vdev) |
| 1155 | return; | 1161 | return; |
| 1156 | 1162 | ||
| 1157 | mutex_lock(&icd->video_lock); | ||
| 1158 | video_unregister_device(vdev); | 1163 | video_unregister_device(vdev); |
| 1159 | icd->vdev = NULL; | 1164 | icd->vdev = NULL; |
| 1160 | mutex_unlock(&icd->video_lock); | ||
| 1161 | } | 1165 | } |
| 1162 | EXPORT_SYMBOL(soc_camera_video_stop); | 1166 | EXPORT_SYMBOL(soc_camera_video_stop); |
| 1163 | 1167 | ||
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 2e5937047278..4d6785e63455 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/smp_lock.h> | ||
| 30 | 31 | ||
| 31 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
| 32 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 0eb313082c97..eaada39c76fd 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/major.h> | 27 | #include <linux/major.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
| 30 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 31 | #include <linux/poll.h> | 32 | #include <linux/poll.h> |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 75f286f7a2e9..8b4e7dafce7b 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #include <linux/init.h> | 62 | #include <linux/init.h> |
| 63 | #include <linux/vmalloc.h> | 63 | #include <linux/vmalloc.h> |
| 64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
| 65 | #include <linux/smp_lock.h> | ||
| 65 | #include <linux/pagemap.h> | 66 | #include <linux/pagemap.h> |
| 66 | #include <linux/errno.h> | 67 | #include <linux/errno.h> |
| 67 | #include <linux/videodev.h> | 68 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 8d73979596f9..45fce39ec9ad 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <linux/vmalloc.h> | 43 | #include <linux/vmalloc.h> |
| 44 | #include <linux/mm.h> | 44 | #include <linux/mm.h> |
| 45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
| 46 | #include <linux/smp_lock.h> | ||
| 46 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
| 47 | #include <linux/firmware.h> | 48 | #include <linux/firmware.h> |
| 48 | #include <linux/ihex.h> | 49 | #include <linux/ihex.h> |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 90b58914f984..90d9b5c0e9a7 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
| 51 | #include <linux/timer.h> | 51 | #include <linux/timer.h> |
| 52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 53 | #include <linux/smp_lock.h> | ||
| 53 | #include <linux/mm.h> | 54 | #include <linux/mm.h> |
| 54 | #include <linux/utsname.h> | 55 | #include <linux/utsname.h> |
| 55 | #include <linux/highmem.h> | 56 | #include <linux/highmem.h> |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 31eac66411d7..a7f1b69a7dab 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/kmod.h> | 26 | #include <linux/kmod.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/smp_lock.h> | ||
| 29 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 30 | #include <asm/system.h> | 29 | #include <asm/system.h> |
| 31 | 30 | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cd7266858462..7705fc6baf00 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
| @@ -343,6 +343,53 @@ static struct bar_std bars[] = { | |||
| 343 | #define TO_U(r, g, b) \ | 343 | #define TO_U(r, g, b) \ |
| 344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) | 344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) |
| 345 | 345 | ||
| 346 | /* precalculate color bar values to speed up rendering */ | ||
| 347 | static void precalculate_bars(struct vivi_fh *fh) | ||
| 348 | { | ||
| 349 | struct vivi_dev *dev = fh->dev; | ||
| 350 | unsigned char r, g, b; | ||
| 351 | int k, is_yuv; | ||
| 352 | |||
| 353 | fh->input = dev->input; | ||
| 354 | |||
| 355 | for (k = 0; k < 8; k++) { | ||
| 356 | r = bars[fh->input].bar[k][0]; | ||
| 357 | g = bars[fh->input].bar[k][1]; | ||
| 358 | b = bars[fh->input].bar[k][2]; | ||
| 359 | is_yuv = 0; | ||
| 360 | |||
| 361 | switch (fh->fmt->fourcc) { | ||
| 362 | case V4L2_PIX_FMT_YUYV: | ||
| 363 | case V4L2_PIX_FMT_UYVY: | ||
| 364 | is_yuv = 1; | ||
| 365 | break; | ||
| 366 | case V4L2_PIX_FMT_RGB565: | ||
| 367 | case V4L2_PIX_FMT_RGB565X: | ||
| 368 | r >>= 3; | ||
| 369 | g >>= 2; | ||
| 370 | b >>= 3; | ||
| 371 | break; | ||
| 372 | case V4L2_PIX_FMT_RGB555: | ||
| 373 | case V4L2_PIX_FMT_RGB555X: | ||
| 374 | r >>= 3; | ||
| 375 | g >>= 3; | ||
| 376 | b >>= 3; | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | |||
| 380 | if (is_yuv) { | ||
| 381 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | ||
| 382 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | ||
| 383 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | ||
| 384 | } else { | ||
| 385 | fh->bars[k][0] = r; | ||
| 386 | fh->bars[k][1] = g; | ||
| 387 | fh->bars[k][2] = b; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | } | ||
| 392 | |||
| 346 | #define TSTAMP_MIN_Y 24 | 393 | #define TSTAMP_MIN_Y 24 |
| 347 | #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) | 394 | #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) |
| 348 | #define TSTAMP_INPUT_X 10 | 395 | #define TSTAMP_INPUT_X 10 |
| @@ -755,6 +802,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
| 755 | buf->vb.height = fh->height; | 802 | buf->vb.height = fh->height; |
| 756 | buf->vb.field = field; | 803 | buf->vb.field = field; |
| 757 | 804 | ||
| 805 | precalculate_bars(fh); | ||
| 806 | |||
| 758 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 807 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
| 759 | rc = videobuf_iolock(vq, &buf->vb, NULL); | 808 | rc = videobuf_iolock(vq, &buf->vb, NULL); |
| 760 | if (rc < 0) | 809 | if (rc < 0) |
| @@ -893,53 +942,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 893 | return 0; | 942 | return 0; |
| 894 | } | 943 | } |
| 895 | 944 | ||
| 896 | /* precalculate color bar values to speed up rendering */ | ||
| 897 | static void precalculate_bars(struct vivi_fh *fh) | ||
| 898 | { | ||
| 899 | struct vivi_dev *dev = fh->dev; | ||
| 900 | unsigned char r, g, b; | ||
| 901 | int k, is_yuv; | ||
| 902 | |||
| 903 | fh->input = dev->input; | ||
| 904 | |||
| 905 | for (k = 0; k < 8; k++) { | ||
| 906 | r = bars[fh->input].bar[k][0]; | ||
| 907 | g = bars[fh->input].bar[k][1]; | ||
| 908 | b = bars[fh->input].bar[k][2]; | ||
| 909 | is_yuv = 0; | ||
| 910 | |||
| 911 | switch (fh->fmt->fourcc) { | ||
| 912 | case V4L2_PIX_FMT_YUYV: | ||
| 913 | case V4L2_PIX_FMT_UYVY: | ||
| 914 | is_yuv = 1; | ||
| 915 | break; | ||
| 916 | case V4L2_PIX_FMT_RGB565: | ||
| 917 | case V4L2_PIX_FMT_RGB565X: | ||
| 918 | r >>= 3; | ||
| 919 | g >>= 2; | ||
| 920 | b >>= 3; | ||
| 921 | break; | ||
| 922 | case V4L2_PIX_FMT_RGB555: | ||
| 923 | case V4L2_PIX_FMT_RGB555X: | ||
| 924 | r >>= 3; | ||
| 925 | g >>= 3; | ||
| 926 | b >>= 3; | ||
| 927 | break; | ||
| 928 | } | ||
| 929 | |||
| 930 | if (is_yuv) { | ||
| 931 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | ||
| 932 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | ||
| 933 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | ||
| 934 | } else { | ||
| 935 | fh->bars[k][0] = r; | ||
| 936 | fh->bars[k][1] = g; | ||
| 937 | fh->bars[k][2] = b; | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 941 | } | ||
| 942 | |||
| 943 | /*FIXME: This seems to be generic enough to be at videodev2 */ | 945 | /*FIXME: This seems to be generic enough to be at videodev2 */ |
| 944 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 946 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
| 945 | struct v4l2_format *f) | 947 | struct v4l2_format *f) |
| @@ -965,8 +967,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 965 | fh->vb_vidq.field = f->fmt.pix.field; | 967 | fh->vb_vidq.field = f->fmt.pix.field; |
| 966 | fh->type = f->type; | 968 | fh->type = f->type; |
| 967 | 969 | ||
| 968 | precalculate_bars(fh); | ||
| 969 | |||
| 970 | ret = 0; | 970 | ret = 0; |
| 971 | out: | 971 | out: |
| 972 | mutex_unlock(&q->vb_lock); | 972 | mutex_unlock(&q->vb_lock); |
| @@ -1357,6 +1357,7 @@ static int __init vivi_create_instance(int inst) | |||
| 1357 | goto unreg_dev; | 1357 | goto unreg_dev; |
| 1358 | 1358 | ||
| 1359 | *vfd = vivi_template; | 1359 | *vfd = vivi_template; |
| 1360 | vfd->debug = debug; | ||
| 1360 | 1361 | ||
| 1361 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); | 1362 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); |
| 1362 | if (ret < 0) | 1363 | if (ret < 0) |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 3d7df32a3d87..bcdefb1bcb3d 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <linux/module.h> | 49 | #include <linux/module.h> |
| 50 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
| 51 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
| 52 | #include <linux/smp_lock.h> | ||
| 52 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
| 53 | #include <linux/vmalloc.h> | 54 | #include <linux/vmalloc.h> |
| 54 | #include <linux/wait.h> | 55 | #include <linux/wait.h> |
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 7ac12cb0be4a..5b6e58a3ba46 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c | |||
| @@ -32,8 +32,7 @@ | |||
| 32 | * This driver was tested with firmware revision A4. | 32 | * This driver was tested with firmware revision A4. |
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #if defined(CONFIG_KEYBOARD_DM355EVM) \ | 35 | #if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE) |
| 36 | || defined(CONFIG_KEYBOARD_DM355EVM_MODULE) | ||
| 37 | #define msp_has_keyboard() true | 36 | #define msp_has_keyboard() true |
| 38 | #else | 37 | #else |
| 39 | #define msp_has_keyboard() false | 38 | #define msp_has_keyboard() false |
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 671a7efe86a8..c1de4afa89a6 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c | |||
| @@ -238,8 +238,10 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap) | |||
| 238 | mutex_lock(&pcap->adc_mutex); | 238 | mutex_lock(&pcap->adc_mutex); |
| 239 | req = pcap->adc_queue[pcap->adc_head]; | 239 | req = pcap->adc_queue[pcap->adc_head]; |
| 240 | 240 | ||
| 241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) | 241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) { |
| 242 | mutex_unlock(&pcap->adc_mutex); | ||
| 242 | return IRQ_HANDLED; | 243 | return IRQ_HANDLED; |
| 244 | } | ||
| 243 | 245 | ||
| 244 | /* read requested channels results */ | 246 | /* read requested channels results */ |
| 245 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); | 247 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 4c7b7962f6b8..0cc5eeff5ee8 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
| @@ -367,7 +367,8 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) | |||
| 367 | break; | 367 | break; |
| 368 | 368 | ||
| 369 | default: | 369 | default: |
| 370 | return -1; | 370 | gate = -1; |
| 371 | goto already; | ||
| 371 | } | 372 | } |
| 372 | 373 | ||
| 373 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); | 374 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); |
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index fa2d93a9fb8d..aed609832bc2 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | #include <linux/smp_lock.h> | ||
| 33 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
| 34 | #include <linux/device.h> | 33 | #include <linux/device.h> |
| 35 | #include <linux/miscdevice.h> | 34 | #include <linux/miscdevice.h> |
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index eedbf9c32760..79689b10f937 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
| 27 | #include <linux/smp_lock.h> | ||
| 28 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
| 29 | #include <linux/device.h> | 28 | #include <linux/device.h> |
| 30 | #include <linux/miscdevice.h> | 29 | #include <linux/miscdevice.h> |
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 8d1c60a3f0df..5d778ec8cdb2 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c | |||
| @@ -235,7 +235,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg) | |||
| 235 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 235 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 236 | 236 | ||
| 237 | dev_dbg(xpnet, "passing skb to network layer\n" | 237 | dev_dbg(xpnet, "passing skb to network layer\n" |
| 238 | KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " | 238 | "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " |
| 239 | "skb->end=0x%p skb->len=%d\n", | 239 | "skb->end=0x%p skb->len=%d\n", |
| 240 | (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), | 240 | (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), |
| 241 | skb_end_pointer(skb), skb->len); | 241 | skb_end_pointer(skb), skb->len); |
| @@ -399,7 +399,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg, | |||
| 399 | msg->buf_pa = xp_pa((void *)start_addr); | 399 | msg->buf_pa = xp_pa((void *)start_addr); |
| 400 | 400 | ||
| 401 | dev_dbg(xpnet, "sending XPC message to %d:%d\n" | 401 | dev_dbg(xpnet, "sending XPC message to %d:%d\n" |
| 402 | KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, " | 402 | "msg->buf_pa=0x%lx, msg->size=%u, " |
| 403 | "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n", | 403 | "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n", |
| 404 | dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size, | 404 | dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size, |
| 405 | msg->leadin_ignore, msg->tailout_ignore); | 405 | msg->leadin_ignore, msg->tailout_ignore); |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 240608cc7ae9..a461017ce5ce 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
| @@ -1313,6 +1313,12 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
| 1313 | struct mmc_spi_host *host; | 1313 | struct mmc_spi_host *host; |
| 1314 | int status; | 1314 | int status; |
| 1315 | 1315 | ||
| 1316 | /* We rely on full duplex transfers, mostly to reduce | ||
| 1317 | * per-transfer overheads (by making fewer transfers). | ||
| 1318 | */ | ||
| 1319 | if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) | ||
| 1320 | return -EINVAL; | ||
| 1321 | |||
| 1316 | /* MMC and SD specs only seem to care that sampling is on the | 1322 | /* MMC and SD specs only seem to care that sampling is on the |
| 1317 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode | 1323 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode |
| 1318 | * should be legit. We'll use mode 0 since the steady state is 0, | 1324 | * should be legit. We'll use mode 0 since the steady state is 0, |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 5011fa73f918..1479da6d3aa6 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
| @@ -194,7 +194,7 @@ static struct mtd_partition * newpart(char *s, | |||
| 194 | parts[this_part].name = extra_mem; | 194 | parts[this_part].name = extra_mem; |
| 195 | extra_mem += name_len + 1; | 195 | extra_mem += name_len + 1; |
| 196 | 196 | ||
| 197 | dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n", | 197 | dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n", |
| 198 | this_part, | 198 | this_part, |
| 199 | parts[this_part].name, | 199 | parts[this_part].name, |
| 200 | parts[this_part].offset, | 200 | parts[this_part].offset, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 59c46126a5ce..ae5fe91867e1 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | #define SR_SRWD 0x80 /* SR write protect */ | 54 | #define SR_SRWD 0x80 /* SR write protect */ |
| 55 | 55 | ||
| 56 | /* Define max times to check status register before we give up. */ | 56 | /* Define max times to check status register before we give up. */ |
| 57 | #define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */ | 57 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
| 58 | #define CMD_SIZE 4 | 58 | #define CMD_SIZE 4 |
| 59 | 59 | ||
| 60 | #ifdef CONFIG_M25PXX_USE_FAST_READ | 60 | #ifdef CONFIG_M25PXX_USE_FAST_READ |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 73f05227dc8c..d8cf29c01cc4 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
| @@ -226,7 +226,7 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) | |||
| 226 | if (!desperate && inftl->numfreeEUNs < 2) { | 226 | if (!desperate && inftl->numfreeEUNs < 2) { |
| 227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " | 227 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " |
| 228 | "EUNs (%d)\n", inftl->numfreeEUNs); | 228 | "EUNs (%d)\n", inftl->numfreeEUNs); |
| 229 | return 0xffff; | 229 | return BLOCK_NIL; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | /* Scan for a free block */ | 232 | /* Scan for a free block */ |
| @@ -281,7 +281,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
| 281 | silly = MAX_LOOPS; | 281 | silly = MAX_LOOPS; |
| 282 | while (thisEUN < inftl->nb_blocks) { | 282 | while (thisEUN < inftl->nb_blocks) { |
| 283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { | 283 | for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { |
| 284 | if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) | 284 | if ((BlockMap[block] != BLOCK_NIL) || |
| 285 | BlockDeleted[block]) | ||
| 285 | continue; | 286 | continue; |
| 286 | 287 | ||
| 287 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) | 288 | if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) |
| @@ -525,7 +526,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) | |||
| 525 | if (!silly--) { | 526 | if (!silly--) { |
| 526 | printk(KERN_WARNING "INFTL: infinite loop in " | 527 | printk(KERN_WARNING "INFTL: infinite loop in " |
| 527 | "Virtual Unit Chain 0x%x\n", thisVUC); | 528 | "Virtual Unit Chain 0x%x\n", thisVUC); |
| 528 | return 0xffff; | 529 | return BLOCK_NIL; |
| 529 | } | 530 | } |
| 530 | 531 | ||
| 531 | /* Skip to next block in chain */ | 532 | /* Skip to next block in chain */ |
| @@ -549,7 +550,7 @@ hitused: | |||
| 549 | * waiting to be picked up. We're going to have to fold | 550 | * waiting to be picked up. We're going to have to fold |
| 550 | * a chain to make room. | 551 | * a chain to make room. |
| 551 | */ | 552 | */ |
| 552 | thisEUN = INFTL_makefreeblock(inftl, 0xffff); | 553 | thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL); |
| 553 | 554 | ||
| 554 | /* | 555 | /* |
| 555 | * Hopefully we free something, lets try again. | 556 | * Hopefully we free something, lets try again. |
| @@ -631,7 +632,7 @@ hitused: | |||
| 631 | 632 | ||
| 632 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " | 633 | printk(KERN_WARNING "INFTL: error folding to make room for Virtual " |
| 633 | "Unit Chain 0x%x\n", thisVUC); | 634 | "Unit Chain 0x%x\n", thisVUC); |
| 634 | return 0xffff; | 635 | return BLOCK_NIL; |
| 635 | } | 636 | } |
| 636 | 637 | ||
| 637 | /* | 638 | /* |
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index b08a798ee254..2aac41bde8b3 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c | |||
| @@ -42,10 +42,8 @@ | |||
| 42 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
| 43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
| 44 | 44 | ||
| 45 | #define SUBDEV_NAME_SIZE (BUS_ID_SIZE + 2) | ||
| 46 | |||
| 47 | struct armflash_subdev_info { | 45 | struct armflash_subdev_info { |
| 48 | char name[SUBDEV_NAME_SIZE]; | 46 | char *name; |
| 49 | struct mtd_info *mtd; | 47 | struct mtd_info *mtd; |
| 50 | struct map_info map; | 48 | struct map_info map; |
| 51 | struct flash_platform_data *plat; | 49 | struct flash_platform_data *plat; |
| @@ -134,6 +132,8 @@ static void armflash_subdev_remove(struct armflash_subdev_info *subdev) | |||
| 134 | map_destroy(subdev->mtd); | 132 | map_destroy(subdev->mtd); |
| 135 | if (subdev->map.virt) | 133 | if (subdev->map.virt) |
| 136 | iounmap(subdev->map.virt); | 134 | iounmap(subdev->map.virt); |
| 135 | kfree(subdev->name); | ||
| 136 | subdev->name = NULL; | ||
| 137 | release_mem_region(subdev->map.phys, subdev->map.size); | 137 | release_mem_region(subdev->map.phys, subdev->map.size); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| @@ -177,16 +177,22 @@ static int armflash_probe(struct platform_device *dev) | |||
| 177 | 177 | ||
| 178 | if (nr == 1) | 178 | if (nr == 1) |
| 179 | /* No MTD concatenation, just use the default name */ | 179 | /* No MTD concatenation, just use the default name */ |
| 180 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s", | 180 | subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL); |
| 181 | dev_name(&dev->dev)); | ||
| 182 | else | 181 | else |
| 183 | snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d", | 182 | subdev->name = kasprintf(GFP_KERNEL, "%s-%d", |
| 184 | dev_name(&dev->dev), i); | 183 | dev_name(&dev->dev), i); |
| 184 | if (!subdev->name) { | ||
| 185 | err = -ENOMEM; | ||
| 186 | break; | ||
| 187 | } | ||
| 185 | subdev->plat = plat; | 188 | subdev->plat = plat; |
| 186 | 189 | ||
| 187 | err = armflash_subdev_probe(subdev, res); | 190 | err = armflash_subdev_probe(subdev, res); |
| 188 | if (err) | 191 | if (err) { |
| 192 | kfree(subdev->name); | ||
| 193 | subdev->name = NULL; | ||
| 189 | break; | 194 | break; |
| 195 | } | ||
| 190 | } | 196 | } |
| 191 | info->nr_subdev = i; | 197 | info->nr_subdev = i; |
| 192 | 198 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2802992b39da..20c828ba9405 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
| @@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
| 534 | &num_partitions); | 534 | &num_partitions); |
| 535 | 535 | ||
| 536 | if ((!partitions) || (num_partitions == 0)) { | 536 | if ((!partitions) || (num_partitions == 0)) { |
| 537 | printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); | 537 | printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n"); |
| 538 | res = ENXIO; | 538 | res = ENXIO; |
| 539 | goto err_no_partitions; | 539 | goto err_no_partitions; |
| 540 | } | 540 | } |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0cd76f89f4b0..ebd07e95b814 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
| 12 | #include <linux/dma-mapping.h> | 12 | #include <linux/dma-mapping.h> |
| 13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 14 | #include <linux/jiffies.h> | ||
| 15 | #include <linux/sched.h> | ||
| 14 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
| 15 | #include <linux/mtd/nand.h> | 17 | #include <linux/mtd/nand.h> |
| 16 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
| @@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
| 541 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 543 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
| 542 | mtd); | 544 | mtd); |
| 543 | unsigned long timeo = jiffies; | 545 | unsigned long timeo = jiffies; |
| 544 | int status, state = this->state; | 546 | int status = NAND_STATUS_FAIL, state = this->state; |
| 545 | 547 | ||
| 546 | if (state == FL_ERASING) | 548 | if (state == FL_ERASING) |
| 547 | timeo += (HZ * 400) / 1000; | 549 | timeo += (HZ * 400) / 1000; |
| @@ -556,8 +558,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
| 556 | 558 | ||
| 557 | while (time_before(jiffies, timeo)) { | 559 | while (time_before(jiffies, timeo)) { |
| 558 | status = __raw_readb(this->IO_ADDR_R); | 560 | status = __raw_readb(this->IO_ADDR_R); |
| 559 | if (!(status & 0x40)) | 561 | if (status & NAND_STATUS_READY) |
| 560 | break; | 562 | break; |
| 563 | cond_resched(); | ||
| 561 | } | 564 | } |
| 562 | return status; | 565 | return status; |
| 563 | } | 566 | } |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e3f8495a94c2..fb86cacd5bdb 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
| @@ -208,7 +208,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
| 208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ | 208 | /* Normally, we force a fold to happen before we run out of free blocks completely */ |
| 209 | if (!desperate && nftl->numfreeEUNs < 2) { | 209 | if (!desperate && nftl->numfreeEUNs < 2) { |
| 210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); | 210 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); |
| 211 | return 0xffff; | 211 | return BLOCK_NIL; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | /* Scan for a free block */ | 214 | /* Scan for a free block */ |
| @@ -230,11 +230,11 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
| 230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " | 230 | printk("Argh! No free blocks found! LastFreeEUN = %d, " |
| 231 | "FirstEUN = %d\n", nftl->LastFreeEUN, | 231 | "FirstEUN = %d\n", nftl->LastFreeEUN, |
| 232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); | 232 | le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); |
| 233 | return 0xffff; | 233 | return BLOCK_NIL; |
| 234 | } | 234 | } |
| 235 | } while (pot != nftl->LastFreeEUN); | 235 | } while (pot != nftl->LastFreeEUN); |
| 236 | 236 | ||
| 237 | return 0xffff; | 237 | return BLOCK_NIL; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) | 240 | static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) |
| @@ -431,7 +431,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
| 431 | 431 | ||
| 432 | /* add the header so that it is now a valid chain */ | 432 | /* add the header so that it is now a valid chain */ |
| 433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); | 433 | oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); |
| 434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; | 434 | oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL; |
| 435 | 435 | ||
| 436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, | 436 | nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, |
| 437 | 8, &retlen, (char *)&oob.u); | 437 | 8, &retlen, (char *)&oob.u); |
| @@ -515,7 +515,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) | |||
| 515 | if (ChainLength < 2) { | 515 | if (ChainLength < 2) { |
| 516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " | 516 | printk(KERN_WARNING "No Virtual Unit Chains available for folding. " |
| 517 | "Failing request\n"); | 517 | "Failing request\n"); |
| 518 | return 0xffff; | 518 | return BLOCK_NIL; |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); | 521 | return NFTL_foldchain (nftl, LongestChain, pendingblock); |
| @@ -578,7 +578,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
| 578 | printk(KERN_WARNING | 578 | printk(KERN_WARNING |
| 579 | "Infinite loop in Virtual Unit Chain 0x%x\n", | 579 | "Infinite loop in Virtual Unit Chain 0x%x\n", |
| 580 | thisVUC); | 580 | thisVUC); |
| 581 | return 0xffff; | 581 | return BLOCK_NIL; |
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | /* Skip to next block in chain */ | 584 | /* Skip to next block in chain */ |
| @@ -601,7 +601,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
| 601 | //u16 startEUN = nftl->EUNtable[thisVUC]; | 601 | //u16 startEUN = nftl->EUNtable[thisVUC]; |
| 602 | 602 | ||
| 603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); | 603 | //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); |
| 604 | writeEUN = NFTL_makefreeblock(nftl, 0xffff); | 604 | writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL); |
| 605 | 605 | ||
| 606 | if (writeEUN == BLOCK_NIL) { | 606 | if (writeEUN == BLOCK_NIL) { |
| 607 | /* OK, we accept that the above comment is | 607 | /* OK, we accept that the above comment is |
| @@ -673,7 +673,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
| 673 | 673 | ||
| 674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", | 674 | printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", |
| 675 | thisVUC); | 675 | thisVUC); |
| 676 | return 0xffff; | 676 | return BLOCK_NIL; |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, | 679 | static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 286ed594e5a0..e1f7d0a78b9d 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi) | |||
| 657 | if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) | 657 | if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) |
| 658 | ubi->bad_allowed = 1; | 658 | ubi->bad_allowed = 1; |
| 659 | 659 | ||
| 660 | if (ubi->mtd->type == MTD_NORFLASH) { | ||
| 661 | ubi_assert(ubi->mtd->writesize == 1); | ||
| 662 | ubi->nor_flash = 1; | ||
| 663 | } | ||
| 664 | |||
| 660 | ubi->min_io_size = ubi->mtd->writesize; | 665 | ubi->min_io_size = ubi->mtd->writesize; |
| 661 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; | 666 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; |
| 662 | 667 | ||
| @@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 996 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", | 1001 | ubi_msg("number of PEBs reserved for bad PEB handling: %d", |
| 997 | ubi->beb_rsvd_pebs); | 1002 | ubi->beb_rsvd_pebs); |
| 998 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); | 1003 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); |
| 1004 | ubi_msg("image sequence number: %d", ubi->image_seq); | ||
| 999 | 1005 | ||
| 1000 | /* | 1006 | /* |
| 1001 | * The below lock makes sure we do not race with 'ubi_thread()' which | 1007 | * The below lock makes sure we do not race with 'ubi_thread()' which |
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c0ed60e8ade9..54b0186915fb 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
| @@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) | |||
| 44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); | 44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); |
| 45 | printk(KERN_DEBUG "\tdata_offset %d\n", | 45 | printk(KERN_DEBUG "\tdata_offset %d\n", |
| 46 | be32_to_cpu(ec_hdr->data_offset)); | 46 | be32_to_cpu(ec_hdr->data_offset)); |
| 47 | printk(KERN_DEBUG "\timage_seq %d\n", | ||
| 48 | be32_to_cpu(ec_hdr->image_seq)); | ||
| 47 | printk(KERN_DEBUG "\thdr_crc %#08x\n", | 49 | printk(KERN_DEBUG "\thdr_crc %#08x\n", |
| 48 | be32_to_cpu(ec_hdr->hdr_crc)); | 50 | be32_to_cpu(ec_hdr->hdr_crc)); |
| 49 | printk(KERN_DEBUG "erase counter header hexdump:\n"); | 51 | printk(KERN_DEBUG "erase counter header hexdump:\n"); |
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 13777e5beac9..a4da7a09b949 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | |||
| 93 | #define UBI_IO_DEBUG 0 | 93 | #define UBI_IO_DEBUG 0 |
| 94 | #endif | 94 | #endif |
| 95 | 95 | ||
| 96 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | ||
| 97 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); | ||
| 98 | #else | ||
| 99 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | ||
| 100 | #endif | ||
| 101 | |||
| 96 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 102 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT |
| 97 | #define DBG_DISABLE_BGT 1 | 103 | #define DBG_DISABLE_BGT 1 |
| 98 | #else | 104 | #else |
| @@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void) | |||
| 167 | #define ubi_dbg_is_bitflip() 0 | 173 | #define ubi_dbg_is_bitflip() 0 |
| 168 | #define ubi_dbg_is_write_failure() 0 | 174 | #define ubi_dbg_is_write_failure() 0 |
| 169 | #define ubi_dbg_is_erase_failure() 0 | 175 | #define ubi_dbg_is_erase_failure() 0 |
| 176 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | ||
| 170 | 177 | ||
| 171 | #endif /* !CONFIG_MTD_UBI_DEBUG */ | 178 | #endif /* !CONFIG_MTD_UBI_DEBUG */ |
| 172 | #endif /* !__UBI_DEBUG_H__ */ | 179 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index effaff28bab1..4cb69925d8d9 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
| 98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); | 98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); |
| 99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, | 99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, |
| 100 | const struct ubi_vid_hdr *vid_hdr); | 100 | const struct ubi_vid_hdr *vid_hdr); |
| 101 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | ||
| 102 | int len); | ||
| 103 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum); | ||
| 104 | #else | 101 | #else |
| 105 | #define paranoid_check_not_bad(ubi, pnum) 0 | 102 | #define paranoid_check_not_bad(ubi, pnum) 0 |
| 106 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 | 103 | #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 |
| 107 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 | 104 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 |
| 108 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 | 105 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 |
| 109 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 | 106 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 |
| 110 | #define paranoid_check_all_ff(ubi, pnum, offset, len) 0 | ||
| 111 | #define paranoid_check_empty(ubi, pnum) 0 | ||
| 112 | #endif | 107 | #endif |
| 113 | 108 | ||
| 114 | /** | 109 | /** |
| @@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 244 | return err > 0 ? -EINVAL : err; | 239 | return err > 0 ? -EINVAL : err; |
| 245 | 240 | ||
| 246 | /* The area we are writing to has to contain all 0xFF bytes */ | 241 | /* The area we are writing to has to contain all 0xFF bytes */ |
| 247 | err = paranoid_check_all_ff(ubi, pnum, offset, len); | 242 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); |
| 248 | if (err) | 243 | if (err) |
| 249 | return err > 0 ? -EINVAL : err; | 244 | return err > 0 ? -EINVAL : err; |
| 250 | 245 | ||
| @@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 271 | addr = (loff_t)pnum * ubi->peb_size + offset; | 266 | addr = (loff_t)pnum * ubi->peb_size + offset; |
| 272 | err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); | 267 | err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); |
| 273 | if (err) { | 268 | if (err) { |
| 274 | ubi_err("error %d while writing %d bytes to PEB %d:%d, written" | 269 | ubi_err("error %d while writing %d bytes to PEB %d:%d, written " |
| 275 | " %zd bytes", err, len, pnum, offset, written); | 270 | "%zd bytes", err, len, pnum, offset, written); |
| 276 | ubi_dbg_dump_stack(); | 271 | ubi_dbg_dump_stack(); |
| 277 | } else | 272 | } else |
| 278 | ubi_assert(written == len); | 273 | ubi_assert(written == len); |
| @@ -350,7 +345,7 @@ retry: | |||
| 350 | return -EIO; | 345 | return -EIO; |
| 351 | } | 346 | } |
| 352 | 347 | ||
| 353 | err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size); | 348 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); |
| 354 | if (err) | 349 | if (err) |
| 355 | return err > 0 ? -EINVAL : err; | 350 | return err > 0 ? -EINVAL : err; |
| 356 | 351 | ||
| @@ -459,6 +454,54 @@ out: | |||
| 459 | } | 454 | } |
| 460 | 455 | ||
| 461 | /** | 456 | /** |
| 457 | * nor_erase_prepare - prepare a NOR flash PEB for erasure. | ||
| 458 | * @ubi: UBI device description object | ||
| 459 | * @pnum: physical eraseblock number to prepare | ||
| 460 | * | ||
| 461 | * NOR flash, or at least some of them, have peculiar embedded PEB erasure | ||
| 462 | * algorithm: the PEB is first filled with zeroes, then it is erased. And | ||
| 463 | * filling with zeroes starts from the end of the PEB. This was observed with | ||
| 464 | * Spansion S29GL512N NOR flash. | ||
| 465 | * | ||
| 466 | * This means that in case of a power cut we may end up with intact data at the | ||
| 467 | * beginning of the PEB, and all zeroes at the end of PEB. In other words, the | ||
| 468 | * EC and VID headers are OK, but a large chunk of data at the end of PEB is | ||
| 469 | * zeroed. This makes UBI mistakenly treat this PEB as used and associate it | ||
| 470 | * with an LEB, which leads to subsequent failures (e.g., UBIFS fails). | ||
| 471 | * | ||
| 472 | * This function is called before erasing NOR PEBs and it zeroes out EC and VID | ||
| 473 | * magic numbers in order to invalidate them and prevent the failures. Returns | ||
| 474 | * zero in case of success and a negative error code in case of failure. | ||
| 475 | */ | ||
| 476 | static int nor_erase_prepare(struct ubi_device *ubi, int pnum) | ||
| 477 | { | ||
| 478 | int err; | ||
| 479 | size_t written; | ||
| 480 | loff_t addr; | ||
| 481 | uint32_t data = 0; | ||
| 482 | |||
| 483 | addr = (loff_t)pnum * ubi->peb_size; | ||
| 484 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); | ||
| 485 | if (err) { | ||
| 486 | ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " | ||
| 487 | "%zd bytes", err, pnum, 0, written); | ||
| 488 | ubi_dbg_dump_stack(); | ||
| 489 | return err; | ||
| 490 | } | ||
| 491 | |||
| 492 | addr += ubi->vid_hdr_aloffset; | ||
| 493 | err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); | ||
| 494 | if (err) { | ||
| 495 | ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " | ||
| 496 | "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); | ||
| 497 | ubi_dbg_dump_stack(); | ||
| 498 | return err; | ||
| 499 | } | ||
| 500 | |||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | /** | ||
| 462 | * ubi_io_sync_erase - synchronously erase a physical eraseblock. | 505 | * ubi_io_sync_erase - synchronously erase a physical eraseblock. |
| 463 | * @ubi: UBI device description object | 506 | * @ubi: UBI device description object |
| 464 | * @pnum: physical eraseblock number to erase | 507 | * @pnum: physical eraseblock number to erase |
| @@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) | |||
| 489 | return -EROFS; | 532 | return -EROFS; |
| 490 | } | 533 | } |
| 491 | 534 | ||
| 535 | if (ubi->nor_flash) { | ||
| 536 | err = nor_erase_prepare(ubi, pnum); | ||
| 537 | if (err) | ||
| 538 | return err; | ||
| 539 | } | ||
| 540 | |||
| 492 | if (torture) { | 541 | if (torture) { |
| 493 | ret = torture_peb(ubi, pnum); | 542 | ret = torture_peb(ubi, pnum); |
| 494 | if (ret < 0) | 543 | if (ret < 0) |
| @@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
| 672 | if (read_err != -EBADMSG && | 721 | if (read_err != -EBADMSG && |
| 673 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { | 722 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { |
| 674 | /* The physical eraseblock is supposedly empty */ | 723 | /* The physical eraseblock is supposedly empty */ |
| 675 | err = paranoid_check_all_ff(ubi, pnum, 0, | ||
| 676 | ubi->peb_size); | ||
| 677 | if (err) | ||
| 678 | return err > 0 ? UBI_IO_BAD_EC_HDR : err; | ||
| 679 | |||
| 680 | if (verbose) | 724 | if (verbose) |
| 681 | ubi_warn("no EC header found at PEB %d, " | 725 | ubi_warn("no EC header found at PEB %d, " |
| 682 | "only 0xFF bytes", pnum); | 726 | "only 0xFF bytes", pnum); |
| @@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, | |||
| 752 | ec_hdr->version = UBI_VERSION; | 796 | ec_hdr->version = UBI_VERSION; |
| 753 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); | 797 | ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); |
| 754 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); | 798 | ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); |
| 799 | ec_hdr->image_seq = cpu_to_be32(ubi->image_seq); | ||
| 755 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); | 800 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); |
| 756 | ec_hdr->hdr_crc = cpu_to_be32(crc); | 801 | ec_hdr->hdr_crc = cpu_to_be32(crc); |
| 757 | 802 | ||
| @@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, | |||
| 947 | if (read_err != -EBADMSG && | 992 | if (read_err != -EBADMSG && |
| 948 | check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { | 993 | check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { |
| 949 | /* The physical eraseblock is supposedly free */ | 994 | /* The physical eraseblock is supposedly free */ |
| 950 | |||
| 951 | /* | ||
| 952 | * The below is just a paranoid check, it has to be | ||
| 953 | * compiled out if paranoid checks are disabled. | ||
| 954 | */ | ||
| 955 | err = paranoid_check_empty(ubi, pnum); | ||
| 956 | if (err) | ||
| 957 | return err > 0 ? UBI_IO_BAD_VID_HDR : err; | ||
| 958 | |||
| 959 | if (verbose) | 995 | if (verbose) |
| 960 | ubi_warn("no VID header found at PEB %d, " | 996 | ubi_warn("no VID header found at PEB %d, " |
| 961 | "only 0xFF bytes", pnum); | 997 | "only 0xFF bytes", pnum); |
| @@ -1229,7 +1265,7 @@ exit: | |||
| 1229 | } | 1265 | } |
| 1230 | 1266 | ||
| 1231 | /** | 1267 | /** |
| 1232 | * paranoid_check_all_ff - check that a region of flash is empty. | 1268 | * ubi_dbg_check_all_ff - check that a region of flash is empty. |
| 1233 | * @ubi: UBI device description object | 1269 | * @ubi: UBI device description object |
| 1234 | * @pnum: the physical eraseblock number to check | 1270 | * @pnum: the physical eraseblock number to check |
| 1235 | * @offset: the starting offset within the physical eraseblock to check | 1271 | * @offset: the starting offset within the physical eraseblock to check |
| @@ -1239,8 +1275,7 @@ exit: | |||
| 1239 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error | 1275 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error |
| 1240 | * code if an error occurred. | 1276 | * code if an error occurred. |
| 1241 | */ | 1277 | */ |
| 1242 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | 1278 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) |
| 1243 | int len) | ||
| 1244 | { | 1279 | { |
| 1245 | size_t read; | 1280 | size_t read; |
| 1246 | int err; | 1281 | int err; |
| @@ -1276,74 +1311,4 @@ error: | |||
| 1276 | return err; | 1311 | return err; |
| 1277 | } | 1312 | } |
| 1278 | 1313 | ||
| 1279 | /** | ||
| 1280 | * paranoid_check_empty - whether a PEB is empty. | ||
| 1281 | * @ubi: UBI device description object | ||
| 1282 | * @pnum: the physical eraseblock number to check | ||
| 1283 | * | ||
| 1284 | * This function makes sure PEB @pnum is empty, which means it contains only | ||
| 1285 | * %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a | ||
| 1286 | * negative error code in case of failure. | ||
| 1287 | * | ||
| 1288 | * Empty PEBs have the EC header, and do not have the VID header. The caller of | ||
| 1289 | * this function should have already made sure the PEB does not have the VID | ||
| 1290 | * header. However, this function re-checks that, because it is possible that | ||
| 1291 | * the header and data has already been written to the PEB. | ||
| 1292 | * | ||
| 1293 | * Let's consider a possible scenario. Suppose there are 2 tasks - A and B. | ||
| 1294 | * Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to | ||
| 1295 | * find which LEB it corresponds to. PEB X is currently unmapped, and has no | ||
| 1296 | * VID header. Task B is trying to write to PEB X. | ||
| 1297 | * | ||
| 1298 | * Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The | ||
| 1299 | * read data contain all 0xFF bytes; | ||
| 1300 | * Task B: writes VID header and some data to PEB X; | ||
| 1301 | * Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we | ||
| 1302 | * do not re-read the VID header, and do not cancel the checking if it | ||
| 1303 | * is there, we fail. | ||
| 1304 | */ | ||
| 1305 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum) | ||
| 1306 | { | ||
| 1307 | int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize; | ||
| 1308 | size_t read; | ||
| 1309 | uint32_t magic; | ||
| 1310 | const struct ubi_vid_hdr *vid_hdr; | ||
| 1311 | |||
| 1312 | mutex_lock(&ubi->dbg_buf_mutex); | ||
| 1313 | err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf); | ||
| 1314 | if (err && err != -EUCLEAN) { | ||
| 1315 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " | ||
| 1316 | "read %zd bytes", err, len, pnum, offs, read); | ||
| 1317 | goto error; | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | vid_hdr = ubi->dbg_peb_buf; | ||
| 1321 | magic = be32_to_cpu(vid_hdr->magic); | ||
| 1322 | if (magic == UBI_VID_HDR_MAGIC) | ||
| 1323 | /* The PEB contains VID header, so it is not empty */ | ||
| 1324 | goto out; | ||
| 1325 | |||
| 1326 | err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); | ||
| 1327 | if (err == 0) { | ||
| 1328 | ubi_err("flash region at PEB %d:%d, length %d does not " | ||
| 1329 | "contain all 0xFF bytes", pnum, offs, len); | ||
| 1330 | goto fail; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | out: | ||
| 1334 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1335 | return 0; | ||
| 1336 | |||
| 1337 | fail: | ||
| 1338 | ubi_err("paranoid check failed for PEB %d", pnum); | ||
| 1339 | ubi_msg("hex dump of the %d-%d region", offs, offs + len); | ||
| 1340 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 1341 | ubi->dbg_peb_buf, len, 1); | ||
| 1342 | err = 1; | ||
| 1343 | error: | ||
| 1344 | ubi_dbg_dump_stack(); | ||
| 1345 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1346 | return err; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ | 1314 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c3d653ba5ca0..f60895ee0aeb 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 757 | si->is_empty = 0; | 757 | si->is_empty = 0; |
| 758 | 758 | ||
| 759 | if (!ec_corr) { | 759 | if (!ec_corr) { |
| 760 | int image_seq; | ||
| 761 | |||
| 760 | /* Make sure UBI version is OK */ | 762 | /* Make sure UBI version is OK */ |
| 761 | if (ech->version != UBI_VERSION) { | 763 | if (ech->version != UBI_VERSION) { |
| 762 | ubi_err("this UBI version is %d, image version is %d", | 764 | ubi_err("this UBI version is %d, image version is %d", |
| @@ -778,6 +780,18 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 778 | ubi_dbg_dump_ec_hdr(ech); | 780 | ubi_dbg_dump_ec_hdr(ech); |
| 779 | return -EINVAL; | 781 | return -EINVAL; |
| 780 | } | 782 | } |
| 783 | |||
| 784 | image_seq = be32_to_cpu(ech->ec); | ||
| 785 | if (!si->image_seq_set) { | ||
| 786 | ubi->image_seq = image_seq; | ||
| 787 | si->image_seq_set = 1; | ||
| 788 | } else if (ubi->image_seq != image_seq) { | ||
| 789 | ubi_err("bad image sequence number %d in PEB %d, " | ||
| 790 | "expected %d", image_seq, pnum, ubi->image_seq); | ||
| 791 | ubi_dbg_dump_ec_hdr(ech); | ||
| 792 | return -EINVAL; | ||
| 793 | } | ||
| 794 | |||
| 781 | } | 795 | } |
| 782 | 796 | ||
| 783 | /* OK, we've done with the EC header, let's look at the VID header */ | 797 | /* OK, we've done with the EC header, let's look at the VID header */ |
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 61df208e2f20..1017cf12def5 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h | |||
| @@ -102,6 +102,7 @@ struct ubi_scan_volume { | |||
| 102 | * @mean_ec: mean erase counter value | 102 | * @mean_ec: mean erase counter value |
| 103 | * @ec_sum: a temporary variable used when calculating @mean_ec | 103 | * @ec_sum: a temporary variable used when calculating @mean_ec |
| 104 | * @ec_count: a temporary variable used when calculating @mean_ec | 104 | * @ec_count: a temporary variable used when calculating @mean_ec |
| 105 | * @image_seq_set: indicates @ubi->image_seq is known | ||
| 105 | * | 106 | * |
| 106 | * This data structure contains the result of scanning and may be used by other | 107 | * This data structure contains the result of scanning and may be used by other |
| 107 | * UBI sub-systems to build final UBI data structures, further error-recovery | 108 | * UBI sub-systems to build final UBI data structures, further error-recovery |
| @@ -124,6 +125,7 @@ struct ubi_scan_info { | |||
| 124 | int mean_ec; | 125 | int mean_ec; |
| 125 | uint64_t ec_sum; | 126 | uint64_t ec_sum; |
| 126 | int ec_count; | 127 | int ec_count; |
| 128 | int image_seq_set; | ||
| 127 | }; | 129 | }; |
| 128 | 130 | ||
| 129 | struct ubi_device; | 131 | struct ubi_device; |
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 8419fdccc79c..503ea9b27309 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
| @@ -129,6 +129,7 @@ enum { | |||
| 129 | * @ec: the erase counter | 129 | * @ec: the erase counter |
| 130 | * @vid_hdr_offset: where the VID header starts | 130 | * @vid_hdr_offset: where the VID header starts |
| 131 | * @data_offset: where the user data start | 131 | * @data_offset: where the user data start |
| 132 | * @image_seq: image sequence number | ||
| 132 | * @padding2: reserved for future, zeroes | 133 | * @padding2: reserved for future, zeroes |
| 133 | * @hdr_crc: erase counter header CRC checksum | 134 | * @hdr_crc: erase counter header CRC checksum |
| 134 | * | 135 | * |
| @@ -144,6 +145,14 @@ enum { | |||
| 144 | * volume identifier header and user data, relative to the beginning of the | 145 | * volume identifier header and user data, relative to the beginning of the |
| 145 | * physical eraseblock. These values have to be the same for all physical | 146 | * physical eraseblock. These values have to be the same for all physical |
| 146 | * eraseblocks. | 147 | * eraseblocks. |
| 148 | * | ||
| 149 | * The @image_seq field is used to validate a UBI image that has been prepared | ||
| 150 | * for a UBI device. The @image_seq value can be any value, but it must be the | ||
| 151 | * same on all eraseblocks. UBI will ensure that all new erase counter headers | ||
| 152 | * also contain this value, and will check the value when scanning at start-up. | ||
| 153 | * One way to make use of @image_seq is to increase its value by one every time | ||
| 154 | * an image is flashed over an existing image, then, if the flashing does not | ||
| 155 | * complete, UBI will detect the error when scanning. | ||
| 147 | */ | 156 | */ |
| 148 | struct ubi_ec_hdr { | 157 | struct ubi_ec_hdr { |
| 149 | __be32 magic; | 158 | __be32 magic; |
| @@ -152,7 +161,8 @@ struct ubi_ec_hdr { | |||
| 152 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ | 161 | __be64 ec; /* Warning: the current limit is 31-bit anyway! */ |
| 153 | __be32 vid_hdr_offset; | 162 | __be32 vid_hdr_offset; |
| 154 | __be32 data_offset; | 163 | __be32 data_offset; |
| 155 | __u8 padding2[36]; | 164 | __be32 image_seq; |
| 165 | __u8 padding2[32]; | ||
| 156 | __be32 hdr_crc; | 166 | __be32 hdr_crc; |
| 157 | } __attribute__ ((packed)); | 167 | } __attribute__ ((packed)); |
| 158 | 168 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 28acd133c997..6a5fe9633783 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -301,6 +301,7 @@ struct ubi_wl_entry; | |||
| 301 | * @vol->readers, @vol->writers, @vol->exclusive, | 301 | * @vol->readers, @vol->writers, @vol->exclusive, |
| 302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. | 302 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. |
| 303 | * @ref_count: count of references on the UBI device | 303 | * @ref_count: count of references on the UBI device |
| 304 | * @image_seq: image sequence number recorded on EC headers | ||
| 304 | * | 305 | * |
| 305 | * @rsvd_pebs: count of reserved physical eraseblocks | 306 | * @rsvd_pebs: count of reserved physical eraseblocks |
| 306 | * @avail_pebs: count of available physical eraseblocks | 307 | * @avail_pebs: count of available physical eraseblocks |
| @@ -372,6 +373,7 @@ struct ubi_wl_entry; | |||
| 372 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset | 373 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset |
| 373 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or | 374 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or |
| 374 | * not | 375 | * not |
| 376 | * @nor_flash: non-zero if working on top of NOR flash | ||
| 375 | * @mtd: MTD device descriptor | 377 | * @mtd: MTD device descriptor |
| 376 | * | 378 | * |
| 377 | * @peb_buf1: a buffer of PEB size used for different purposes | 379 | * @peb_buf1: a buffer of PEB size used for different purposes |
| @@ -390,6 +392,7 @@ struct ubi_device { | |||
| 390 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; | 392 | struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; |
| 391 | spinlock_t volumes_lock; | 393 | spinlock_t volumes_lock; |
| 392 | int ref_count; | 394 | int ref_count; |
| 395 | int image_seq; | ||
| 393 | 396 | ||
| 394 | int rsvd_pebs; | 397 | int rsvd_pebs; |
| 395 | int avail_pebs; | 398 | int avail_pebs; |
| @@ -452,7 +455,8 @@ struct ubi_device { | |||
| 452 | int vid_hdr_offset; | 455 | int vid_hdr_offset; |
| 453 | int vid_hdr_aloffset; | 456 | int vid_hdr_aloffset; |
| 454 | int vid_hdr_shift; | 457 | int vid_hdr_shift; |
| 455 | int bad_allowed; | 458 | unsigned int bad_allowed:1; |
| 459 | unsigned int nor_flash:1; | ||
| 456 | struct mtd_info *mtd; | 460 | struct mtd_info *mtd; |
| 457 | 461 | ||
| 458 | void *peb_buf1; | 462 | void *peb_buf1; |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2b2472300610..600c7229d5cf 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
| @@ -459,6 +459,14 @@ retry: | |||
| 459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); | 459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); |
| 460 | prot_queue_add(ubi, e); | 460 | prot_queue_add(ubi, e); |
| 461 | spin_unlock(&ubi->wl_lock); | 461 | spin_unlock(&ubi->wl_lock); |
| 462 | |||
| 463 | err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, | ||
| 464 | ubi->peb_size - ubi->vid_hdr_aloffset); | ||
| 465 | if (err) { | ||
| 466 | ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); | ||
| 467 | return err > 0 ? -EINVAL : err; | ||
| 468 | } | ||
| 469 | |||
| 462 | return e->pnum; | 470 | return e->pnum; |
| 463 | } | 471 | } |
| 464 | 472 | ||
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 8ae72ec14456..0e2ba21d4441 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c | |||
| @@ -908,6 +908,7 @@ static const struct net_device_ops rtl8139_netdev_ops = { | |||
| 908 | .ndo_open = rtl8139_open, | 908 | .ndo_open = rtl8139_open, |
| 909 | .ndo_stop = rtl8139_close, | 909 | .ndo_stop = rtl8139_close, |
| 910 | .ndo_get_stats = rtl8139_get_stats, | 910 | .ndo_get_stats = rtl8139_get_stats, |
| 911 | .ndo_change_mtu = eth_change_mtu, | ||
| 911 | .ndo_validate_addr = eth_validate_addr, | 912 | .ndo_validate_addr = eth_validate_addr, |
| 912 | .ndo_set_mac_address = rtl8139_set_mac_address, | 913 | .ndo_set_mac_address = rtl8139_set_mac_address, |
| 913 | .ndo_start_xmit = rtl8139_start_xmit, | 914 | .ndo_start_xmit = rtl8139_start_xmit, |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1dc721517e4c..c155bd3ec9f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -1725,6 +1725,7 @@ config TLAN | |||
| 1725 | 1725 | ||
| 1726 | config KS8842 | 1726 | config KS8842 |
| 1727 | tristate "Micrel KSZ8842" | 1727 | tristate "Micrel KSZ8842" |
| 1728 | depends on HAS_IOMEM | ||
| 1728 | help | 1729 | help |
| 1729 | This platform driver is for Micrel KSZ8842 chip. | 1730 | This platform driver is for Micrel KSZ8842 chip. |
| 1730 | 1731 | ||
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 85a18175730b..08787f5a22a3 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c | |||
| @@ -569,16 +569,8 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | |||
| 569 | 569 | ||
| 570 | #ifdef DEBUG_DRIVER | 570 | #ifdef DEBUG_DRIVER |
| 571 | /* dump the packet */ | 571 | /* dump the packet */ |
| 572 | { | 572 | print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE, |
| 573 | int i; | 573 | 16, 1, skb->data, 64, true); |
| 574 | |||
| 575 | for (i = 0; i < 64; i++) { | ||
| 576 | if ((i % 16) == 0) | ||
| 577 | printk("\n" KERN_DEBUG); | ||
| 578 | printk ("%2.2x ", skb->data [i]); | ||
| 579 | } | ||
| 580 | printk("\n"); | ||
| 581 | } | ||
| 582 | #endif | 574 | #endif |
| 583 | entry = lp->tx_new & lp->tx_ring_mod_mask; | 575 | entry = lp->tx_new & lp->tx_ring_mod_mask; |
| 584 | ib->btx_ring [entry].length = (-skblen) | 0xf000; | 576 | ib->btx_ring [entry].length = (-skblen) | 0xf000; |
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index d6d4ab3b430c..7d227cdab9f8 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c | |||
| @@ -158,15 +158,12 @@ module_exit(arcnet_exit); | |||
| 158 | void arcnet_dump_skb(struct net_device *dev, | 158 | void arcnet_dump_skb(struct net_device *dev, |
| 159 | struct sk_buff *skb, char *desc) | 159 | struct sk_buff *skb, char *desc) |
| 160 | { | 160 | { |
| 161 | int i; | 161 | char hdr[32]; |
| 162 | 162 | ||
| 163 | printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); | 163 | /* dump the packet */ |
| 164 | for (i = 0; i < skb->len; i++) { | 164 | snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc); |
| 165 | if (i % 16 == 0) | 165 | print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, |
| 166 | printk("\n" KERN_DEBUG "[%04X] ", i); | 166 | 16, 1, skb->data, skb->len, true); |
| 167 | printk("%02X ", ((u_char *) skb->data)[i]); | ||
| 168 | } | ||
| 169 | printk("\n"); | ||
| 170 | } | 167 | } |
| 171 | 168 | ||
| 172 | EXPORT_SYMBOL(arcnet_dump_skb); | 169 | EXPORT_SYMBOL(arcnet_dump_skb); |
| @@ -184,6 +181,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, | |||
| 184 | int i, length; | 181 | int i, length; |
| 185 | unsigned long flags = 0; | 182 | unsigned long flags = 0; |
| 186 | static uint8_t buf[512]; | 183 | static uint8_t buf[512]; |
| 184 | char hdr[32]; | ||
| 187 | 185 | ||
| 188 | /* hw.copy_from_card expects IRQ context so take the IRQ lock | 186 | /* hw.copy_from_card expects IRQ context so take the IRQ lock |
| 189 | to keep it single threaded */ | 187 | to keep it single threaded */ |
| @@ -197,14 +195,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, | |||
| 197 | /* if the offset[0] byte is nonzero, this is a 256-byte packet */ | 195 | /* if the offset[0] byte is nonzero, this is a 256-byte packet */ |
| 198 | length = (buf[2] ? 256 : 512); | 196 | length = (buf[2] ? 256 : 512); |
| 199 | 197 | ||
| 200 | printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); | 198 | /* dump the packet */ |
| 201 | for (i = 0; i < length; i++) { | 199 | snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc); |
| 202 | if (i % 16 == 0) | 200 | print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, |
| 203 | printk("\n" KERN_DEBUG "[%04X] ", i); | 201 | 16, 1, buf, length, true); |
| 204 | printk("%02X ", buf[i]); | ||
| 205 | } | ||
| 206 | printk("\n"); | ||
| 207 | |||
| 208 | } | 202 | } |
| 209 | 203 | ||
| 210 | #else | 204 | #else |
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 6f42ad728915..3fe09876e76d 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c | |||
| @@ -1142,7 +1142,9 @@ static const struct net_device_ops ixp4xx_netdev_ops = { | |||
| 1142 | .ndo_start_xmit = eth_xmit, | 1142 | .ndo_start_xmit = eth_xmit, |
| 1143 | .ndo_set_multicast_list = eth_set_mcast_list, | 1143 | .ndo_set_multicast_list = eth_set_mcast_list, |
| 1144 | .ndo_do_ioctl = eth_ioctl, | 1144 | .ndo_do_ioctl = eth_ioctl, |
| 1145 | 1145 | .ndo_change_mtu = eth_change_mtu, | |
| 1146 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1147 | .ndo_validate_addr = eth_validate_addr, | ||
| 1146 | }; | 1148 | }; |
| 1147 | 1149 | ||
| 1148 | static int __devinit eth_init_one(struct platform_device *pdev) | 1150 | static int __devinit eth_init_one(struct platform_device *pdev) |
diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index e4afbd628c23..607007d75b6f 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c | |||
| @@ -281,6 +281,8 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 281 | if (wol->wolopts & WAKE_PHY) | 281 | if (wol->wolopts & WAKE_PHY) |
| 282 | adapter->wol |= AT_WUFC_LNKC; | 282 | adapter->wol |= AT_WUFC_LNKC; |
| 283 | 283 | ||
| 284 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 285 | |||
| 284 | return 0; | 286 | return 0; |
| 285 | } | 287 | } |
| 286 | 288 | ||
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index 619c6583e1aa..4003955d7a96 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c | |||
| @@ -365,6 +365,8 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 365 | if (wol->wolopts & WAKE_PHY) | 365 | if (wol->wolopts & WAKE_PHY) |
| 366 | adapter->wol |= AT_WUFC_LNKC; | 366 | adapter->wol |= AT_WUFC_LNKC; |
| 367 | 367 | ||
| 368 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 369 | |||
| 368 | return 0; | 370 | return 0; |
| 369 | } | 371 | } |
| 370 | 372 | ||
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index c734b1983ec1..204db961029e 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c | |||
| @@ -2071,7 +2071,7 @@ static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 2071 | if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) | 2071 | if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) |
| 2072 | return -EOPNOTSUPP; | 2072 | return -EOPNOTSUPP; |
| 2073 | 2073 | ||
| 2074 | if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST)) | 2074 | if (wol->wolopts & (WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) |
| 2075 | return -EOPNOTSUPP; | 2075 | return -EOPNOTSUPP; |
| 2076 | 2076 | ||
| 2077 | /* these settings will always override what we currently have */ | 2077 | /* these settings will always override what we currently have */ |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index f703758f0a6e..5b4bf3d2cdc2 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
| @@ -73,7 +73,7 @@ static inline char *nic_name(struct pci_dev *pdev) | |||
| 73 | #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) | 73 | #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) |
| 74 | 74 | ||
| 75 | #define BE_MAX_LRO_DESCRIPTORS 16 | 75 | #define BE_MAX_LRO_DESCRIPTORS 16 |
| 76 | #define BE_MAX_FRAGS_PER_FRAME 16 | 76 | #define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS)) |
| 77 | 77 | ||
| 78 | struct be_dma_mem { | 78 | struct be_dma_mem { |
| 79 | void *va; | 79 | void *va; |
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 9592f22e4c8c..cccc5419ad72 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
| @@ -162,8 +162,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) | |||
| 162 | return -EINVAL; | 162 | return -EINVAL; |
| 163 | 163 | ||
| 164 | adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; | 164 | adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; |
| 165 | if (adapter->max_rx_coal > MAX_SKB_FRAGS) | 165 | if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME) |
| 166 | adapter->max_rx_coal = MAX_SKB_FRAGS - 1; | 166 | adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; |
| 167 | 167 | ||
| 168 | /* if AIC is being turned on now, start with an EQD of 0 */ | 168 | /* if AIC is being turned on now, start with an EQD of 0 */ |
| 169 | if (rx_eq->enable_aic == 0 && | 169 | if (rx_eq->enable_aic == 0 && |
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index b02e805c1db3..29c33c709c6d 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h | |||
| @@ -55,6 +55,10 @@ | |||
| 55 | #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ | 55 | #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ |
| 56 | #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 | 56 | #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 |
| 57 | 57 | ||
| 58 | /********* ISR0 Register offset **********/ | ||
| 59 | #define CEV_ISR0_OFFSET 0xC18 | ||
| 60 | #define CEV_ISR_SIZE 4 | ||
| 61 | |||
| 58 | /********* Event Q door bell *************/ | 62 | /********* Event Q door bell *************/ |
| 59 | #define DB_EQ_OFFSET DB_CQ_OFFSET | 63 | #define DB_EQ_OFFSET DB_CQ_OFFSET |
| 60 | #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ | 64 | #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 66c10c87f517..c43f6a119295 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
| @@ -666,7 +666,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
| 666 | { | 666 | { |
| 667 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 667 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
| 668 | struct be_rx_page_info *page_info; | 668 | struct be_rx_page_info *page_info; |
| 669 | u16 rxq_idx, i, num_rcvd; | 669 | u16 rxq_idx, i, num_rcvd, j; |
| 670 | u32 pktsize, hdr_len, curr_frag_len; | 670 | u32 pktsize, hdr_len, curr_frag_len; |
| 671 | u8 *start; | 671 | u8 *start; |
| 672 | 672 | ||
| @@ -709,22 +709,33 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
| 709 | 709 | ||
| 710 | /* More frags present for this completion */ | 710 | /* More frags present for this completion */ |
| 711 | pktsize -= curr_frag_len; /* account for above copied frag */ | 711 | pktsize -= curr_frag_len; /* account for above copied frag */ |
| 712 | for (i = 1; i < num_rcvd; i++) { | 712 | for (i = 1, j = 0; i < num_rcvd; i++) { |
| 713 | index_inc(&rxq_idx, rxq->len); | 713 | index_inc(&rxq_idx, rxq->len); |
| 714 | page_info = get_rx_page_info(adapter, rxq_idx); | 714 | page_info = get_rx_page_info(adapter, rxq_idx); |
| 715 | 715 | ||
| 716 | curr_frag_len = min(pktsize, rx_frag_size); | 716 | curr_frag_len = min(pktsize, rx_frag_size); |
| 717 | 717 | ||
| 718 | skb_shinfo(skb)->frags[i].page = page_info->page; | 718 | /* Coalesce all frags from the same physical page in one slot */ |
| 719 | skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; | 719 | if (page_info->page_offset == 0) { |
| 720 | skb_shinfo(skb)->frags[i].size = curr_frag_len; | 720 | /* Fresh page */ |
| 721 | j++; | ||
| 722 | skb_shinfo(skb)->frags[j].page = page_info->page; | ||
| 723 | skb_shinfo(skb)->frags[j].page_offset = | ||
| 724 | page_info->page_offset; | ||
| 725 | skb_shinfo(skb)->frags[j].size = 0; | ||
| 726 | skb_shinfo(skb)->nr_frags++; | ||
| 727 | } else { | ||
| 728 | put_page(page_info->page); | ||
| 729 | } | ||
| 730 | |||
| 731 | skb_shinfo(skb)->frags[j].size += curr_frag_len; | ||
| 721 | skb->len += curr_frag_len; | 732 | skb->len += curr_frag_len; |
| 722 | skb->data_len += curr_frag_len; | 733 | skb->data_len += curr_frag_len; |
| 723 | skb_shinfo(skb)->nr_frags++; | ||
| 724 | pktsize -= curr_frag_len; | 734 | pktsize -= curr_frag_len; |
| 725 | 735 | ||
| 726 | memset(page_info, 0, sizeof(*page_info)); | 736 | memset(page_info, 0, sizeof(*page_info)); |
| 727 | } | 737 | } |
| 738 | BUG_ON(j > MAX_SKB_FRAGS); | ||
| 728 | 739 | ||
| 729 | done: | 740 | done: |
| 730 | be_rx_stats_update(adapter, pktsize, num_rcvd); | 741 | be_rx_stats_update(adapter, pktsize, num_rcvd); |
| @@ -786,7 +797,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
| 786 | struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; | 797 | struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; |
| 787 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 798 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
| 788 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; | 799 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; |
| 789 | u16 i, rxq_idx = 0, vid; | 800 | u16 i, rxq_idx = 0, vid, j; |
| 790 | 801 | ||
| 791 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 802 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
| 792 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 803 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
| @@ -794,20 +805,28 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, | |||
| 794 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 805 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
| 795 | 806 | ||
| 796 | remaining = pkt_size; | 807 | remaining = pkt_size; |
| 797 | for (i = 0; i < num_rcvd; i++) { | 808 | for (i = 0, j = -1; i < num_rcvd; i++) { |
| 798 | page_info = get_rx_page_info(adapter, rxq_idx); | 809 | page_info = get_rx_page_info(adapter, rxq_idx); |
| 799 | 810 | ||
| 800 | curr_frag_len = min(remaining, rx_frag_size); | 811 | curr_frag_len = min(remaining, rx_frag_size); |
| 801 | 812 | ||
| 802 | rx_frags[i].page = page_info->page; | 813 | /* Coalesce all frags from the same physical page in one slot */ |
| 803 | rx_frags[i].page_offset = page_info->page_offset; | 814 | if (i == 0 || page_info->page_offset == 0) { |
| 804 | rx_frags[i].size = curr_frag_len; | 815 | /* First frag or Fresh page */ |
| 805 | remaining -= curr_frag_len; | 816 | j++; |
| 817 | rx_frags[j].page = page_info->page; | ||
| 818 | rx_frags[j].page_offset = page_info->page_offset; | ||
| 819 | rx_frags[j].size = 0; | ||
| 820 | } else { | ||
| 821 | put_page(page_info->page); | ||
| 822 | } | ||
| 823 | rx_frags[j].size += curr_frag_len; | ||
| 806 | 824 | ||
| 825 | remaining -= curr_frag_len; | ||
| 807 | index_inc(&rxq_idx, rxq->len); | 826 | index_inc(&rxq_idx, rxq->len); |
| 808 | |||
| 809 | memset(page_info, 0, sizeof(*page_info)); | 827 | memset(page_info, 0, sizeof(*page_info)); |
| 810 | } | 828 | } |
| 829 | BUG_ON(j > MAX_SKB_FRAGS); | ||
| 811 | 830 | ||
| 812 | if (likely(!vlanf)) { | 831 | if (likely(!vlanf)) { |
| 813 | lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, | 832 | lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, |
| @@ -1255,15 +1274,17 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
| 1255 | { | 1274 | { |
| 1256 | struct be_adapter *adapter = dev; | 1275 | struct be_adapter *adapter = dev; |
| 1257 | struct be_ctrl_info *ctrl = &adapter->ctrl; | 1276 | struct be_ctrl_info *ctrl = &adapter->ctrl; |
| 1258 | int rx, tx; | 1277 | int isr; |
| 1259 | 1278 | ||
| 1260 | tx = event_handle(ctrl, &adapter->tx_eq); | 1279 | isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + |
| 1261 | rx = event_handle(ctrl, &adapter->rx_eq); | 1280 | ctrl->pci_func * CEV_ISR_SIZE); |
| 1281 | if (!isr) | ||
| 1282 | return IRQ_NONE; | ||
| 1262 | 1283 | ||
| 1263 | if (rx || tx) | 1284 | event_handle(ctrl, &adapter->tx_eq); |
| 1264 | return IRQ_HANDLED; | 1285 | event_handle(ctrl, &adapter->rx_eq); |
| 1265 | else | 1286 | |
| 1266 | return IRQ_NONE; | 1287 | return IRQ_HANDLED; |
| 1267 | } | 1288 | } |
| 1268 | 1289 | ||
| 1269 | static irqreturn_t be_msix_rx(int irq, void *dev) | 1290 | static irqreturn_t be_msix_rx(int irq, void *dev) |
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 9578a3dfac01..206144f2470f 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c | |||
| @@ -428,10 +428,11 @@ bmac_init_phy(struct net_device *dev) | |||
| 428 | printk(KERN_DEBUG "phy registers:"); | 428 | printk(KERN_DEBUG "phy registers:"); |
| 429 | for (addr = 0; addr < 32; ++addr) { | 429 | for (addr = 0; addr < 32; ++addr) { |
| 430 | if ((addr & 7) == 0) | 430 | if ((addr & 7) == 0) |
| 431 | printk("\n" KERN_DEBUG); | 431 | printk(KERN_DEBUG); |
| 432 | printk(" %.4x", bmac_mif_read(dev, addr)); | 432 | printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); |
| 433 | } | 433 | } |
| 434 | printk("\n"); | 434 | printk(KERN_CONT "\n"); |
| 435 | |||
| 435 | if (bp->is_bmac_plus) { | 436 | if (bp->is_bmac_plus) { |
| 436 | unsigned int capable, ctrl; | 437 | unsigned int capable, ctrl; |
| 437 | 438 | ||
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 38f1c3375d7f..b70cc99962fc 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -6825,6 +6825,14 @@ bnx2_nway_reset(struct net_device *dev) | |||
| 6825 | return 0; | 6825 | return 0; |
| 6826 | } | 6826 | } |
| 6827 | 6827 | ||
| 6828 | static u32 | ||
| 6829 | bnx2_get_link(struct net_device *dev) | ||
| 6830 | { | ||
| 6831 | struct bnx2 *bp = netdev_priv(dev); | ||
| 6832 | |||
| 6833 | return bp->link_up; | ||
| 6834 | } | ||
| 6835 | |||
| 6828 | static int | 6836 | static int |
| 6829 | bnx2_get_eeprom_len(struct net_device *dev) | 6837 | bnx2_get_eeprom_len(struct net_device *dev) |
| 6830 | { | 6838 | { |
| @@ -7392,7 +7400,7 @@ static const struct ethtool_ops bnx2_ethtool_ops = { | |||
| 7392 | .get_wol = bnx2_get_wol, | 7400 | .get_wol = bnx2_get_wol, |
| 7393 | .set_wol = bnx2_set_wol, | 7401 | .set_wol = bnx2_set_wol, |
| 7394 | .nway_reset = bnx2_nway_reset, | 7402 | .nway_reset = bnx2_nway_reset, |
| 7395 | .get_link = ethtool_op_get_link, | 7403 | .get_link = bnx2_get_link, |
| 7396 | .get_eeprom_len = bnx2_get_eeprom_len, | 7404 | .get_eeprom_len = bnx2_get_eeprom_len, |
| 7397 | .get_eeprom = bnx2_get_eeprom, | 7405 | .get_eeprom = bnx2_get_eeprom, |
| 7398 | .set_eeprom = bnx2_set_eeprom, | 7406 | .set_eeprom = bnx2_set_eeprom, |
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 8678457849f9..85a737c5c23f 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h | |||
| @@ -902,6 +902,8 @@ struct bnx2x { | |||
| 902 | u16 rx_quick_cons_trip; | 902 | u16 rx_quick_cons_trip; |
| 903 | u16 rx_ticks_int; | 903 | u16 rx_ticks_int; |
| 904 | u16 rx_ticks; | 904 | u16 rx_ticks; |
| 905 | /* Maximal coalescing timeout in us */ | ||
| 906 | #define BNX2X_MAX_COALESCE_TOUT (0xf0*12) | ||
| 905 | 907 | ||
| 906 | u32 lin_cnt; | 908 | u32 lin_cnt; |
| 907 | 909 | ||
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fbf1352e9c1c..c36a5f33739f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
| @@ -484,8 +484,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp) | |||
| 484 | 484 | ||
| 485 | mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); | 485 | mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); |
| 486 | mark = ((mark + 0x3) & ~0x3); | 486 | mark = ((mark + 0x3) & ~0x3); |
| 487 | printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark); | 487 | printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark); |
| 488 | 488 | ||
| 489 | printk(KERN_ERR PFX); | ||
| 489 | for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { | 490 | for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { |
| 490 | for (word = 0; word < 8; word++) | 491 | for (word = 0; word < 8; word++) |
| 491 | data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + | 492 | data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + |
| @@ -500,7 +501,7 @@ static void bnx2x_fw_dump(struct bnx2x *bp) | |||
| 500 | data[8] = 0x0; | 501 | data[8] = 0x0; |
| 501 | printk(KERN_CONT "%s", (char *)data); | 502 | printk(KERN_CONT "%s", (char *)data); |
| 502 | } | 503 | } |
| 503 | printk("\n" KERN_ERR PFX "end of fw dump\n"); | 504 | printk(KERN_ERR PFX "end of fw dump\n"); |
| 504 | } | 505 | } |
| 505 | 506 | ||
| 506 | static void bnx2x_panic_dump(struct bnx2x *bp) | 507 | static void bnx2x_panic_dump(struct bnx2x *bp) |
| @@ -4434,7 +4435,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) | |||
| 4434 | REG_WR16(bp, BAR_USTRORM_INTMEM + | 4435 | REG_WR16(bp, BAR_USTRORM_INTMEM + |
| 4435 | USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, | 4436 | USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, |
| 4436 | U_SB_ETH_RX_CQ_INDEX), | 4437 | U_SB_ETH_RX_CQ_INDEX), |
| 4437 | bp->rx_ticks ? 0 : 1); | 4438 | (bp->rx_ticks/12) ? 0 : 1); |
| 4438 | 4439 | ||
| 4439 | /* HC_INDEX_C_ETH_TX_CQ_CONS */ | 4440 | /* HC_INDEX_C_ETH_TX_CQ_CONS */ |
| 4440 | REG_WR8(bp, BAR_CSTRORM_INTMEM + | 4441 | REG_WR8(bp, BAR_CSTRORM_INTMEM + |
| @@ -4444,7 +4445,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) | |||
| 4444 | REG_WR16(bp, BAR_CSTRORM_INTMEM + | 4445 | REG_WR16(bp, BAR_CSTRORM_INTMEM + |
| 4445 | CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, | 4446 | CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, |
| 4446 | C_SB_ETH_TX_CQ_INDEX), | 4447 | C_SB_ETH_TX_CQ_INDEX), |
| 4447 | bp->tx_ticks ? 0 : 1); | 4448 | (bp->tx_ticks/12) ? 0 : 1); |
| 4448 | } | 4449 | } |
| 4449 | } | 4450 | } |
| 4450 | 4451 | ||
| @@ -7354,7 +7355,7 @@ static void bnx2x_reset_task(struct work_struct *work) | |||
| 7354 | #ifdef BNX2X_STOP_ON_ERROR | 7355 | #ifdef BNX2X_STOP_ON_ERROR |
| 7355 | BNX2X_ERR("reset task called but STOP_ON_ERROR defined" | 7356 | BNX2X_ERR("reset task called but STOP_ON_ERROR defined" |
| 7356 | " so reset not done to allow debug dump,\n" | 7357 | " so reset not done to allow debug dump,\n" |
| 7357 | KERN_ERR " you will need to reboot when done\n"); | 7358 | " you will need to reboot when done\n"); |
| 7358 | return; | 7359 | return; |
| 7359 | #endif | 7360 | #endif |
| 7360 | 7361 | ||
| @@ -8637,6 +8638,14 @@ static int bnx2x_nway_reset(struct net_device *dev) | |||
| 8637 | return 0; | 8638 | return 0; |
| 8638 | } | 8639 | } |
| 8639 | 8640 | ||
| 8641 | static u32 | ||
| 8642 | bnx2x_get_link(struct net_device *dev) | ||
| 8643 | { | ||
| 8644 | struct bnx2x *bp = netdev_priv(dev); | ||
| 8645 | |||
| 8646 | return bp->link_vars.link_up; | ||
| 8647 | } | ||
| 8648 | |||
| 8640 | static int bnx2x_get_eeprom_len(struct net_device *dev) | 8649 | static int bnx2x_get_eeprom_len(struct net_device *dev) |
| 8641 | { | 8650 | { |
| 8642 | struct bnx2x *bp = netdev_priv(dev); | 8651 | struct bnx2x *bp = netdev_priv(dev); |
| @@ -9061,12 +9070,12 @@ static int bnx2x_set_coalesce(struct net_device *dev, | |||
| 9061 | struct bnx2x *bp = netdev_priv(dev); | 9070 | struct bnx2x *bp = netdev_priv(dev); |
| 9062 | 9071 | ||
| 9063 | bp->rx_ticks = (u16) coal->rx_coalesce_usecs; | 9072 | bp->rx_ticks = (u16) coal->rx_coalesce_usecs; |
| 9064 | if (bp->rx_ticks > 3000) | 9073 | if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT) |
| 9065 | bp->rx_ticks = 3000; | 9074 | bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT; |
| 9066 | 9075 | ||
| 9067 | bp->tx_ticks = (u16) coal->tx_coalesce_usecs; | 9076 | bp->tx_ticks = (u16) coal->tx_coalesce_usecs; |
| 9068 | if (bp->tx_ticks > 0x3000) | 9077 | if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT) |
| 9069 | bp->tx_ticks = 0x3000; | 9078 | bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT; |
| 9070 | 9079 | ||
| 9071 | if (netif_running(dev)) | 9080 | if (netif_running(dev)) |
| 9072 | bnx2x_update_coalesce(bp); | 9081 | bnx2x_update_coalesce(bp); |
| @@ -10034,7 +10043,7 @@ static struct ethtool_ops bnx2x_ethtool_ops = { | |||
| 10034 | .get_msglevel = bnx2x_get_msglevel, | 10043 | .get_msglevel = bnx2x_get_msglevel, |
| 10035 | .set_msglevel = bnx2x_set_msglevel, | 10044 | .set_msglevel = bnx2x_set_msglevel, |
| 10036 | .nway_reset = bnx2x_nway_reset, | 10045 | .nway_reset = bnx2x_nway_reset, |
| 10037 | .get_link = ethtool_op_get_link, | 10046 | .get_link = bnx2x_get_link, |
| 10038 | .get_eeprom_len = bnx2x_get_eeprom_len, | 10047 | .get_eeprom_len = bnx2x_get_eeprom_len, |
| 10039 | .get_eeprom = bnx2x_get_eeprom, | 10048 | .get_eeprom = bnx2x_get_eeprom, |
| 10040 | .set_eeprom = bnx2x_set_eeprom, | 10049 | .set_eeprom = bnx2x_set_eeprom, |
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index d5e18812bf49..33821a81cbf8 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
| @@ -36,7 +36,7 @@ config CAN_CALC_BITTIMING | |||
| 36 | If unsure, say Y. | 36 | If unsure, say Y. |
| 37 | 37 | ||
| 38 | config CAN_SJA1000 | 38 | config CAN_SJA1000 |
| 39 | depends on CAN_DEV | 39 | depends on CAN_DEV && HAS_IOMEM |
| 40 | tristate "Philips SJA1000" | 40 | tristate "Philips SJA1000" |
| 41 | ---help--- | 41 | ---help--- |
| 42 | Driver for the SJA1000 CAN controllers from Philips or NXP | 42 | Driver for the SJA1000 CAN controllers from Philips or NXP |
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 58afafbd3b9c..fd5e32cbcb87 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c | |||
| @@ -1097,7 +1097,7 @@ static const struct net_device_ops cpmac_netdev_ops = { | |||
| 1097 | .ndo_start_xmit = cpmac_start_xmit, | 1097 | .ndo_start_xmit = cpmac_start_xmit, |
| 1098 | .ndo_tx_timeout = cpmac_tx_timeout, | 1098 | .ndo_tx_timeout = cpmac_tx_timeout, |
| 1099 | .ndo_set_multicast_list = cpmac_set_multicast_list, | 1099 | .ndo_set_multicast_list = cpmac_set_multicast_list, |
| 1100 | .ndo_so_ioctl = cpmac_ioctl, | 1100 | .ndo_do_ioctl = cpmac_ioctl, |
| 1101 | .ndo_set_config = cpmac_config, | 1101 | .ndo_set_config = cpmac_config, |
| 1102 | .ndo_change_mtu = eth_change_mtu, | 1102 | .ndo_change_mtu = eth_change_mtu, |
| 1103 | .ndo_validate_addr = eth_validate_addr, | 1103 | .ndo_validate_addr = eth_validate_addr, |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 3eee666a9cd2..55445f980f9c 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
| @@ -1524,6 +1524,7 @@ static void net_timeout(struct net_device *dev) | |||
| 1524 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | 1524 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev) |
| 1525 | { | 1525 | { |
| 1526 | struct net_local *lp = netdev_priv(dev); | 1526 | struct net_local *lp = netdev_priv(dev); |
| 1527 | unsigned long flags; | ||
| 1527 | 1528 | ||
| 1528 | if (net_debug > 3) { | 1529 | if (net_debug > 3) { |
| 1529 | printk("%s: sent %d byte packet of type %x\n", | 1530 | printk("%s: sent %d byte packet of type %x\n", |
| @@ -1535,7 +1536,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
| 1535 | ask the chip to start transmitting before the | 1536 | ask the chip to start transmitting before the |
| 1536 | whole packet has been completely uploaded. */ | 1537 | whole packet has been completely uploaded. */ |
| 1537 | 1538 | ||
| 1538 | spin_lock_irq(&lp->lock); | 1539 | spin_lock_irqsave(&lp->lock, flags); |
| 1539 | netif_stop_queue(dev); | 1540 | netif_stop_queue(dev); |
| 1540 | 1541 | ||
| 1541 | /* initiate a transmit sequence */ | 1542 | /* initiate a transmit sequence */ |
| @@ -1549,13 +1550,13 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
| 1549 | * we're waiting for TxOk, so return 1 and requeue this packet. | 1550 | * we're waiting for TxOk, so return 1 and requeue this packet. |
| 1550 | */ | 1551 | */ |
| 1551 | 1552 | ||
| 1552 | spin_unlock_irq(&lp->lock); | 1553 | spin_unlock_irqrestore(&lp->lock, flags); |
| 1553 | if (net_debug) printk("cs89x0: Tx buffer not free!\n"); | 1554 | if (net_debug) printk("cs89x0: Tx buffer not free!\n"); |
| 1554 | return NETDEV_TX_BUSY; | 1555 | return NETDEV_TX_BUSY; |
| 1555 | } | 1556 | } |
| 1556 | /* Write the contents of the packet */ | 1557 | /* Write the contents of the packet */ |
| 1557 | writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); | 1558 | writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); |
| 1558 | spin_unlock_irq(&lp->lock); | 1559 | spin_unlock_irqrestore(&lp->lock, flags); |
| 1559 | lp->stats.tx_bytes += skb->len; | 1560 | lp->stats.tx_bytes += skb->len; |
| 1560 | dev->trans_start = jiffies; | 1561 | dev->trans_start = jiffies; |
| 1561 | dev_kfree_skb (skb); | 1562 | dev_kfree_skb (skb); |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 538dda4422dc..fb5df5c6203e 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -642,8 +642,7 @@ static int setup_sge_qsets(struct adapter *adap) | |||
| 642 | struct port_info *pi = netdev_priv(dev); | 642 | struct port_info *pi = netdev_priv(dev); |
| 643 | 643 | ||
| 644 | pi->qs = &adap->sge.qs[pi->first_qset]; | 644 | pi->qs = &adap->sge.qs[pi->first_qset]; |
| 645 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; | 645 | for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { |
| 646 | ++j, ++qset_idx) { | ||
| 647 | set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); | 646 | set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); |
| 648 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | 647 | err = t3_sge_alloc_qset(adap, qset_idx, 1, |
| 649 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | 648 | (adap->flags & USING_MSIX) ? qset_idx + 1 : |
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2df8fb0af701..12fd446f9895 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c | |||
| @@ -1820,11 +1820,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | |||
| 1820 | struct device *emac_dev = &priv->ndev->dev; | 1820 | struct device *emac_dev = &priv->ndev->dev; |
| 1821 | struct sockaddr *sa = addr; | 1821 | struct sockaddr *sa = addr; |
| 1822 | 1822 | ||
| 1823 | if (!is_valid_ether_addr(sa->sa_data)) | ||
| 1824 | return -EINVAL; | ||
| 1825 | |||
| 1823 | /* Store mac addr in priv and rx channel and set it in EMAC hw */ | 1826 | /* Store mac addr in priv and rx channel and set it in EMAC hw */ |
| 1824 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); | 1827 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); |
| 1825 | memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); | ||
| 1826 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); | 1828 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); |
| 1827 | emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); | 1829 | |
| 1830 | /* If the interface is down - rxch is NULL. */ | ||
| 1831 | /* MAC address is configured only after the interface is enabled. */ | ||
| 1832 | if (netif_running(ndev)) { | ||
| 1833 | memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); | ||
| 1834 | emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); | ||
| 1835 | } | ||
| 1828 | 1836 | ||
| 1829 | if (netif_msg_drv(priv)) | 1837 | if (netif_msg_drv(priv)) |
| 1830 | dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", | 1838 | dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", |
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 895d72143ee0..4b6a219fecea 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c | |||
| @@ -268,8 +268,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 268 | printk(KERN_INFO "tx_coalesce:\t%d packets\n", | 268 | printk(KERN_INFO "tx_coalesce:\t%d packets\n", |
| 269 | tx_coalesce); | 269 | tx_coalesce); |
| 270 | if (np->coalesce) | 270 | if (np->coalesce) |
| 271 | printk(KERN_INFO "rx_coalesce:\t%d packets\n" | 271 | printk(KERN_INFO |
| 272 | KERN_INFO "rx_timeout: \t%d ns\n", | 272 | "rx_coalesce:\t%d packets\n" |
| 273 | "rx_timeout: \t%d ns\n", | ||
| 273 | np->rx_coalesce, np->rx_timeout*640); | 274 | np->rx_coalesce, np->rx_timeout*640); |
| 274 | if (np->vlan) | 275 | if (np->vlan) |
| 275 | printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); | 276 | printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); |
| @@ -1522,9 +1523,9 @@ mii_get_media (struct net_device *dev) | |||
| 1522 | printk (KERN_INFO "Operating at 10 Mbps, "); | 1523 | printk (KERN_INFO "Operating at 10 Mbps, "); |
| 1523 | } | 1524 | } |
| 1524 | if (bmcr & MII_BMCR_DUPLEX_MODE) { | 1525 | if (bmcr & MII_BMCR_DUPLEX_MODE) { |
| 1525 | printk ("Full duplex\n"); | 1526 | printk (KERN_CONT "Full duplex\n"); |
| 1526 | } else { | 1527 | } else { |
| 1527 | printk ("Half duplex\n"); | 1528 | printk (KERN_CONT "Half duplex\n"); |
| 1528 | } | 1529 | } |
| 1529 | } | 1530 | } |
| 1530 | if (np->tx_flow) | 1531 | if (np->tx_flow) |
| @@ -1614,9 +1615,9 @@ mii_set_media (struct net_device *dev) | |||
| 1614 | } | 1615 | } |
| 1615 | if (np->full_duplex) { | 1616 | if (np->full_duplex) { |
| 1616 | bmcr |= MII_BMCR_DUPLEX_MODE; | 1617 | bmcr |= MII_BMCR_DUPLEX_MODE; |
| 1617 | printk ("Full duplex\n"); | 1618 | printk (KERN_CONT "Full duplex\n"); |
| 1618 | } else { | 1619 | } else { |
| 1619 | printk ("Half duplex\n"); | 1620 | printk (KERN_CONT "Half duplex\n"); |
| 1620 | } | 1621 | } |
| 1621 | #if 0 | 1622 | #if 0 |
| 1622 | /* Set 1000BaseT Master/Slave setting */ | 1623 | /* Set 1000BaseT Master/Slave setting */ |
| @@ -1669,9 +1670,9 @@ mii_get_media_pcs (struct net_device *dev) | |||
| 1669 | __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR); | 1670 | __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR); |
| 1670 | printk (KERN_INFO "Operating at 1000 Mbps, "); | 1671 | printk (KERN_INFO "Operating at 1000 Mbps, "); |
| 1671 | if (bmcr & MII_BMCR_DUPLEX_MODE) { | 1672 | if (bmcr & MII_BMCR_DUPLEX_MODE) { |
| 1672 | printk ("Full duplex\n"); | 1673 | printk (KERN_CONT "Full duplex\n"); |
| 1673 | } else { | 1674 | } else { |
| 1674 | printk ("Half duplex\n"); | 1675 | printk (KERN_CONT "Half duplex\n"); |
| 1675 | } | 1676 | } |
| 1676 | } | 1677 | } |
| 1677 | if (np->tx_flow) | 1678 | if (np->tx_flow) |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e3356f8eb5a..5b8cbdb4b520 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -2185,12 +2185,16 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, | |||
| 2185 | /* Free all the Rx ring sk_buffs */ | 2185 | /* Free all the Rx ring sk_buffs */ |
| 2186 | for (i = 0; i < rx_ring->count; i++) { | 2186 | for (i = 0; i < rx_ring->count; i++) { |
| 2187 | buffer_info = &rx_ring->buffer_info[i]; | 2187 | buffer_info = &rx_ring->buffer_info[i]; |
| 2188 | if (buffer_info->skb) { | 2188 | if (buffer_info->dma) { |
| 2189 | pci_unmap_single(pdev, | 2189 | pci_unmap_single(pdev, |
| 2190 | buffer_info->dma, | 2190 | buffer_info->dma, |
| 2191 | buffer_info->length, | 2191 | buffer_info->length, |
| 2192 | PCI_DMA_FROMDEVICE); | 2192 | PCI_DMA_FROMDEVICE); |
| 2193 | } | ||
| 2194 | |||
| 2195 | buffer_info->dma = 0; | ||
| 2193 | 2196 | ||
| 2197 | if (buffer_info->skb) { | ||
| 2194 | dev_kfree_skb(buffer_info->skb); | 2198 | dev_kfree_skb(buffer_info->skb); |
| 2195 | buffer_info->skb = NULL; | 2199 | buffer_info->skb = NULL; |
| 2196 | } | 2200 | } |
| @@ -4033,6 +4037,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
| 4033 | buffer_info->dma, | 4037 | buffer_info->dma, |
| 4034 | buffer_info->length, | 4038 | buffer_info->length, |
| 4035 | PCI_DMA_FROMDEVICE); | 4039 | PCI_DMA_FROMDEVICE); |
| 4040 | buffer_info->dma = 0; | ||
| 4036 | 4041 | ||
| 4037 | length = le16_to_cpu(rx_desc->length); | 4042 | length = le16_to_cpu(rx_desc->length); |
| 4038 | /* !EOP means multiple descriptors were used to store a single | 4043 | /* !EOP means multiple descriptors were used to store a single |
| @@ -4222,6 +4227,7 @@ map_skb: | |||
| 4222 | pci_unmap_single(pdev, buffer_info->dma, | 4227 | pci_unmap_single(pdev, buffer_info->dma, |
| 4223 | adapter->rx_buffer_len, | 4228 | adapter->rx_buffer_len, |
| 4224 | PCI_DMA_FROMDEVICE); | 4229 | PCI_DMA_FROMDEVICE); |
| 4230 | buffer_info->dma = 0; | ||
| 4225 | 4231 | ||
| 4226 | break; /* while !buffer_info->skb */ | 4232 | break; /* while !buffer_info->skb */ |
| 4227 | } | 4233 | } |
| @@ -4817,6 +4823,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, | |||
| 4817 | 4823 | ||
| 4818 | netif_device_detach(netdev); | 4824 | netif_device_detach(netdev); |
| 4819 | 4825 | ||
| 4826 | if (state == pci_channel_io_perm_failure) | ||
| 4827 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 4828 | |||
| 4820 | if (netif_running(netdev)) | 4829 | if (netif_running(netdev)) |
| 4821 | e1000_down(adapter); | 4830 | e1000_down(adapter); |
| 4822 | pci_disable_device(pdev); | 4831 | pci_disable_device(pdev); |
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 8890c97e1120..c0f185beb8bc 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h | |||
| @@ -238,6 +238,7 @@ | |||
| 238 | #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ | 238 | #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ |
| 239 | #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ | 239 | #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ |
| 240 | #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ | 240 | #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ |
| 241 | #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ | ||
| 241 | #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ | 242 | #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ |
| 242 | 243 | ||
| 243 | /* Constants used to interpret the masked PCI-X bus speed. */ | 244 | /* Constants used to interpret the masked PCI-X bus speed. */ |
| @@ -575,6 +576,8 @@ | |||
| 575 | #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ | 576 | #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ |
| 576 | #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ | 577 | #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ |
| 577 | 578 | ||
| 579 | #define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ | ||
| 580 | |||
| 578 | /* NVM Control */ | 581 | /* NVM Control */ |
| 579 | #define E1000_EECD_SK 0x00000001 /* NVM Clock */ | 582 | #define E1000_EECD_SK 0x00000001 /* NVM Clock */ |
| 580 | #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ | 583 | #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ |
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 163c1c0cfee7..fd44d9f90769 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h | |||
| @@ -215,6 +215,7 @@ enum e1e_registers { | |||
| 215 | E1000_SWSM = 0x05B50, /* SW Semaphore */ | 215 | E1000_SWSM = 0x05B50, /* SW Semaphore */ |
| 216 | E1000_FWSM = 0x05B54, /* FW Semaphore */ | 216 | E1000_FWSM = 0x05B54, /* FW Semaphore */ |
| 217 | E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ | 217 | E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ |
| 218 | E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ | ||
| 218 | E1000_HICR = 0x08F00, /* Host Interface Control */ | 219 | E1000_HICR = 0x08F00, /* Host Interface Control */ |
| 219 | }; | 220 | }; |
| 220 | 221 | ||
| @@ -302,6 +303,9 @@ enum e1e_registers { | |||
| 302 | #define E1000_KMRNCTRLSTA_REN 0x00200000 | 303 | #define E1000_KMRNCTRLSTA_REN 0x00200000 |
| 303 | #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ | 304 | #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ |
| 304 | #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ | 305 | #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ |
| 306 | #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 | ||
| 307 | #define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E | ||
| 308 | #define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 | ||
| 305 | 309 | ||
| 306 | #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 | 310 | #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 |
| 307 | #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ | 311 | #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 9e23f50fb9cd..d56c7473144a 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
| @@ -338,6 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) | |||
| 338 | { | 338 | { |
| 339 | struct e1000_nvm_info *nvm = &hw->nvm; | 339 | struct e1000_nvm_info *nvm = &hw->nvm; |
| 340 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; | 340 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; |
| 341 | union ich8_hws_flash_status hsfsts; | ||
| 341 | u32 gfpreg; | 342 | u32 gfpreg; |
| 342 | u32 sector_base_addr; | 343 | u32 sector_base_addr; |
| 343 | u32 sector_end_addr; | 344 | u32 sector_end_addr; |
| @@ -374,6 +375,20 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) | |||
| 374 | /* Adjust to word count */ | 375 | /* Adjust to word count */ |
| 375 | nvm->flash_bank_size /= sizeof(u16); | 376 | nvm->flash_bank_size /= sizeof(u16); |
| 376 | 377 | ||
| 378 | /* | ||
| 379 | * Make sure the flash bank size does not overwrite the 4k | ||
| 380 | * sector ranges. We may have 64k allotted to us but we only care | ||
| 381 | * about the first 2 4k sectors. Therefore, if we have anything less | ||
| 382 | * than 64k set in the HSFSTS register, we will reduce the bank size | ||
| 383 | * down to 4k and let the rest remain unused. If berasesz == 3, then | ||
| 384 | * we are working in 64k mode. Otherwise we are not. | ||
| 385 | */ | ||
| 386 | if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) { | ||
| 387 | hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); | ||
| 388 | if (hsfsts.hsf_status.berasesz != 3) | ||
| 389 | nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS; | ||
| 390 | } | ||
| 391 | |||
| 377 | nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; | 392 | nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; |
| 378 | 393 | ||
| 379 | /* Clear shadow ram */ | 394 | /* Clear shadow ram */ |
| @@ -446,6 +461,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) | |||
| 446 | return 0; | 461 | return 0; |
| 447 | } | 462 | } |
| 448 | 463 | ||
| 464 | /** | ||
| 465 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) | ||
| 466 | * @hw: pointer to the HW structure | ||
| 467 | * | ||
| 468 | * Checks to see of the link status of the hardware has changed. If a | ||
| 469 | * change in link status has been detected, then we read the PHY registers | ||
| 470 | * to get the current speed/duplex if link exists. | ||
| 471 | **/ | ||
| 472 | static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | ||
| 473 | { | ||
| 474 | struct e1000_mac_info *mac = &hw->mac; | ||
| 475 | s32 ret_val; | ||
| 476 | bool link; | ||
| 477 | |||
| 478 | /* | ||
| 479 | * We only want to go out to the PHY registers to see if Auto-Neg | ||
| 480 | * has completed and/or if our link status has changed. The | ||
| 481 | * get_link_status flag is set upon receiving a Link Status | ||
| 482 | * Change or Rx Sequence Error interrupt. | ||
| 483 | */ | ||
| 484 | if (!mac->get_link_status) { | ||
| 485 | ret_val = 0; | ||
| 486 | goto out; | ||
| 487 | } | ||
| 488 | |||
| 489 | if (hw->mac.type == e1000_pchlan) { | ||
| 490 | ret_val = e1000e_write_kmrn_reg(hw, | ||
| 491 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
| 492 | E1000_KMRNCTRLSTA_K1_ENABLE); | ||
| 493 | if (ret_val) | ||
| 494 | goto out; | ||
| 495 | } | ||
| 496 | |||
| 497 | /* | ||
| 498 | * First we want to see if the MII Status Register reports | ||
| 499 | * link. If so, then we want to get the current speed/duplex | ||
| 500 | * of the PHY. | ||
| 501 | */ | ||
| 502 | ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); | ||
| 503 | if (ret_val) | ||
| 504 | goto out; | ||
| 505 | |||
| 506 | if (!link) | ||
| 507 | goto out; /* No link detected */ | ||
| 508 | |||
| 509 | mac->get_link_status = false; | ||
| 510 | |||
| 511 | if (hw->phy.type == e1000_phy_82578) { | ||
| 512 | ret_val = e1000_link_stall_workaround_hv(hw); | ||
| 513 | if (ret_val) | ||
| 514 | goto out; | ||
| 515 | } | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Check if there was DownShift, must be checked | ||
| 519 | * immediately after link-up | ||
| 520 | */ | ||
| 521 | e1000e_check_downshift(hw); | ||
| 522 | |||
| 523 | /* | ||
| 524 | * If we are forcing speed/duplex, then we simply return since | ||
| 525 | * we have already determined whether we have link or not. | ||
| 526 | */ | ||
| 527 | if (!mac->autoneg) { | ||
| 528 | ret_val = -E1000_ERR_CONFIG; | ||
| 529 | goto out; | ||
| 530 | } | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Auto-Neg is enabled. Auto Speed Detection takes care | ||
| 534 | * of MAC speed/duplex configuration. So we only need to | ||
| 535 | * configure Collision Distance in the MAC. | ||
| 536 | */ | ||
| 537 | e1000e_config_collision_dist(hw); | ||
| 538 | |||
| 539 | /* | ||
| 540 | * Configure Flow Control now that Auto-Neg has completed. | ||
| 541 | * First, we need to restore the desired flow control | ||
| 542 | * settings because we may have had to re-autoneg with a | ||
| 543 | * different link partner. | ||
| 544 | */ | ||
| 545 | ret_val = e1000e_config_fc_after_link_up(hw); | ||
| 546 | if (ret_val) | ||
| 547 | hw_dbg(hw, "Error configuring flow control\n"); | ||
| 548 | |||
| 549 | out: | ||
| 550 | return ret_val; | ||
| 551 | } | ||
| 552 | |||
| 449 | static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) | 553 | static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) |
| 450 | { | 554 | { |
| 451 | struct e1000_hw *hw = &adapter->hw; | 555 | struct e1000_hw *hw = &adapter->hw; |
| @@ -694,6 +798,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) | |||
| 694 | } | 798 | } |
| 695 | 799 | ||
| 696 | /** | 800 | /** |
| 801 | * e1000_lan_init_done_ich8lan - Check for PHY config completion | ||
| 802 | * @hw: pointer to the HW structure | ||
| 803 | * | ||
| 804 | * Check the appropriate indication the MAC has finished configuring the | ||
| 805 | * PHY after a software reset. | ||
| 806 | **/ | ||
| 807 | static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) | ||
| 808 | { | ||
| 809 | u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; | ||
| 810 | |||
| 811 | /* Wait for basic configuration completes before proceeding */ | ||
| 812 | do { | ||
| 813 | data = er32(STATUS); | ||
| 814 | data &= E1000_STATUS_LAN_INIT_DONE; | ||
| 815 | udelay(100); | ||
| 816 | } while ((!data) && --loop); | ||
| 817 | |||
| 818 | /* | ||
| 819 | * If basic configuration is incomplete before the above loop | ||
| 820 | * count reaches 0, loading the configuration from NVM will | ||
| 821 | * leave the PHY in a bad state possibly resulting in no link. | ||
| 822 | */ | ||
| 823 | if (loop == 0) | ||
| 824 | hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); | ||
| 825 | |||
| 826 | /* Clear the Init Done bit for the next init event */ | ||
| 827 | data = er32(STATUS); | ||
| 828 | data &= ~E1000_STATUS_LAN_INIT_DONE; | ||
| 829 | ew32(STATUS, data); | ||
| 830 | } | ||
| 831 | |||
| 832 | /** | ||
| 697 | * e1000_phy_hw_reset_ich8lan - Performs a PHY reset | 833 | * e1000_phy_hw_reset_ich8lan - Performs a PHY reset |
| 698 | * @hw: pointer to the HW structure | 834 | * @hw: pointer to the HW structure |
| 699 | * | 835 | * |
| @@ -707,13 +843,15 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) | |||
| 707 | u32 i; | 843 | u32 i; |
| 708 | u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; | 844 | u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; |
| 709 | s32 ret_val; | 845 | s32 ret_val; |
| 710 | u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; | ||
| 711 | u16 word_addr, reg_data, reg_addr, phy_page = 0; | 846 | u16 word_addr, reg_data, reg_addr, phy_page = 0; |
| 712 | 847 | ||
| 713 | ret_val = e1000e_phy_hw_reset_generic(hw); | 848 | ret_val = e1000e_phy_hw_reset_generic(hw); |
| 714 | if (ret_val) | 849 | if (ret_val) |
| 715 | return ret_val; | 850 | return ret_val; |
| 716 | 851 | ||
| 852 | /* Allow time for h/w to get to a quiescent state after reset */ | ||
| 853 | mdelay(10); | ||
| 854 | |||
| 717 | if (hw->mac.type == e1000_pchlan) { | 855 | if (hw->mac.type == e1000_pchlan) { |
| 718 | ret_val = e1000_hv_phy_workarounds_ich8lan(hw); | 856 | ret_val = e1000_hv_phy_workarounds_ich8lan(hw); |
| 719 | if (ret_val) | 857 | if (ret_val) |
| @@ -741,26 +879,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) | |||
| 741 | if (!(data & sw_cfg_mask)) | 879 | if (!(data & sw_cfg_mask)) |
| 742 | return 0; | 880 | return 0; |
| 743 | 881 | ||
| 744 | /* Wait for basic configuration completes before proceeding*/ | 882 | /* Wait for basic configuration completes before proceeding */ |
| 745 | do { | 883 | e1000_lan_init_done_ich8lan(hw); |
| 746 | data = er32(STATUS); | ||
| 747 | data &= E1000_STATUS_LAN_INIT_DONE; | ||
| 748 | udelay(100); | ||
| 749 | } while ((!data) && --loop); | ||
| 750 | |||
| 751 | /* | ||
| 752 | * If basic configuration is incomplete before the above loop | ||
| 753 | * count reaches 0, loading the configuration from NVM will | ||
| 754 | * leave the PHY in a bad state possibly resulting in no link. | ||
| 755 | */ | ||
| 756 | if (loop == 0) { | ||
| 757 | hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); | ||
| 758 | } | ||
| 759 | |||
| 760 | /* Clear the Init Done bit for the next init event */ | ||
| 761 | data = er32(STATUS); | ||
| 762 | data &= ~E1000_STATUS_LAN_INIT_DONE; | ||
| 763 | ew32(STATUS, data); | ||
| 764 | 884 | ||
| 765 | /* | 885 | /* |
| 766 | * Make sure HW does not configure LCD from PHY | 886 | * Make sure HW does not configure LCD from PHY |
| @@ -961,12 +1081,14 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) | |||
| 961 | phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; | 1081 | phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; |
| 962 | ew32(PHY_CTRL, phy_ctrl); | 1082 | ew32(PHY_CTRL, phy_ctrl); |
| 963 | 1083 | ||
| 1084 | if (phy->type != e1000_phy_igp_3) | ||
| 1085 | return 0; | ||
| 1086 | |||
| 964 | /* | 1087 | /* |
| 965 | * Call gig speed drop workaround on LPLU before accessing | 1088 | * Call gig speed drop workaround on LPLU before accessing |
| 966 | * any PHY registers | 1089 | * any PHY registers |
| 967 | */ | 1090 | */ |
| 968 | if ((hw->mac.type == e1000_ich8lan) && | 1091 | if (hw->mac.type == e1000_ich8lan) |
| 969 | (hw->phy.type == e1000_phy_igp_3)) | ||
| 970 | e1000e_gig_downshift_workaround_ich8lan(hw); | 1092 | e1000e_gig_downshift_workaround_ich8lan(hw); |
| 971 | 1093 | ||
| 972 | /* When LPLU is enabled, we should disable SmartSpeed */ | 1094 | /* When LPLU is enabled, we should disable SmartSpeed */ |
| @@ -979,6 +1101,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) | |||
| 979 | phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; | 1101 | phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; |
| 980 | ew32(PHY_CTRL, phy_ctrl); | 1102 | ew32(PHY_CTRL, phy_ctrl); |
| 981 | 1103 | ||
| 1104 | if (phy->type != e1000_phy_igp_3) | ||
| 1105 | return 0; | ||
| 1106 | |||
| 982 | /* | 1107 | /* |
| 983 | * LPLU and SmartSpeed are mutually exclusive. LPLU is used | 1108 | * LPLU and SmartSpeed are mutually exclusive. LPLU is used |
| 984 | * during Dx states where the power conservation is most | 1109 | * during Dx states where the power conservation is most |
| @@ -1038,6 +1163,10 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) | |||
| 1038 | if (!active) { | 1163 | if (!active) { |
| 1039 | phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; | 1164 | phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; |
| 1040 | ew32(PHY_CTRL, phy_ctrl); | 1165 | ew32(PHY_CTRL, phy_ctrl); |
| 1166 | |||
| 1167 | if (phy->type != e1000_phy_igp_3) | ||
| 1168 | return 0; | ||
| 1169 | |||
| 1041 | /* | 1170 | /* |
| 1042 | * LPLU and SmartSpeed are mutually exclusive. LPLU is used | 1171 | * LPLU and SmartSpeed are mutually exclusive. LPLU is used |
| 1043 | * during Dx states where the power conservation is most | 1172 | * during Dx states where the power conservation is most |
| @@ -1073,12 +1202,14 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) | |||
| 1073 | phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; | 1202 | phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; |
| 1074 | ew32(PHY_CTRL, phy_ctrl); | 1203 | ew32(PHY_CTRL, phy_ctrl); |
| 1075 | 1204 | ||
| 1205 | if (phy->type != e1000_phy_igp_3) | ||
| 1206 | return 0; | ||
| 1207 | |||
| 1076 | /* | 1208 | /* |
| 1077 | * Call gig speed drop workaround on LPLU before accessing | 1209 | * Call gig speed drop workaround on LPLU before accessing |
| 1078 | * any PHY registers | 1210 | * any PHY registers |
| 1079 | */ | 1211 | */ |
| 1080 | if ((hw->mac.type == e1000_ich8lan) && | 1212 | if (hw->mac.type == e1000_ich8lan) |
| 1081 | (hw->phy.type == e1000_phy_igp_3)) | ||
| 1082 | e1000e_gig_downshift_workaround_ich8lan(hw); | 1213 | e1000e_gig_downshift_workaround_ich8lan(hw); |
| 1083 | 1214 | ||
| 1084 | /* When LPLU is enabled, we should disable SmartSpeed */ | 1215 | /* When LPLU is enabled, we should disable SmartSpeed */ |
| @@ -1905,7 +2036,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) | |||
| 1905 | break; | 2036 | break; |
| 1906 | case 1: | 2037 | case 1: |
| 1907 | sector_size = ICH_FLASH_SEG_SIZE_4K; | 2038 | sector_size = ICH_FLASH_SEG_SIZE_4K; |
| 1908 | iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; | 2039 | iteration = 1; |
| 1909 | break; | 2040 | break; |
| 1910 | case 2: | 2041 | case 2: |
| 1911 | if (hw->mac.type == e1000_ich9lan) { | 2042 | if (hw->mac.type == e1000_ich9lan) { |
| @@ -1917,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) | |||
| 1917 | break; | 2048 | break; |
| 1918 | case 3: | 2049 | case 3: |
| 1919 | sector_size = ICH_FLASH_SEG_SIZE_64K; | 2050 | sector_size = ICH_FLASH_SEG_SIZE_64K; |
| 1920 | iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; | 2051 | iteration = 1; |
| 1921 | break; | 2052 | break; |
| 1922 | default: | 2053 | default: |
| 1923 | return -E1000_ERR_NVM; | 2054 | return -E1000_ERR_NVM; |
| @@ -2143,6 +2274,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
| 2143 | ctrl = er32(CTRL); | 2274 | ctrl = er32(CTRL); |
| 2144 | 2275 | ||
| 2145 | if (!e1000_check_reset_block(hw)) { | 2276 | if (!e1000_check_reset_block(hw)) { |
| 2277 | /* Clear PHY Reset Asserted bit */ | ||
| 2278 | if (hw->mac.type >= e1000_pchlan) { | ||
| 2279 | u32 status = er32(STATUS); | ||
| 2280 | ew32(STATUS, status & ~E1000_STATUS_PHYRA); | ||
| 2281 | } | ||
| 2282 | |||
| 2146 | /* | 2283 | /* |
| 2147 | * PHY HW reset requires MAC CORE reset at the same | 2284 | * PHY HW reset requires MAC CORE reset at the same |
| 2148 | * time to make sure the interface between MAC and the | 2285 | * time to make sure the interface between MAC and the |
| @@ -2156,23 +2293,34 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
| 2156 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); | 2293 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); |
| 2157 | msleep(20); | 2294 | msleep(20); |
| 2158 | 2295 | ||
| 2159 | if (!ret_val) { | 2296 | if (!ret_val) |
| 2160 | /* release the swflag because it is not reset by | ||
| 2161 | * hardware reset | ||
| 2162 | */ | ||
| 2163 | e1000_release_swflag_ich8lan(hw); | 2297 | e1000_release_swflag_ich8lan(hw); |
| 2164 | } | ||
| 2165 | 2298 | ||
| 2166 | ret_val = e1000e_get_auto_rd_done(hw); | 2299 | if (ctrl & E1000_CTRL_PHY_RST) |
| 2167 | if (ret_val) { | 2300 | ret_val = hw->phy.ops.get_cfg_done(hw); |
| 2168 | /* | 2301 | |
| 2169 | * When auto config read does not complete, do not | 2302 | if (hw->mac.type >= e1000_ich10lan) { |
| 2170 | * return with an error. This can happen in situations | 2303 | e1000_lan_init_done_ich8lan(hw); |
| 2171 | * where there is no eeprom and prevents getting link. | 2304 | } else { |
| 2172 | */ | 2305 | ret_val = e1000e_get_auto_rd_done(hw); |
| 2173 | hw_dbg(hw, "Auto Read Done did not complete\n"); | 2306 | if (ret_val) { |
| 2307 | /* | ||
| 2308 | * When auto config read does not complete, do not | ||
| 2309 | * return with an error. This can happen in situations | ||
| 2310 | * where there is no eeprom and prevents getting link. | ||
| 2311 | */ | ||
| 2312 | hw_dbg(hw, "Auto Read Done did not complete\n"); | ||
| 2313 | } | ||
| 2174 | } | 2314 | } |
| 2175 | 2315 | ||
| 2316 | /* | ||
| 2317 | * For PCH, this write will make sure that any noise | ||
| 2318 | * will be detected as a CRC error and be dropped rather than show up | ||
| 2319 | * as a bad packet to the DMA engine. | ||
| 2320 | */ | ||
| 2321 | if (hw->mac.type == e1000_pchlan) | ||
| 2322 | ew32(CRC_OFFSET, 0x65656565); | ||
| 2323 | |||
| 2176 | ew32(IMC, 0xffffffff); | 2324 | ew32(IMC, 0xffffffff); |
| 2177 | icr = er32(ICR); | 2325 | icr = er32(ICR); |
| 2178 | 2326 | ||
| @@ -2222,6 +2370,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) | |||
| 2222 | for (i = 0; i < mac->mta_reg_count; i++) | 2370 | for (i = 0; i < mac->mta_reg_count; i++) |
| 2223 | E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); | 2371 | E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); |
| 2224 | 2372 | ||
| 2373 | /* | ||
| 2374 | * The 82578 Rx buffer will stall if wakeup is enabled in host and | ||
| 2375 | * the ME. Reading the BM_WUC register will clear the host wakeup bit. | ||
| 2376 | * Reset the phy after disabling host wakeup to reset the Rx buffer. | ||
| 2377 | */ | ||
| 2378 | if (hw->phy.type == e1000_phy_82578) { | ||
| 2379 | hw->phy.ops.read_phy_reg(hw, BM_WUC, &i); | ||
| 2380 | ret_val = e1000_phy_hw_reset_ich8lan(hw); | ||
| 2381 | if (ret_val) | ||
| 2382 | return ret_val; | ||
| 2383 | } | ||
| 2384 | |||
| 2225 | /* Setup link and flow control */ | 2385 | /* Setup link and flow control */ |
| 2226 | ret_val = e1000_setup_link_ich8lan(hw); | 2386 | ret_val = e1000_setup_link_ich8lan(hw); |
| 2227 | 2387 | ||
| @@ -2254,16 +2414,6 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) | |||
| 2254 | ew32(CTRL_EXT, ctrl_ext); | 2414 | ew32(CTRL_EXT, ctrl_ext); |
| 2255 | 2415 | ||
| 2256 | /* | 2416 | /* |
| 2257 | * The 82578 Rx buffer will stall if wakeup is enabled in host and | ||
| 2258 | * the ME. Reading the BM_WUC register will clear the host wakeup bit. | ||
| 2259 | * Reset the phy after disabling host wakeup to reset the Rx buffer. | ||
| 2260 | */ | ||
| 2261 | if (hw->phy.type == e1000_phy_82578) { | ||
| 2262 | e1e_rphy(hw, BM_WUC, &i); | ||
| 2263 | e1000e_phy_hw_reset_generic(hw); | ||
| 2264 | } | ||
| 2265 | |||
| 2266 | /* | ||
| 2267 | * Clear all of the statistics registers (clear on read). It is | 2417 | * Clear all of the statistics registers (clear on read). It is |
| 2268 | * important that we do this after we have tried to establish link | 2418 | * important that we do this after we have tried to establish link |
| 2269 | * because the symbol error count will increment wildly if there | 2419 | * because the symbol error count will increment wildly if there |
| @@ -2485,6 +2635,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, | |||
| 2485 | if (ret_val) | 2635 | if (ret_val) |
| 2486 | return ret_val; | 2636 | return ret_val; |
| 2487 | 2637 | ||
| 2638 | if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { | ||
| 2639 | ret_val = e1000e_write_kmrn_reg(hw, | ||
| 2640 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
| 2641 | E1000_KMRNCTRLSTA_K1_DISABLE); | ||
| 2642 | if (ret_val) | ||
| 2643 | return ret_val; | ||
| 2644 | } | ||
| 2645 | |||
| 2488 | if ((hw->mac.type == e1000_ich8lan) && | 2646 | if ((hw->mac.type == e1000_ich8lan) && |
| 2489 | (hw->phy.type == e1000_phy_igp_3) && | 2647 | (hw->phy.type == e1000_phy_igp_3) && |
| 2490 | (*speed == SPEED_1000)) { | 2648 | (*speed == SPEED_1000)) { |
| @@ -2850,6 +3008,16 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) | |||
| 2850 | { | 3008 | { |
| 2851 | u32 bank = 0; | 3009 | u32 bank = 0; |
| 2852 | 3010 | ||
| 3011 | if (hw->mac.type >= e1000_pchlan) { | ||
| 3012 | u32 status = er32(STATUS); | ||
| 3013 | |||
| 3014 | if (status & E1000_STATUS_PHYRA) | ||
| 3015 | ew32(STATUS, status & ~E1000_STATUS_PHYRA); | ||
| 3016 | else | ||
| 3017 | hw_dbg(hw, | ||
| 3018 | "PHY Reset Asserted not set - needs delay\n"); | ||
| 3019 | } | ||
| 3020 | |||
| 2853 | e1000e_get_cfg_done(hw); | 3021 | e1000e_get_cfg_done(hw); |
| 2854 | 3022 | ||
| 2855 | /* If EEPROM is not marked present, init the IGP 3 PHY manually */ | 3023 | /* If EEPROM is not marked present, init the IGP 3 PHY manually */ |
| @@ -2921,7 +3089,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) | |||
| 2921 | static struct e1000_mac_operations ich8_mac_ops = { | 3089 | static struct e1000_mac_operations ich8_mac_ops = { |
| 2922 | .id_led_init = e1000e_id_led_init, | 3090 | .id_led_init = e1000e_id_led_init, |
| 2923 | .check_mng_mode = e1000_check_mng_mode_ich8lan, | 3091 | .check_mng_mode = e1000_check_mng_mode_ich8lan, |
| 2924 | .check_for_link = e1000e_check_for_copper_link, | 3092 | .check_for_link = e1000_check_for_copper_link_ich8lan, |
| 2925 | /* cleanup_led dependent on mac type */ | 3093 | /* cleanup_led dependent on mac type */ |
| 2926 | .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, | 3094 | .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, |
| 2927 | .get_bus_info = e1000_get_bus_info_ich8lan, | 3095 | .get_bus_info = e1000_get_bus_info_ich8lan, |
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index be6d9e990374..99ba2b8a2a05 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c | |||
| @@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) | |||
| 378 | 378 | ||
| 379 | mac->get_link_status = 0; | 379 | mac->get_link_status = 0; |
| 380 | 380 | ||
| 381 | if (hw->phy.type == e1000_phy_82578) { | ||
| 382 | ret_val = e1000_link_stall_workaround_hv(hw); | ||
| 383 | if (ret_val) | ||
| 384 | return ret_val; | ||
| 385 | } | ||
| 386 | |||
| 387 | /* | 381 | /* |
| 388 | * Check if there was DownShift, must be checked | 382 | * Check if there was DownShift, must be checked |
| 389 | * immediately after link-up | 383 | * immediately after link-up |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 679885a122b4..63415bb6f48f 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -4785,6 +4785,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, | |||
| 4785 | 4785 | ||
| 4786 | netif_device_detach(netdev); | 4786 | netif_device_detach(netdev); |
| 4787 | 4787 | ||
| 4788 | if (state == pci_channel_io_perm_failure) | ||
| 4789 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 4790 | |||
| 4788 | if (netif_running(netdev)) | 4791 | if (netif_running(netdev)) |
| 4789 | e1000e_down(adapter); | 4792 | e1000e_down(adapter); |
| 4790 | pci_disable_device(pdev); | 4793 | pci_disable_device(pdev); |
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index e23459cf3d0e..994401fd0664 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c | |||
| @@ -1531,7 +1531,12 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, | |||
| 1531 | */ | 1531 | */ |
| 1532 | ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); | 1532 | ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); |
| 1533 | if (ret_val) | 1533 | if (ret_val) |
| 1534 | break; | 1534 | /* |
| 1535 | * If the first read fails, another entity may have | ||
| 1536 | * ownership of the resources, wait and try again to | ||
| 1537 | * see if they have relinquished the resources yet. | ||
| 1538 | */ | ||
| 1539 | udelay(usec_interval); | ||
| 1535 | ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); | 1540 | ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); |
| 1536 | if (ret_val) | 1541 | if (ret_val) |
| 1537 | break; | 1542 | break; |
| @@ -2737,6 +2742,11 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) | |||
| 2737 | if (hw->phy.type != e1000_phy_82578) | 2742 | if (hw->phy.type != e1000_phy_82578) |
| 2738 | goto out; | 2743 | goto out; |
| 2739 | 2744 | ||
| 2745 | /* Do not apply workaround if in PHY loopback bit 14 set */ | ||
| 2746 | hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data); | ||
| 2747 | if (data & PHY_CONTROL_LB) | ||
| 2748 | goto out; | ||
| 2749 | |||
| 2740 | /* check if link is up and at 1Gbps */ | 2750 | /* check if link is up and at 1Gbps */ |
| 2741 | ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); | 2751 | ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); |
| 2742 | if (ret_val) | 2752 | if (ret_val) |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 147c4b088fb3..e8d46cc1bec2 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
| @@ -3080,7 +3080,9 @@ static const struct net_device_ops ehea_netdev_ops = { | |||
| 3080 | .ndo_poll_controller = ehea_netpoll, | 3080 | .ndo_poll_controller = ehea_netpoll, |
| 3081 | #endif | 3081 | #endif |
| 3082 | .ndo_get_stats = ehea_get_stats, | 3082 | .ndo_get_stats = ehea_get_stats, |
| 3083 | .ndo_change_mtu = eth_change_mtu, | ||
| 3083 | .ndo_set_mac_address = ehea_set_mac_addr, | 3084 | .ndo_set_mac_address = ehea_set_mac_addr, |
| 3085 | .ndo_validate_addr = eth_validate_addr, | ||
| 3084 | .ndo_set_multicast_list = ehea_set_multicast_list, | 3086 | .ndo_set_multicast_list = ehea_set_multicast_list, |
| 3085 | .ndo_change_mtu = ehea_change_mtu, | 3087 | .ndo_change_mtu = ehea_change_mtu, |
| 3086 | .ndo_vlan_rx_register = ehea_vlan_rx_register, | 3088 | .ndo_vlan_rx_register = ehea_vlan_rx_register, |
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index b60e27dfcfa7..88d7ebf31220 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c | |||
| @@ -338,8 +338,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, | |||
| 338 | #ifndef MODULE | 338 | #ifndef MODULE |
| 339 | static int printed_version; | 339 | static int printed_version; |
| 340 | if (!printed_version++) | 340 | if (!printed_version++) |
| 341 | printk (KERN_INFO "%s" KERN_INFO "%s", | 341 | printk(KERN_INFO "%s%s", version, version2); |
| 342 | version, version2); | ||
| 343 | #endif | 342 | #endif |
| 344 | 343 | ||
| 345 | card_idx++; | 344 | card_idx++; |
| @@ -1600,7 +1599,7 @@ static int __init epic_init (void) | |||
| 1600 | { | 1599 | { |
| 1601 | /* when a module, this is printed whether or not devices are found in probe */ | 1600 | /* when a module, this is printed whether or not devices are found in probe */ |
| 1602 | #ifdef MODULE | 1601 | #ifdef MODULE |
| 1603 | printk (KERN_INFO "%s" KERN_INFO "%s", | 1602 | printk (KERN_INFO "%s%s", |
| 1604 | version, version2); | 1603 | version, version2); |
| 1605 | #endif | 1604 | #endif |
| 1606 | 1605 | ||
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 891be28a7d4f..48385c42ab57 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c | |||
| @@ -1209,17 +1209,20 @@ static void fealnx_tx_timeout(struct net_device *dev) | |||
| 1209 | unsigned long flags; | 1209 | unsigned long flags; |
| 1210 | int i; | 1210 | int i; |
| 1211 | 1211 | ||
| 1212 | printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," | 1212 | printk(KERN_WARNING |
| 1213 | " resetting...\n", dev->name, ioread32(ioaddr + ISR)); | 1213 | "%s: Transmit timed out, status %8.8x, resetting...\n", |
| 1214 | dev->name, ioread32(ioaddr + ISR)); | ||
| 1214 | 1215 | ||
| 1215 | { | 1216 | { |
| 1216 | printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); | 1217 | printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); |
| 1217 | for (i = 0; i < RX_RING_SIZE; i++) | 1218 | for (i = 0; i < RX_RING_SIZE; i++) |
| 1218 | printk(" %8.8x", (unsigned int) np->rx_ring[i].status); | 1219 | printk(KERN_CONT " %8.8x", |
| 1219 | printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); | 1220 | (unsigned int) np->rx_ring[i].status); |
| 1221 | printk(KERN_CONT "\n"); | ||
| 1222 | printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); | ||
| 1220 | for (i = 0; i < TX_RING_SIZE; i++) | 1223 | for (i = 0; i < TX_RING_SIZE; i++) |
| 1221 | printk(" %4.4x", np->tx_ring[i].status); | 1224 | printk(KERN_CONT " %4.4x", np->tx_ring[i].status); |
| 1222 | printk("\n"); | 1225 | printk(KERN_CONT "\n"); |
| 1223 | } | 1226 | } |
| 1224 | 1227 | ||
| 1225 | spin_lock_irqsave(&np->lock, flags); | 1228 | spin_lock_irqsave(&np->lock, flags); |
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 0f19b743749b..d4b98074b1b7 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
| @@ -1642,6 +1642,7 @@ static const struct net_device_ops fec_netdev_ops = { | |||
| 1642 | .ndo_stop = fec_enet_close, | 1642 | .ndo_stop = fec_enet_close, |
| 1643 | .ndo_start_xmit = fec_enet_start_xmit, | 1643 | .ndo_start_xmit = fec_enet_start_xmit, |
| 1644 | .ndo_set_multicast_list = set_multicast_list, | 1644 | .ndo_set_multicast_list = set_multicast_list, |
| 1645 | .ndo_change_mtu = eth_change_mtu, | ||
| 1645 | .ndo_validate_addr = eth_validate_addr, | 1646 | .ndo_validate_addr = eth_validate_addr, |
| 1646 | .ndo_tx_timeout = fec_timeout, | 1647 | .ndo_tx_timeout = fec_timeout, |
| 1647 | .ndo_set_mac_address = fec_set_mac_address, | 1648 | .ndo_set_mac_address = fec_set_mac_address, |
diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 30b7dd671336..cc47f3f057c7 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h | |||
| @@ -46,12 +46,12 @@ | |||
| 46 | 46 | ||
| 47 | #else | 47 | #else |
| 48 | 48 | ||
| 49 | #define FEC_ECNTRL; 0x000 /* Ethernet control reg */ | 49 | #define FEC_ECNTRL 0x000 /* Ethernet control reg */ |
| 50 | #define FEC_IEVENT; 0x004 /* Interrupt even reg */ | 50 | #define FEC_IEVENT 0x004 /* Interrupt even reg */ |
| 51 | #define FEC_IMASK; 0x008 /* Interrupt mask reg */ | 51 | #define FEC_IMASK 0x008 /* Interrupt mask reg */ |
| 52 | #define FEC_IVEC; 0x00c /* Interrupt vec status reg */ | 52 | #define FEC_IVEC 0x00c /* Interrupt vec status reg */ |
| 53 | #define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ | 53 | #define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ |
| 54 | #define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ | 54 | #define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ |
| 55 | #define FEC_MII_DATA 0x040 /* MII manage frame reg */ | 55 | #define FEC_MII_DATA 0x040 /* MII manage frame reg */ |
| 56 | #define FEC_MII_SPEED 0x044 /* MII speed control reg */ | 56 | #define FEC_MII_SPEED 0x044 /* MII speed control reg */ |
| 57 | #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ | 57 | #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 1094d292630f..3b4e0766c7b2 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -3514,11 +3514,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
| 3514 | nv_msi_workaround(np); | 3514 | nv_msi_workaround(np); |
| 3515 | 3515 | ||
| 3516 | #ifdef CONFIG_FORCEDETH_NAPI | 3516 | #ifdef CONFIG_FORCEDETH_NAPI |
| 3517 | napi_schedule(&np->napi); | 3517 | if (napi_schedule_prep(&np->napi)) { |
| 3518 | 3518 | /* | |
| 3519 | /* Disable furthur irq's | 3519 | * Disable further irq's (msix not enabled with napi) |
| 3520 | (msix not enabled with napi) */ | 3520 | */ |
| 3521 | writel(0, base + NvRegIrqMask); | 3521 | writel(0, base + NvRegIrqMask); |
| 3522 | __napi_schedule(&np->napi); | ||
| 3523 | } | ||
| 3522 | 3524 | ||
| 3523 | #else | 3525 | #else |
| 3524 | do | 3526 | do |
| @@ -3615,12 +3617,13 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) | |||
| 3615 | nv_msi_workaround(np); | 3617 | nv_msi_workaround(np); |
| 3616 | 3618 | ||
| 3617 | #ifdef CONFIG_FORCEDETH_NAPI | 3619 | #ifdef CONFIG_FORCEDETH_NAPI |
| 3618 | napi_schedule(&np->napi); | 3620 | if (napi_schedule_prep(&np->napi)) { |
| 3619 | 3621 | /* | |
| 3620 | /* Disable furthur irq's | 3622 | * Disable further irq's (msix not enabled with napi) |
| 3621 | (msix not enabled with napi) */ | 3623 | */ |
| 3622 | writel(0, base + NvRegIrqMask); | 3624 | writel(0, base + NvRegIrqMask); |
| 3623 | 3625 | __napi_schedule(&np->napi); | |
| 3626 | } | ||
| 3624 | #else | 3627 | #else |
| 3625 | do | 3628 | do |
| 3626 | { | 3629 | { |
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index 3af581303ca2..d167090248e2 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c | |||
| @@ -188,7 +188,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | 190 | ||
| 191 | #ifdef CONFIG_GIANFAR | 191 | #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) |
| 192 | static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) | 192 | static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) |
| 193 | { | 193 | { |
| 194 | struct gfar __iomem *enet_regs; | 194 | struct gfar __iomem *enet_regs; |
| @@ -206,7 +206,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) | |||
| 206 | #endif | 206 | #endif |
| 207 | 207 | ||
| 208 | 208 | ||
| 209 | #ifdef CONFIG_UCC_GETH | 209 | #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) |
| 210 | static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) | 210 | static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) |
| 211 | { | 211 | { |
| 212 | struct device_node *np = NULL; | 212 | struct device_node *np = NULL; |
| @@ -291,7 +291,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, | |||
| 291 | if (of_device_is_compatible(np, "fsl,gianfar-mdio") || | 291 | if (of_device_is_compatible(np, "fsl,gianfar-mdio") || |
| 292 | of_device_is_compatible(np, "fsl,gianfar-tbi") || | 292 | of_device_is_compatible(np, "fsl,gianfar-tbi") || |
| 293 | of_device_is_compatible(np, "gianfar")) { | 293 | of_device_is_compatible(np, "gianfar")) { |
| 294 | #ifdef CONFIG_GIANFAR | 294 | #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) |
| 295 | tbipa = get_gfar_tbipa(regs); | 295 | tbipa = get_gfar_tbipa(regs); |
| 296 | #else | 296 | #else |
| 297 | err = -ENODEV; | 297 | err = -ENODEV; |
| @@ -299,7 +299,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, | |||
| 299 | #endif | 299 | #endif |
| 300 | } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || | 300 | } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || |
| 301 | of_device_is_compatible(np, "ucc_geth_phy")) { | 301 | of_device_is_compatible(np, "ucc_geth_phy")) { |
| 302 | #ifdef CONFIG_UCC_GETH | 302 | #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) |
| 303 | u32 id; | 303 | u32 id; |
| 304 | static u32 mii_mng_master; | 304 | static u32 mii_mng_master; |
| 305 | 305 | ||
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4ae1d259fced..43d813ed9f45 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -156,6 +156,8 @@ static const struct net_device_ops gfar_netdev_ops = { | |||
| 156 | .ndo_tx_timeout = gfar_timeout, | 156 | .ndo_tx_timeout = gfar_timeout, |
| 157 | .ndo_do_ioctl = gfar_ioctl, | 157 | .ndo_do_ioctl = gfar_ioctl, |
| 158 | .ndo_vlan_rx_register = gfar_vlan_rx_register, | 158 | .ndo_vlan_rx_register = gfar_vlan_rx_register, |
| 159 | .ndo_set_mac_address = eth_mac_addr, | ||
| 160 | .ndo_validate_addr = eth_validate_addr, | ||
| 159 | #ifdef CONFIG_NET_POLL_CONTROLLER | 161 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 160 | .ndo_poll_controller = gfar_netpoll, | 162 | .ndo_poll_controller = gfar_netpoll, |
| 161 | #endif | 163 | #endif |
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 9d5b62cb30f7..d62378cbc149 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c | |||
| @@ -173,8 +173,8 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; | |||
| 173 | 173 | ||
| 174 | static const char version[] __devinitconst = | 174 | static const char version[] __devinitconst = |
| 175 | KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" | 175 | KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" |
| 176 | KERN_INFO " Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" | 176 | " Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" |
| 177 | KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; | 177 | " Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; |
| 178 | 178 | ||
| 179 | 179 | ||
| 180 | /* IP_MF appears to be only defined in <netinet/ip.h>, however, | 180 | /* IP_MF appears to be only defined in <netinet/ip.h>, however, |
| @@ -1080,11 +1080,14 @@ static void hamachi_tx_timeout(struct net_device *dev) | |||
| 1080 | { | 1080 | { |
| 1081 | printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); | 1081 | printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); |
| 1082 | for (i = 0; i < RX_RING_SIZE; i++) | 1082 | for (i = 0; i < RX_RING_SIZE; i++) |
| 1083 | printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length)); | 1083 | printk(KERN_CONT " %8.8x", |
| 1084 | printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); | 1084 | le32_to_cpu(hmp->rx_ring[i].status_n_length)); |
| 1085 | printk(KERN_CONT "\n"); | ||
| 1086 | printk(KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); | ||
| 1085 | for (i = 0; i < TX_RING_SIZE; i++) | 1087 | for (i = 0; i < TX_RING_SIZE; i++) |
| 1086 | printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length)); | 1088 | printk(KERN_CONT " %4.4x", |
| 1087 | printk("\n"); | 1089 | le32_to_cpu(hmp->tx_ring[i].status_n_length)); |
| 1090 | printk(KERN_CONT "\n"); | ||
| 1088 | } | 1091 | } |
| 1089 | 1092 | ||
| 1090 | /* Reinit the hardware and make sure the Rx and Tx processes | 1093 | /* Reinit the hardware and make sure the Rx and Tx processes |
| @@ -1753,13 +1756,13 @@ static int hamachi_close(struct net_device *dev) | |||
| 1753 | 1756 | ||
| 1754 | #ifdef __i386__ | 1757 | #ifdef __i386__ |
| 1755 | if (hamachi_debug > 2) { | 1758 | if (hamachi_debug > 2) { |
| 1756 | printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", | 1759 | printk(KERN_DEBUG " Tx ring at %8.8x:\n", |
| 1757 | (int)hmp->tx_ring_dma); | 1760 | (int)hmp->tx_ring_dma); |
| 1758 | for (i = 0; i < TX_RING_SIZE; i++) | 1761 | for (i = 0; i < TX_RING_SIZE; i++) |
| 1759 | printk(" %c #%d desc. %8.8x %8.8x.\n", | 1762 | printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n", |
| 1760 | readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ', | 1763 | readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ', |
| 1761 | i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr); | 1764 | i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr); |
| 1762 | printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", | 1765 | printk(KERN_DEBUG " Rx ring %8.8x:\n", |
| 1763 | (int)hmp->rx_ring_dma); | 1766 | (int)hmp->rx_ring_dma); |
| 1764 | for (i = 0; i < RX_RING_SIZE; i++) { | 1767 | for (i = 0; i < RX_RING_SIZE; i++) { |
| 1765 | printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n", | 1768 | printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n", |
| @@ -1770,7 +1773,7 @@ static int hamachi_close(struct net_device *dev) | |||
| 1770 | u16 *addr = (u16 *) | 1773 | u16 *addr = (u16 *) |
| 1771 | hmp->rx_skbuff[i]->data; | 1774 | hmp->rx_skbuff[i]->data; |
| 1772 | int j; | 1775 | int j; |
| 1773 | 1776 | printk(KERN_DEBUG "Addr: "); | |
| 1774 | for (j = 0; j < 0x50; j++) | 1777 | for (j = 0; j < 0x50; j++) |
| 1775 | printk(" %4.4x", addr[j]); | 1778 | printk(" %4.4x", addr[j]); |
| 1776 | printk("\n"); | 1779 | printk("\n"); |
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 5e4b7afd0683..352703255bba 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c | |||
| @@ -68,7 +68,7 @@ static const char paranoia_str[] = KERN_ERR | |||
| 68 | 68 | ||
| 69 | static const char bc_drvname[] = "baycom_epp"; | 69 | static const char bc_drvname[] = "baycom_epp"; |
| 70 | static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 70 | static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
| 71 | KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; | 71 | "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; |
| 72 | 72 | ||
| 73 | /* --------------------------------------------------------------------- */ | 73 | /* --------------------------------------------------------------------- */ |
| 74 | 74 | ||
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 2e6fc4dc74b1..5f5af9a606f8 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c | |||
| @@ -102,7 +102,7 @@ | |||
| 102 | 102 | ||
| 103 | static const char bc_drvname[] = "baycom_par"; | 103 | static const char bc_drvname[] = "baycom_par"; |
| 104 | static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 104 | static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
| 105 | KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; | 105 | "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; |
| 106 | 106 | ||
| 107 | /* --------------------------------------------------------------------- */ | 107 | /* --------------------------------------------------------------------- */ |
| 108 | 108 | ||
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index b6a816e60c0f..aa4488e871b2 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c | |||
| @@ -91,7 +91,7 @@ | |||
| 91 | 91 | ||
| 92 | static const char bc_drvname[] = "baycom_ser_fdx"; | 92 | static const char bc_drvname[] = "baycom_ser_fdx"; |
| 93 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 93 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
| 94 | KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; | 94 | "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; |
| 95 | 95 | ||
| 96 | /* --------------------------------------------------------------------- */ | 96 | /* --------------------------------------------------------------------- */ |
| 97 | 97 | ||
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c index 3bcc57acbe6d..88c593596020 100644 --- a/drivers/net/hamradio/baycom_ser_hdx.c +++ b/drivers/net/hamradio/baycom_ser_hdx.c | |||
| @@ -79,7 +79,7 @@ | |||
| 79 | 79 | ||
| 80 | static const char bc_drvname[] = "baycom_ser_hdx"; | 80 | static const char bc_drvname[] = "baycom_ser_hdx"; |
| 81 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 81 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
| 82 | KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; | 82 | "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; |
| 83 | 83 | ||
| 84 | /* --------------------------------------------------------------------- */ | 84 | /* --------------------------------------------------------------------- */ |
| 85 | 85 | ||
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index efd9be214885..ac28dd5a4fd1 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c | |||
| @@ -190,6 +190,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | |||
| 190 | phy->ops.write_reg = igb_write_phy_reg_igp; | 190 | phy->ops.write_reg = igb_write_phy_reg_igp; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | /* set lan id */ | ||
| 194 | hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> | ||
| 195 | E1000_STATUS_FUNC_SHIFT; | ||
| 196 | |||
| 193 | /* Set phy->phy_addr and phy->id. */ | 197 | /* Set phy->phy_addr and phy->id. */ |
| 194 | ret_val = igb_get_phy_id_82575(hw); | 198 | ret_val = igb_get_phy_id_82575(hw); |
| 195 | if (ret_val) | 199 | if (ret_val) |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ea17319624aa..adb09d32625d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -127,14 +127,48 @@ static void igb_restore_vlan(struct igb_adapter *); | |||
| 127 | static void igb_ping_all_vfs(struct igb_adapter *); | 127 | static void igb_ping_all_vfs(struct igb_adapter *); |
| 128 | static void igb_msg_task(struct igb_adapter *); | 128 | static void igb_msg_task(struct igb_adapter *); |
| 129 | static int igb_rcv_msg_from_vf(struct igb_adapter *, u32); | 129 | static int igb_rcv_msg_from_vf(struct igb_adapter *, u32); |
| 130 | static inline void igb_set_rah_pool(struct e1000_hw *, int , int); | ||
| 131 | static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); | 130 | static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); |
| 132 | static void igb_vmm_control(struct igb_adapter *); | 131 | static void igb_vmm_control(struct igb_adapter *); |
| 133 | static inline void igb_set_vmolr(struct e1000_hw *, int); | ||
| 134 | static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int); | ||
| 135 | static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); | 132 | static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); |
| 136 | static void igb_restore_vf_multicasts(struct igb_adapter *adapter); | 133 | static void igb_restore_vf_multicasts(struct igb_adapter *adapter); |
| 137 | 134 | ||
| 135 | static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn) | ||
| 136 | { | ||
| 137 | u32 reg_data; | ||
| 138 | |||
| 139 | reg_data = rd32(E1000_VMOLR(vfn)); | ||
| 140 | reg_data |= E1000_VMOLR_BAM | /* Accept broadcast */ | ||
| 141 | E1000_VMOLR_ROPE | /* Accept packets matched in UTA */ | ||
| 142 | E1000_VMOLR_ROMPE | /* Accept packets matched in MTA */ | ||
| 143 | E1000_VMOLR_AUPE | /* Accept untagged packets */ | ||
| 144 | E1000_VMOLR_STRVLAN; /* Strip vlan tags */ | ||
| 145 | wr32(E1000_VMOLR(vfn), reg_data); | ||
| 146 | } | ||
| 147 | |||
| 148 | static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, | ||
| 149 | int vfn) | ||
| 150 | { | ||
| 151 | struct e1000_hw *hw = &adapter->hw; | ||
| 152 | u32 vmolr; | ||
| 153 | |||
| 154 | vmolr = rd32(E1000_VMOLR(vfn)); | ||
| 155 | vmolr &= ~E1000_VMOLR_RLPML_MASK; | ||
| 156 | vmolr |= size | E1000_VMOLR_LPE; | ||
| 157 | wr32(E1000_VMOLR(vfn), vmolr); | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry) | ||
| 163 | { | ||
| 164 | u32 reg_data; | ||
| 165 | |||
| 166 | reg_data = rd32(E1000_RAH(entry)); | ||
| 167 | reg_data &= ~E1000_RAH_POOL_MASK; | ||
| 168 | reg_data |= E1000_RAH_POOL_1 << pool;; | ||
| 169 | wr32(E1000_RAH(entry), reg_data); | ||
| 170 | } | ||
| 171 | |||
| 138 | #ifdef CONFIG_PM | 172 | #ifdef CONFIG_PM |
| 139 | static int igb_suspend(struct pci_dev *, pm_message_t); | 173 | static int igb_suspend(struct pci_dev *, pm_message_t); |
| 140 | static int igb_resume(struct pci_dev *); | 174 | static int igb_resume(struct pci_dev *); |
| @@ -4549,11 +4583,12 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
| 4549 | cleaned = true; | 4583 | cleaned = true; |
| 4550 | cleaned_count++; | 4584 | cleaned_count++; |
| 4551 | 4585 | ||
| 4586 | /* this is the fast path for the non-packet split case */ | ||
| 4552 | if (!adapter->rx_ps_hdr_size) { | 4587 | if (!adapter->rx_ps_hdr_size) { |
| 4553 | pci_unmap_single(pdev, buffer_info->dma, | 4588 | pci_unmap_single(pdev, buffer_info->dma, |
| 4554 | adapter->rx_buffer_len + | 4589 | adapter->rx_buffer_len, |
| 4555 | NET_IP_ALIGN, | ||
| 4556 | PCI_DMA_FROMDEVICE); | 4590 | PCI_DMA_FROMDEVICE); |
| 4591 | buffer_info->dma = 0; | ||
| 4557 | skb_put(skb, length); | 4592 | skb_put(skb, length); |
| 4558 | goto send_up; | 4593 | goto send_up; |
| 4559 | } | 4594 | } |
| @@ -4570,8 +4605,9 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
| 4570 | 4605 | ||
| 4571 | if (!skb_shinfo(skb)->nr_frags) { | 4606 | if (!skb_shinfo(skb)->nr_frags) { |
| 4572 | pci_unmap_single(pdev, buffer_info->dma, | 4607 | pci_unmap_single(pdev, buffer_info->dma, |
| 4573 | adapter->rx_ps_hdr_size + NET_IP_ALIGN, | 4608 | adapter->rx_ps_hdr_size, |
| 4574 | PCI_DMA_FROMDEVICE); | 4609 | PCI_DMA_FROMDEVICE); |
| 4610 | buffer_info->dma = 0; | ||
| 4575 | skb_put(skb, hlen); | 4611 | skb_put(skb, hlen); |
| 4576 | } | 4612 | } |
| 4577 | 4613 | ||
| @@ -4713,7 +4749,6 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, | |||
| 4713 | bufsz = adapter->rx_ps_hdr_size; | 4749 | bufsz = adapter->rx_ps_hdr_size; |
| 4714 | else | 4750 | else |
| 4715 | bufsz = adapter->rx_buffer_len; | 4751 | bufsz = adapter->rx_buffer_len; |
| 4716 | bufsz += NET_IP_ALIGN; | ||
| 4717 | 4752 | ||
| 4718 | while (cleaned_count--) { | 4753 | while (cleaned_count--) { |
| 4719 | rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); | 4754 | rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); |
| @@ -4737,7 +4772,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, | |||
| 4737 | } | 4772 | } |
| 4738 | 4773 | ||
| 4739 | if (!buffer_info->skb) { | 4774 | if (!buffer_info->skb) { |
| 4740 | skb = netdev_alloc_skb(netdev, bufsz); | 4775 | skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN); |
| 4741 | if (!skb) { | 4776 | if (!skb) { |
| 4742 | adapter->alloc_rx_buff_failed++; | 4777 | adapter->alloc_rx_buff_failed++; |
| 4743 | goto no_buffers; | 4778 | goto no_buffers; |
| @@ -5338,6 +5373,9 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, | |||
| 5338 | 5373 | ||
| 5339 | netif_device_detach(netdev); | 5374 | netif_device_detach(netdev); |
| 5340 | 5375 | ||
| 5376 | if (state == pci_channel_io_perm_failure) | ||
| 5377 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 5378 | |||
| 5341 | if (netif_running(netdev)) | 5379 | if (netif_running(netdev)) |
| 5342 | igb_down(adapter); | 5380 | igb_down(adapter); |
| 5343 | pci_disable_device(pdev); | 5381 | pci_disable_device(pdev); |
| @@ -5414,43 +5452,6 @@ static void igb_io_resume(struct pci_dev *pdev) | |||
| 5414 | igb_get_hw_control(adapter); | 5452 | igb_get_hw_control(adapter); |
| 5415 | } | 5453 | } |
| 5416 | 5454 | ||
| 5417 | static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn) | ||
| 5418 | { | ||
| 5419 | u32 reg_data; | ||
| 5420 | |||
| 5421 | reg_data = rd32(E1000_VMOLR(vfn)); | ||
| 5422 | reg_data |= E1000_VMOLR_BAM | /* Accept broadcast */ | ||
| 5423 | E1000_VMOLR_ROPE | /* Accept packets matched in UTA */ | ||
| 5424 | E1000_VMOLR_ROMPE | /* Accept packets matched in MTA */ | ||
| 5425 | E1000_VMOLR_AUPE | /* Accept untagged packets */ | ||
| 5426 | E1000_VMOLR_STRVLAN; /* Strip vlan tags */ | ||
| 5427 | wr32(E1000_VMOLR(vfn), reg_data); | ||
| 5428 | } | ||
| 5429 | |||
| 5430 | static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, | ||
| 5431 | int vfn) | ||
| 5432 | { | ||
| 5433 | struct e1000_hw *hw = &adapter->hw; | ||
| 5434 | u32 vmolr; | ||
| 5435 | |||
| 5436 | vmolr = rd32(E1000_VMOLR(vfn)); | ||
| 5437 | vmolr &= ~E1000_VMOLR_RLPML_MASK; | ||
| 5438 | vmolr |= size | E1000_VMOLR_LPE; | ||
| 5439 | wr32(E1000_VMOLR(vfn), vmolr); | ||
| 5440 | |||
| 5441 | return 0; | ||
| 5442 | } | ||
| 5443 | |||
| 5444 | static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry) | ||
| 5445 | { | ||
| 5446 | u32 reg_data; | ||
| 5447 | |||
| 5448 | reg_data = rd32(E1000_RAH(entry)); | ||
| 5449 | reg_data &= ~E1000_RAH_POOL_MASK; | ||
| 5450 | reg_data |= E1000_RAH_POOL_1 << pool;; | ||
| 5451 | wr32(E1000_RAH(entry), reg_data); | ||
| 5452 | } | ||
| 5453 | |||
| 5454 | static void igb_set_mc_list_pools(struct igb_adapter *adapter, | 5455 | static void igb_set_mc_list_pools(struct igb_adapter *adapter, |
| 5455 | int entry_count, u16 total_rar_filters) | 5456 | int entry_count, u16 total_rar_filters) |
| 5456 | { | 5457 | { |
diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index f3eed6a8fba5..911c082cee5a 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c | |||
| @@ -677,6 +677,14 @@ static int bfin_sir_init_iobuf(iobuff_t *io, int size) | |||
| 677 | return 0; | 677 | return 0; |
| 678 | } | 678 | } |
| 679 | 679 | ||
| 680 | static const struct net_device_ops bfin_sir_ndo = { | ||
| 681 | .ndo_open = bfin_sir_open, | ||
| 682 | .ndo_stop = bfin_sir_stop, | ||
| 683 | .ndo_start_xmit = bfin_sir_hard_xmit, | ||
| 684 | .ndo_do_ioctl = bfin_sir_ioctl, | ||
| 685 | .ndo_get_stats = bfin_sir_stats, | ||
| 686 | }; | ||
| 687 | |||
| 680 | static int __devinit bfin_sir_probe(struct platform_device *pdev) | 688 | static int __devinit bfin_sir_probe(struct platform_device *pdev) |
| 681 | { | 689 | { |
| 682 | struct net_device *dev; | 690 | struct net_device *dev; |
| @@ -718,12 +726,8 @@ static int __devinit bfin_sir_probe(struct platform_device *pdev) | |||
| 718 | if (err) | 726 | if (err) |
| 719 | goto err_mem_3; | 727 | goto err_mem_3; |
| 720 | 728 | ||
| 721 | dev->hard_start_xmit = bfin_sir_hard_xmit; | 729 | dev->netdev_ops = &bfin_sir_ndo; |
| 722 | dev->open = bfin_sir_open; | 730 | dev->irq = sir_port->irq; |
| 723 | dev->stop = bfin_sir_stop; | ||
| 724 | dev->do_ioctl = bfin_sir_ioctl; | ||
| 725 | dev->get_stats = bfin_sir_stats; | ||
| 726 | dev->irq = sir_port->irq; | ||
| 727 | 731 | ||
| 728 | irda_init_max_qos_capabilies(&self->qos); | 732 | irda_init_max_qos_capabilies(&self->qos); |
| 729 | 733 | ||
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index d53aa9582137..20f9bc626688 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/tty.h> | 31 | #include <linux/tty.h> |
| 32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
| 33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
| 34 | #include <linux/smp_lock.h> | ||
| 35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
| 36 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
| 37 | 36 | ||
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index 73585fd8f29f..d12377b84358 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c | |||
| @@ -430,7 +430,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
| 430 | * hardware interrupt handler. Queue flow control is | 430 | * hardware interrupt handler. Queue flow control is |
| 431 | * thus managed under this lock as well. | 431 | * thus managed under this lock as well. |
| 432 | */ | 432 | */ |
| 433 | spin_lock_irq(&np->lock); | 433 | unsigned long flags; |
| 434 | spin_lock_irqsave(&np->lock, flags); | ||
| 434 | 435 | ||
| 435 | add_to_tx_ring(np, skb, length); | 436 | add_to_tx_ring(np, skb, length); |
| 436 | dev->trans_start = jiffies; | 437 | dev->trans_start = jiffies; |
| @@ -446,7 +447,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
| 446 | * is when the transmit statistics are updated. | 447 | * is when the transmit statistics are updated. |
| 447 | */ | 448 | */ |
| 448 | 449 | ||
| 449 | spin_unlock_irq(&np->lock); | 450 | spin_unlock_irqrestore(&np->lock, flags); |
| 450 | #else | 451 | #else |
| 451 | /* This is the case for older hardware which takes | 452 | /* This is the case for older hardware which takes |
| 452 | * a single transmit buffer at a time, and it is | 453 | * a single transmit buffer at a time, and it is |
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index d56890f5c9d5..7c5978ad929a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
| @@ -138,6 +138,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
| 138 | adapter->hw.fc.requested_mode = ixgbe_fc_none; | 138 | adapter->hw.fc.requested_mode = ixgbe_fc_none; |
| 139 | } | 139 | } |
| 140 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | 140 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; |
| 141 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { | ||
| 142 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
| 143 | adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | ||
| 144 | } | ||
| 141 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; | 145 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; |
| 142 | ixgbe_init_interrupt_scheme(adapter); | 146 | ixgbe_init_interrupt_scheme(adapter); |
| 143 | if (netif_running(netdev)) | 147 | if (netif_running(netdev)) |
| @@ -154,6 +158,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
| 154 | adapter->dcb_cfg.pfc_mode_enable = false; | 158 | adapter->dcb_cfg.pfc_mode_enable = false; |
| 155 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | 159 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; |
| 156 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | 160 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; |
| 161 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) | ||
| 162 | adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
| 157 | ixgbe_init_interrupt_scheme(adapter); | 163 | ixgbe_init_interrupt_scheme(adapter); |
| 158 | if (netif_running(netdev)) | 164 | if (netif_running(netdev)) |
| 159 | netdev->netdev_ops->ndo_open(netdev); | 165 | netdev->netdev_ops->ndo_open(netdev); |
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 86f4f3e36f27..2a978008fd6e 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
| @@ -139,7 +139,7 @@ static int ixgbe_get_settings(struct net_device *netdev, | |||
| 139 | ecmd->autoneg = AUTONEG_ENABLE; | 139 | ecmd->autoneg = AUTONEG_ENABLE; |
| 140 | ecmd->transceiver = XCVR_EXTERNAL; | 140 | ecmd->transceiver = XCVR_EXTERNAL; |
| 141 | if ((hw->phy.media_type == ixgbe_media_type_copper) || | 141 | if ((hw->phy.media_type == ixgbe_media_type_copper) || |
| 142 | (hw->mac.type == ixgbe_mac_82599EB)) { | 142 | (hw->phy.multispeed_fiber)) { |
| 143 | ecmd->supported |= (SUPPORTED_1000baseT_Full | | 143 | ecmd->supported |= (SUPPORTED_1000baseT_Full | |
| 144 | SUPPORTED_Autoneg); | 144 | SUPPORTED_Autoneg); |
| 145 | 145 | ||
| @@ -217,7 +217,7 @@ static int ixgbe_set_settings(struct net_device *netdev, | |||
| 217 | s32 err = 0; | 217 | s32 err = 0; |
| 218 | 218 | ||
| 219 | if ((hw->phy.media_type == ixgbe_media_type_copper) || | 219 | if ((hw->phy.media_type == ixgbe_media_type_copper) || |
| 220 | (hw->mac.type == ixgbe_mac_82599EB)) { | 220 | (hw->phy.multispeed_fiber)) { |
| 221 | /* 10000/copper and 1000/copper must autoneg | 221 | /* 10000/copper and 1000/copper must autoneg |
| 222 | * this function does not support any duplex forcing, but can | 222 | * this function does not support any duplex forcing, but can |
| 223 | * limit the advertising of the adapter to only 10000 or 1000 */ | 223 | * limit the advertising of the adapter to only 10000 or 1000 */ |
| @@ -245,6 +245,7 @@ static int ixgbe_set_settings(struct net_device *netdev, | |||
| 245 | } else { | 245 | } else { |
| 246 | /* in this case we currently only support 10Gb/FULL */ | 246 | /* in this case we currently only support 10Gb/FULL */ |
| 247 | if ((ecmd->autoneg == AUTONEG_ENABLE) || | 247 | if ((ecmd->autoneg == AUTONEG_ENABLE) || |
| 248 | (ecmd->advertising != ADVERTISED_10000baseT_Full) || | ||
| 248 | (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) | 249 | (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) |
| 249 | return -EINVAL; | 250 | return -EINVAL; |
| 250 | } | 251 | } |
| @@ -1829,7 +1830,6 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, | |||
| 1829 | break; | 1830 | break; |
| 1830 | default: | 1831 | default: |
| 1831 | wol->supported = 0; | 1832 | wol->supported = 0; |
| 1832 | retval = 0; | ||
| 1833 | } | 1833 | } |
| 1834 | 1834 | ||
| 1835 | return retval; | 1835 | return retval; |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e756e220db32..e3442f47f932 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
| @@ -563,7 +563,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
| 563 | union ixgbe_adv_rx_desc *rx_desc; | 563 | union ixgbe_adv_rx_desc *rx_desc; |
| 564 | struct ixgbe_rx_buffer *bi; | 564 | struct ixgbe_rx_buffer *bi; |
| 565 | unsigned int i; | 565 | unsigned int i; |
| 566 | unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN; | ||
| 567 | 566 | ||
| 568 | i = rx_ring->next_to_use; | 567 | i = rx_ring->next_to_use; |
| 569 | bi = &rx_ring->rx_buffer_info[i]; | 568 | bi = &rx_ring->rx_buffer_info[i]; |
| @@ -593,7 +592,9 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
| 593 | 592 | ||
| 594 | if (!bi->skb) { | 593 | if (!bi->skb) { |
| 595 | struct sk_buff *skb; | 594 | struct sk_buff *skb; |
| 596 | skb = netdev_alloc_skb(adapter->netdev, bufsz); | 595 | skb = netdev_alloc_skb(adapter->netdev, |
| 596 | (rx_ring->rx_buf_len + | ||
| 597 | NET_IP_ALIGN)); | ||
| 597 | 598 | ||
| 598 | if (!skb) { | 599 | if (!skb) { |
| 599 | adapter->alloc_rx_buff_failed++; | 600 | adapter->alloc_rx_buff_failed++; |
| @@ -608,7 +609,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
| 608 | skb_reserve(skb, NET_IP_ALIGN); | 609 | skb_reserve(skb, NET_IP_ALIGN); |
| 609 | 610 | ||
| 610 | bi->skb = skb; | 611 | bi->skb = skb; |
| 611 | bi->dma = pci_map_single(pdev, skb->data, bufsz, | 612 | bi->dma = pci_map_single(pdev, skb->data, |
| 613 | rx_ring->rx_buf_len, | ||
| 612 | PCI_DMA_FROMDEVICE); | 614 | PCI_DMA_FROMDEVICE); |
| 613 | } | 615 | } |
| 614 | /* Refresh the desc even if buffer_addrs didn't change because | 616 | /* Refresh the desc even if buffer_addrs didn't change because |
| @@ -732,6 +734,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, | |||
| 732 | pci_unmap_single(pdev, rx_buffer_info->dma, | 734 | pci_unmap_single(pdev, rx_buffer_info->dma, |
| 733 | rx_ring->rx_buf_len, | 735 | rx_ring->rx_buf_len, |
| 734 | PCI_DMA_FROMDEVICE); | 736 | PCI_DMA_FROMDEVICE); |
| 737 | rx_buffer_info->dma = 0; | ||
| 735 | skb_put(skb, len); | 738 | skb_put(skb, len); |
| 736 | } | 739 | } |
| 737 | 740 | ||
| @@ -2694,16 +2697,23 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
| 2694 | 2697 | ||
| 2695 | /* | 2698 | /* |
| 2696 | * For hot-pluggable SFP+ devices, a new SFP+ module may have | 2699 | * For hot-pluggable SFP+ devices, a new SFP+ module may have |
| 2697 | * arrived before interrupts were enabled. We need to kick off | 2700 | * arrived before interrupts were enabled but after probe. Such |
| 2698 | * the SFP+ module setup first, then try to bring up link. | 2701 | * devices wouldn't have their type identified yet. We need to |
| 2702 | * kick off the SFP+ module setup first, then try to bring up link. | ||
| 2699 | * If we're not hot-pluggable SFP+, we just need to configure link | 2703 | * If we're not hot-pluggable SFP+, we just need to configure link |
| 2700 | * and bring it up. | 2704 | * and bring it up. |
| 2701 | */ | 2705 | */ |
| 2702 | err = hw->phy.ops.identify(hw); | 2706 | if (hw->phy.type == ixgbe_phy_unknown) { |
| 2703 | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | 2707 | err = hw->phy.ops.identify(hw); |
| 2704 | DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err); | 2708 | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { |
| 2705 | ixgbe_down(adapter); | 2709 | /* |
| 2706 | return err; | 2710 | * Take the device down and schedule the sfp tasklet |
| 2711 | * which will unregister_netdev and log it. | ||
| 2712 | */ | ||
| 2713 | ixgbe_down(adapter); | ||
| 2714 | schedule_work(&adapter->sfp_config_module_task); | ||
| 2715 | return err; | ||
| 2716 | } | ||
| 2707 | } | 2717 | } |
| 2708 | 2718 | ||
| 2709 | if (ixgbe_is_sfp(hw)) { | 2719 | if (ixgbe_is_sfp(hw)) { |
| @@ -2812,9 +2822,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, | |||
| 2812 | } | 2822 | } |
| 2813 | if (!rx_buffer_info->page) | 2823 | if (!rx_buffer_info->page) |
| 2814 | continue; | 2824 | continue; |
| 2815 | pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2, | 2825 | if (rx_buffer_info->page_dma) { |
| 2816 | PCI_DMA_FROMDEVICE); | 2826 | pci_unmap_page(pdev, rx_buffer_info->page_dma, |
| 2817 | rx_buffer_info->page_dma = 0; | 2827 | PAGE_SIZE / 2, PCI_DMA_FROMDEVICE); |
| 2828 | rx_buffer_info->page_dma = 0; | ||
| 2829 | } | ||
| 2818 | put_page(rx_buffer_info->page); | 2830 | put_page(rx_buffer_info->page); |
| 2819 | rx_buffer_info->page = NULL; | 2831 | rx_buffer_info->page = NULL; |
| 2820 | rx_buffer_info->page_offset = 0; | 2832 | rx_buffer_info->page_offset = 0; |
| @@ -3118,7 +3130,11 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) | |||
| 3118 | #endif | 3130 | #endif |
| 3119 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { | 3131 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { |
| 3120 | DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); | 3132 | DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); |
| 3121 | ixgbe_set_rss_queues(adapter); | 3133 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || |
| 3134 | (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) | ||
| 3135 | ixgbe_set_fdir_queues(adapter); | ||
| 3136 | else | ||
| 3137 | ixgbe_set_rss_queues(adapter); | ||
| 3122 | } | 3138 | } |
| 3123 | /* adding FCoE rx rings to the end */ | 3139 | /* adding FCoE rx rings to the end */ |
| 3124 | f->mask = adapter->num_rx_queues; | 3140 | f->mask = adapter->num_rx_queues; |
| @@ -3376,7 +3392,12 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) | |||
| 3376 | } | 3392 | } |
| 3377 | #endif /* CONFIG_IXGBE_DCB */ | 3393 | #endif /* CONFIG_IXGBE_DCB */ |
| 3378 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { | 3394 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { |
| 3379 | ixgbe_cache_ring_rss(adapter); | 3395 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || |
| 3396 | (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) | ||
| 3397 | ixgbe_cache_ring_fdir(adapter); | ||
| 3398 | else | ||
| 3399 | ixgbe_cache_ring_rss(adapter); | ||
| 3400 | |||
| 3380 | fcoe_i = f->mask; | 3401 | fcoe_i = f->mask; |
| 3381 | } | 3402 | } |
| 3382 | for (i = 0; i < f->indices; i++, fcoe_i++) | 3403 | for (i = 0; i < f->indices; i++, fcoe_i++) |
| @@ -3716,14 +3737,15 @@ static void ixgbe_sfp_task(struct work_struct *work) | |||
| 3716 | if ((hw->phy.type == ixgbe_phy_nl) && | 3737 | if ((hw->phy.type == ixgbe_phy_nl) && |
| 3717 | (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { | 3738 | (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { |
| 3718 | s32 ret = hw->phy.ops.identify_sfp(hw); | 3739 | s32 ret = hw->phy.ops.identify_sfp(hw); |
| 3719 | if (ret) | 3740 | if (ret == IXGBE_ERR_SFP_NOT_PRESENT) |
| 3720 | goto reschedule; | 3741 | goto reschedule; |
| 3721 | ret = hw->phy.ops.reset(hw); | 3742 | ret = hw->phy.ops.reset(hw); |
| 3722 | if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { | 3743 | if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { |
| 3723 | DPRINTK(PROBE, ERR, "failed to initialize because an " | 3744 | dev_err(&adapter->pdev->dev, "failed to initialize " |
| 3724 | "unsupported SFP+ module type was detected.\n" | 3745 | "because an unsupported SFP+ module type " |
| 3725 | "Reload the driver after installing a " | 3746 | "was detected.\n" |
| 3726 | "supported module.\n"); | 3747 | "Reload the driver after installing a " |
| 3748 | "supported module.\n"); | ||
| 3727 | unregister_netdev(adapter->netdev); | 3749 | unregister_netdev(adapter->netdev); |
| 3728 | } else { | 3750 | } else { |
| 3729 | DPRINTK(PROBE, INFO, "detected SFP+: %d\n", | 3751 | DPRINTK(PROBE, INFO, "detected SFP+: %d\n", |
| @@ -4502,7 +4524,8 @@ static void ixgbe_multispeed_fiber_task(struct work_struct *work) | |||
| 4502 | u32 autoneg; | 4524 | u32 autoneg; |
| 4503 | 4525 | ||
| 4504 | adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK; | 4526 | adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK; |
| 4505 | if (hw->mac.ops.get_link_capabilities) | 4527 | autoneg = hw->phy.autoneg_advertised; |
| 4528 | if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) | ||
| 4506 | hw->mac.ops.get_link_capabilities(hw, &autoneg, | 4529 | hw->mac.ops.get_link_capabilities(hw, &autoneg, |
| 4507 | &hw->mac.autoneg); | 4530 | &hw->mac.autoneg); |
| 4508 | if (hw->mac.ops.setup_link_speed) | 4531 | if (hw->mac.ops.setup_link_speed) |
| @@ -4524,10 +4547,17 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) | |||
| 4524 | u32 err; | 4547 | u32 err; |
| 4525 | 4548 | ||
| 4526 | adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; | 4549 | adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; |
| 4550 | |||
| 4551 | /* Time for electrical oscillations to settle down */ | ||
| 4552 | msleep(100); | ||
| 4527 | err = hw->phy.ops.identify_sfp(hw); | 4553 | err = hw->phy.ops.identify_sfp(hw); |
| 4554 | |||
| 4528 | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | 4555 | if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { |
| 4529 | DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err); | 4556 | dev_err(&adapter->pdev->dev, "failed to initialize because " |
| 4530 | ixgbe_down(adapter); | 4557 | "an unsupported SFP+ module type was detected.\n" |
| 4558 | "Reload the driver after installing a supported " | ||
| 4559 | "module.\n"); | ||
| 4560 | unregister_netdev(adapter->netdev); | ||
| 4531 | return; | 4561 | return; |
| 4532 | } | 4562 | } |
| 4533 | hw->mac.ops.setup_sfp(hw); | 4563 | hw->mac.ops.setup_sfp(hw); |
| @@ -5513,8 +5543,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
| 5513 | round_jiffies(jiffies + (2 * HZ))); | 5543 | round_jiffies(jiffies + (2 * HZ))); |
| 5514 | err = 0; | 5544 | err = 0; |
| 5515 | } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { | 5545 | } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { |
| 5516 | dev_err(&adapter->pdev->dev, "failed to load because an " | 5546 | dev_err(&adapter->pdev->dev, "failed to initialize because " |
| 5517 | "unsupported SFP+ module type was detected.\n"); | 5547 | "an unsupported SFP+ module type was detected.\n" |
| 5548 | "Reload the driver after installing a supported " | ||
| 5549 | "module.\n"); | ||
| 5518 | goto err_sw_init; | 5550 | goto err_sw_init; |
| 5519 | } else if (err) { | 5551 | } else if (err) { |
| 5520 | dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); | 5552 | dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); |
| @@ -5555,12 +5587,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
| 5555 | netdev->features |= NETIF_F_FCOE_CRC; | 5587 | netdev->features |= NETIF_F_FCOE_CRC; |
| 5556 | netdev->features |= NETIF_F_FSO; | 5588 | netdev->features |= NETIF_F_FSO; |
| 5557 | netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; | 5589 | netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; |
| 5558 | DPRINTK(DRV, INFO, "FCoE enabled, " | ||
| 5559 | "disabling Flow Director\n"); | ||
| 5560 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; | ||
| 5561 | adapter->flags &= | ||
| 5562 | ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | ||
| 5563 | adapter->atr_sample_rate = 0; | ||
| 5564 | } else { | 5590 | } else { |
| 5565 | adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; | 5591 | adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; |
| 5566 | } | 5592 | } |
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 453e966762f0..9ecad17522c3 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c | |||
| @@ -60,6 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) | |||
| 60 | 60 | ||
| 61 | if (hw->phy.type == ixgbe_phy_unknown) { | 61 | if (hw->phy.type == ixgbe_phy_unknown) { |
| 62 | for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { | 62 | for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { |
| 63 | hw->phy.mdio.prtad = phy_addr; | ||
| 63 | if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { | 64 | if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { |
| 64 | ixgbe_get_phy_id(hw); | 65 | ixgbe_get_phy_id(hw); |
| 65 | hw->phy.type = | 66 | hw->phy.type = |
| @@ -68,6 +69,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) | |||
| 68 | break; | 69 | break; |
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 72 | /* clear value if nothing found */ | ||
| 73 | hw->phy.mdio.prtad = 0; | ||
| 71 | } else { | 74 | } else { |
| 72 | status = 0; | 75 | status = 0; |
| 73 | } | 76 | } |
diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index dc45e9856c35..6851bdb2ce29 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c | |||
| @@ -14,6 +14,10 @@ | |||
| 14 | #include <linux/mdio.h> | 14 | #include <linux/mdio.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | 16 | ||
| 17 | MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers"); | ||
| 18 | MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc."); | ||
| 19 | MODULE_LICENSE("GPL"); | ||
| 20 | |||
| 17 | /** | 21 | /** |
| 18 | * mdio45_probe - probe for an MDIO (clause 45) device | 22 | * mdio45_probe - probe for an MDIO (clause 45) device |
| 19 | * @mdio: MDIO interface | 23 | * @mdio: MDIO interface |
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c index 2845a0560b84..65ec77dc31f5 100644 --- a/drivers/net/mlx4/cmd.c +++ b/drivers/net/mlx4/cmd.c | |||
| @@ -80,7 +80,9 @@ enum { | |||
| 80 | /* Bad management packet (silently discarded): */ | 80 | /* Bad management packet (silently discarded): */ |
| 81 | CMD_STAT_BAD_PKT = 0x30, | 81 | CMD_STAT_BAD_PKT = 0x30, |
| 82 | /* More outstanding CQEs in CQ than new CQ size: */ | 82 | /* More outstanding CQEs in CQ than new CQ size: */ |
| 83 | CMD_STAT_BAD_SIZE = 0x40 | 83 | CMD_STAT_BAD_SIZE = 0x40, |
| 84 | /* Multi Function device support required: */ | ||
| 85 | CMD_STAT_MULTI_FUNC_REQ = 0x50, | ||
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 86 | enum { | 88 | enum { |
| @@ -128,6 +130,7 @@ static int mlx4_status_to_errno(u8 status) | |||
| 128 | [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, | 130 | [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, |
| 129 | [CMD_STAT_BAD_PKT] = -EINVAL, | 131 | [CMD_STAT_BAD_PKT] = -EINVAL, |
| 130 | [CMD_STAT_BAD_SIZE] = -ENOMEM, | 132 | [CMD_STAT_BAD_SIZE] = -ENOMEM, |
| 133 | [CMD_STAT_MULTI_FUNC_REQ] = -EACCES, | ||
| 131 | }; | 134 | }; |
| 132 | 135 | ||
| 133 | if (status >= ARRAY_SIZE(trans_table) || | 136 | if (status >= ARRAY_SIZE(trans_table) || |
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 018348c01193..dac621b1e9fc 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
| @@ -729,7 +729,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
| 729 | 729 | ||
| 730 | err = mlx4_QUERY_FW(dev); | 730 | err = mlx4_QUERY_FW(dev); |
| 731 | if (err) { | 731 | if (err) { |
| 732 | mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); | 732 | if (err == -EACCES) |
| 733 | mlx4_info(dev, "non-primary physical function, skipping.\n"); | ||
| 734 | else | ||
| 735 | mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); | ||
| 733 | return err; | 736 | return err; |
| 734 | } | 737 | } |
| 735 | 738 | ||
| @@ -1285,6 +1288,7 @@ static struct pci_device_id mlx4_pci_table[] = { | |||
| 1285 | { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ | 1288 | { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ |
| 1286 | { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */ | 1289 | { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */ |
| 1287 | { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */ | 1290 | { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */ |
| 1291 | { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/ | ||
| 1288 | { 0, } | 1292 | { 0, } |
| 1289 | }; | 1293 | }; |
| 1290 | 1294 | ||
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c9bfe4eea189..78c088331f57 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c | |||
| @@ -130,8 +130,8 @@ static int full_duplex[MAX_UNITS]; | |||
| 130 | static const char version[] __devinitconst = | 130 | static const char version[] __devinitconst = |
| 131 | KERN_INFO DRV_NAME " dp8381x driver, version " | 131 | KERN_INFO DRV_NAME " dp8381x driver, version " |
| 132 | DRV_VERSION ", " DRV_RELDATE "\n" | 132 | DRV_VERSION ", " DRV_RELDATE "\n" |
| 133 | KERN_INFO " originally by Donald Becker <becker@scyld.com>\n" | 133 | " originally by Donald Becker <becker@scyld.com>\n" |
| 134 | KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; | 134 | " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; |
| 135 | 135 | ||
| 136 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); | 136 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); |
| 137 | MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); | 137 | MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); |
diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 5c3e242428f1..992dbfffdb05 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c | |||
| @@ -321,7 +321,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) | |||
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | if (ei_debug && version_printed++ == 0) | 323 | if (ei_debug && version_printed++ == 0) |
| 324 | printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); | 324 | printk(KERN_INFO "%s%s", version1, version2); |
| 325 | 325 | ||
| 326 | printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr); | 326 | printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr); |
| 327 | 327 | ||
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 970cedeb5f37..e1cdba752e09 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
| @@ -60,7 +60,18 @@ | |||
| 60 | #define _NETXEN_NIC_LINUX_SUBVERSION 30 | 60 | #define _NETXEN_NIC_LINUX_SUBVERSION 30 |
| 61 | #define NETXEN_NIC_LINUX_VERSIONID "4.0.30" | 61 | #define NETXEN_NIC_LINUX_VERSIONID "4.0.30" |
| 62 | 62 | ||
| 63 | #define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) | 63 | #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) |
| 64 | #define _major(v) (((v) >> 24) & 0xff) | ||
| 65 | #define _minor(v) (((v) >> 16) & 0xff) | ||
| 66 | #define _build(v) ((v) & 0xffff) | ||
| 67 | |||
| 68 | /* version in image has weird encoding: | ||
| 69 | * 7:0 - major | ||
| 70 | * 15:8 - minor | ||
| 71 | * 31:16 - build (little endian) | ||
| 72 | */ | ||
| 73 | #define NETXEN_DECODE_VERSION(v) \ | ||
| 74 | NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16)) | ||
| 64 | 75 | ||
| 65 | #define NETXEN_NUM_FLASH_SECTORS (64) | 76 | #define NETXEN_NUM_FLASH_SECTORS (64) |
| 66 | #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) | 77 | #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) |
| @@ -614,6 +625,7 @@ struct netxen_new_user_info { | |||
| 614 | #define NX_P2_MN_ROMIMAGE 0 | 625 | #define NX_P2_MN_ROMIMAGE 0 |
| 615 | #define NX_P3_CT_ROMIMAGE 1 | 626 | #define NX_P3_CT_ROMIMAGE 1 |
| 616 | #define NX_P3_MN_ROMIMAGE 2 | 627 | #define NX_P3_MN_ROMIMAGE 2 |
| 628 | #define NX_FLASH_ROMIMAGE 3 | ||
| 617 | 629 | ||
| 618 | #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ | 630 | #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ |
| 619 | 631 | ||
| @@ -1243,7 +1255,7 @@ struct netxen_adapter { | |||
| 1243 | u32 resv3; | 1255 | u32 resv3; |
| 1244 | 1256 | ||
| 1245 | u8 has_link_events; | 1257 | u8 has_link_events; |
| 1246 | u8 resv1; | 1258 | u8 fw_type; |
| 1247 | u16 tx_context_id; | 1259 | u16 tx_context_id; |
| 1248 | u16 mtu; | 1260 | u16 mtu; |
| 1249 | u16 is_up; | 1261 | u16 is_up; |
| @@ -1387,6 +1399,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter); | |||
| 1387 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); | 1399 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); |
| 1388 | int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); | 1400 | int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); |
| 1389 | int netxen_load_firmware(struct netxen_adapter *adapter); | 1401 | int netxen_load_firmware(struct netxen_adapter *adapter); |
| 1402 | int netxen_need_fw_reset(struct netxen_adapter *adapter); | ||
| 1390 | void netxen_request_firmware(struct netxen_adapter *adapter); | 1403 | void netxen_request_firmware(struct netxen_adapter *adapter); |
| 1391 | void netxen_release_firmware(struct netxen_adapter *adapter); | 1404 | void netxen_release_firmware(struct netxen_adapter *adapter); |
| 1392 | int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); | 1405 | int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); |
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 3cc047844af3..824103675648 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h | |||
| @@ -853,6 +853,7 @@ enum { | |||
| 853 | #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) | 853 | #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) |
| 854 | 854 | ||
| 855 | #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) | 855 | #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) |
| 856 | #define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0)) | ||
| 856 | 857 | ||
| 857 | #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | 858 | #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) |
| 858 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) | 859 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index bdb143d2b5c7..b899bd51fcd8 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
| @@ -684,11 +684,84 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) | |||
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | int | 686 | int |
| 687 | netxen_need_fw_reset(struct netxen_adapter *adapter) | ||
| 688 | { | ||
| 689 | u32 count, old_count; | ||
| 690 | u32 val, version, major, minor, build; | ||
| 691 | int i, timeout; | ||
| 692 | u8 fw_type; | ||
| 693 | |||
| 694 | /* NX2031 firmware doesn't support heartbit */ | ||
| 695 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
| 696 | return 1; | ||
| 697 | |||
| 698 | /* last attempt had failed */ | ||
| 699 | if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) | ||
| 700 | return 1; | ||
| 701 | |||
| 702 | old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); | ||
| 703 | |||
| 704 | for (i = 0; i < 10; i++) { | ||
| 705 | |||
| 706 | timeout = msleep_interruptible(200); | ||
| 707 | if (timeout) { | ||
| 708 | NXWR32(adapter, CRB_CMDPEG_STATE, | ||
| 709 | PHAN_INITIALIZE_FAILED); | ||
| 710 | return -EINTR; | ||
| 711 | } | ||
| 712 | |||
| 713 | count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); | ||
| 714 | if (count != old_count) | ||
| 715 | break; | ||
| 716 | } | ||
| 717 | |||
| 718 | /* firmware is dead */ | ||
| 719 | if (count == old_count) | ||
| 720 | return 1; | ||
| 721 | |||
| 722 | /* check if we have got newer or different file firmware */ | ||
| 723 | if (adapter->fw) { | ||
| 724 | |||
| 725 | const struct firmware *fw = adapter->fw; | ||
| 726 | |||
| 727 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | ||
| 728 | version = NETXEN_DECODE_VERSION(val); | ||
| 729 | |||
| 730 | major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); | ||
| 731 | minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); | ||
| 732 | build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); | ||
| 733 | |||
| 734 | if (version > NETXEN_VERSION_CODE(major, minor, build)) | ||
| 735 | return 1; | ||
| 736 | |||
| 737 | if (version == NETXEN_VERSION_CODE(major, minor, build)) { | ||
| 738 | |||
| 739 | val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); | ||
| 740 | fw_type = (val & 0x4) ? | ||
| 741 | NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE; | ||
| 742 | |||
| 743 | if (adapter->fw_type != fw_type) | ||
| 744 | return 1; | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | return 0; | ||
| 749 | } | ||
| 750 | |||
| 751 | static char *fw_name[] = { | ||
| 752 | "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash", | ||
| 753 | }; | ||
| 754 | |||
| 755 | int | ||
| 687 | netxen_load_firmware(struct netxen_adapter *adapter) | 756 | netxen_load_firmware(struct netxen_adapter *adapter) |
| 688 | { | 757 | { |
| 689 | u64 *ptr64; | 758 | u64 *ptr64; |
| 690 | u32 i, flashaddr, size; | 759 | u32 i, flashaddr, size; |
| 691 | const struct firmware *fw = adapter->fw; | 760 | const struct firmware *fw = adapter->fw; |
| 761 | struct pci_dev *pdev = adapter->pdev; | ||
| 762 | |||
| 763 | dev_info(&pdev->dev, "loading firmware from %s\n", | ||
| 764 | fw_name[adapter->fw_type]); | ||
| 692 | 765 | ||
| 693 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | 766 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
| 694 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); | 767 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); |
| @@ -756,7 +829,7 @@ static int | |||
| 756 | netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) | 829 | netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) |
| 757 | { | 830 | { |
| 758 | __le32 val; | 831 | __le32 val; |
| 759 | u32 major, minor, build, ver, min_ver, bios; | 832 | u32 ver, min_ver, bios; |
| 760 | struct pci_dev *pdev = adapter->pdev; | 833 | struct pci_dev *pdev = adapter->pdev; |
| 761 | const struct firmware *fw = adapter->fw; | 834 | const struct firmware *fw = adapter->fw; |
| 762 | 835 | ||
| @@ -768,21 +841,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) | |||
| 768 | return -EINVAL; | 841 | return -EINVAL; |
| 769 | 842 | ||
| 770 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | 843 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); |
| 771 | major = (__force u32)val & 0xff; | ||
| 772 | minor = ((__force u32)val >> 8) & 0xff; | ||
| 773 | build = (__force u32)val >> 16; | ||
| 774 | 844 | ||
| 775 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | 845 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
| 776 | min_ver = NETXEN_VERSION_CODE(4, 0, 216); | 846 | min_ver = NETXEN_VERSION_CODE(4, 0, 216); |
| 777 | else | 847 | else |
| 778 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); | 848 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); |
| 779 | 849 | ||
| 780 | ver = NETXEN_VERSION_CODE(major, minor, build); | 850 | ver = NETXEN_DECODE_VERSION(val); |
| 781 | 851 | ||
| 782 | if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { | 852 | if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { |
| 783 | dev_err(&pdev->dev, | 853 | dev_err(&pdev->dev, |
| 784 | "%s: firmware version %d.%d.%d unsupported\n", | 854 | "%s: firmware version %d.%d.%d unsupported\n", |
| 785 | fwname, major, minor, build); | 855 | fwname, _major(ver), _minor(ver), _build(ver)); |
| 786 | return -EINVAL; | 856 | return -EINVAL; |
| 787 | } | 857 | } |
| 788 | 858 | ||
| @@ -798,22 +868,21 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) | |||
| 798 | if (netxen_rom_fast_read(adapter, | 868 | if (netxen_rom_fast_read(adapter, |
| 799 | NX_FW_VERSION_OFFSET, (int *)&val)) | 869 | NX_FW_VERSION_OFFSET, (int *)&val)) |
| 800 | return -EIO; | 870 | return -EIO; |
| 801 | major = (__force u32)val & 0xff; | 871 | val = NETXEN_DECODE_VERSION(val); |
| 802 | minor = ((__force u32)val >> 8) & 0xff; | 872 | if (val > ver) { |
| 803 | build = (__force u32)val >> 16; | 873 | dev_info(&pdev->dev, "%s: firmware is older than flash\n", |
| 804 | if (NETXEN_VERSION_CODE(major, minor, build) > ver) | 874 | fwname); |
| 805 | return -EINVAL; | 875 | return -EINVAL; |
| 876 | } | ||
| 806 | 877 | ||
| 807 | NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); | 878 | NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); |
| 808 | return 0; | 879 | return 0; |
| 809 | } | 880 | } |
| 810 | 881 | ||
| 811 | static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; | ||
| 812 | |||
| 813 | void netxen_request_firmware(struct netxen_adapter *adapter) | 882 | void netxen_request_firmware(struct netxen_adapter *adapter) |
| 814 | { | 883 | { |
| 815 | u32 capability, flashed_ver; | 884 | u32 capability, flashed_ver; |
| 816 | int fw_type; | 885 | u8 fw_type; |
| 817 | struct pci_dev *pdev = adapter->pdev; | 886 | struct pci_dev *pdev = adapter->pdev; |
| 818 | int rc = 0; | 887 | int rc = 0; |
| 819 | 888 | ||
| @@ -830,6 +899,8 @@ request_mn: | |||
| 830 | 899 | ||
| 831 | netxen_rom_fast_read(adapter, | 900 | netxen_rom_fast_read(adapter, |
| 832 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); | 901 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); |
| 902 | flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); | ||
| 903 | |||
| 833 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { | 904 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { |
| 834 | capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); | 905 | capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); |
| 835 | if (capability & NX_PEG_TUNE_MN_PRESENT) { | 906 | if (capability & NX_PEG_TUNE_MN_PRESENT) { |
| @@ -838,6 +909,10 @@ request_mn: | |||
| 838 | } | 909 | } |
| 839 | } | 910 | } |
| 840 | 911 | ||
| 912 | fw_type = NX_FLASH_ROMIMAGE; | ||
| 913 | adapter->fw = NULL; | ||
| 914 | goto done; | ||
| 915 | |||
| 841 | request_fw: | 916 | request_fw: |
| 842 | rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); | 917 | rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); |
| 843 | if (rc != 0) { | 918 | if (rc != 0) { |
| @@ -846,6 +921,7 @@ request_fw: | |||
| 846 | goto request_mn; | 921 | goto request_mn; |
| 847 | } | 922 | } |
| 848 | 923 | ||
| 924 | fw_type = NX_FLASH_ROMIMAGE; | ||
| 849 | adapter->fw = NULL; | 925 | adapter->fw = NULL; |
| 850 | goto done; | 926 | goto done; |
| 851 | } | 927 | } |
| @@ -859,16 +935,13 @@ request_fw: | |||
| 859 | goto request_mn; | 935 | goto request_mn; |
| 860 | } | 936 | } |
| 861 | 937 | ||
| 938 | fw_type = NX_FLASH_ROMIMAGE; | ||
| 862 | adapter->fw = NULL; | 939 | adapter->fw = NULL; |
| 863 | goto done; | 940 | goto done; |
| 864 | } | 941 | } |
| 865 | 942 | ||
| 866 | done: | 943 | done: |
| 867 | if (adapter->fw) | 944 | adapter->fw_type = fw_type; |
| 868 | dev_info(&pdev->dev, "loading firmware from file %s\n", | ||
| 869 | fw_name[fw_type]); | ||
| 870 | else | ||
| 871 | dev_info(&pdev->dev, "loading firmware from flash\n"); | ||
| 872 | } | 945 | } |
| 873 | 946 | ||
| 874 | 947 | ||
| @@ -944,28 +1017,31 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) | |||
| 944 | u32 val = 0; | 1017 | u32 val = 0; |
| 945 | int retries = 60; | 1018 | int retries = 60; |
| 946 | 1019 | ||
| 947 | if (!pegtune_val) { | 1020 | if (pegtune_val) |
| 948 | do { | 1021 | return 0; |
| 949 | val = NXRD32(adapter, CRB_CMDPEG_STATE); | ||
| 950 | 1022 | ||
| 951 | if (val == PHAN_INITIALIZE_COMPLETE || | 1023 | do { |
| 952 | val == PHAN_INITIALIZE_ACK) | 1024 | val = NXRD32(adapter, CRB_CMDPEG_STATE); |
| 953 | return 0; | ||
| 954 | 1025 | ||
| 955 | msleep(500); | 1026 | switch (val) { |
| 1027 | case PHAN_INITIALIZE_COMPLETE: | ||
| 1028 | case PHAN_INITIALIZE_ACK: | ||
| 1029 | return 0; | ||
| 1030 | case PHAN_INITIALIZE_FAILED: | ||
| 1031 | goto out_err; | ||
| 1032 | default: | ||
| 1033 | break; | ||
| 1034 | } | ||
| 956 | 1035 | ||
| 957 | } while (--retries); | 1036 | msleep(500); |
| 958 | 1037 | ||
| 959 | if (!retries) { | 1038 | } while (--retries); |
| 960 | pegtune_val = NXRD32(adapter, | ||
| 961 | NETXEN_ROMUSB_GLB_PEGTUNE_DONE); | ||
| 962 | printk(KERN_WARNING "netxen_phantom_init: init failed, " | ||
| 963 | "pegtune_val=%x\n", pegtune_val); | ||
| 964 | return -1; | ||
| 965 | } | ||
| 966 | } | ||
| 967 | 1039 | ||
| 968 | return 0; | 1040 | NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); |
| 1041 | |||
| 1042 | out_err: | ||
| 1043 | dev_warn(&adapter->pdev->dev, "firmware init failed\n"); | ||
| 1044 | return -EIO; | ||
| 969 | } | 1045 | } |
| 970 | 1046 | ||
| 971 | static int | 1047 | static int |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 71daa3d5f114..27539ddf94c4 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
| @@ -705,7 +705,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) | |||
| 705 | first_driver = (adapter->ahw.pci_func == 0); | 705 | first_driver = (adapter->ahw.pci_func == 0); |
| 706 | 706 | ||
| 707 | if (!first_driver) | 707 | if (!first_driver) |
| 708 | return 0; | 708 | goto wait_init; |
| 709 | 709 | ||
| 710 | first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); | 710 | first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); |
| 711 | 711 | ||
| @@ -718,6 +718,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) | |||
| 718 | if (request_fw) | 718 | if (request_fw) |
| 719 | netxen_request_firmware(adapter); | 719 | netxen_request_firmware(adapter); |
| 720 | 720 | ||
| 721 | err = netxen_need_fw_reset(adapter); | ||
| 722 | if (err <= 0) | ||
| 723 | return err; | ||
| 724 | |||
| 721 | if (first_boot != 0x55555555) { | 725 | if (first_boot != 0x55555555) { |
| 722 | NXWR32(adapter, CRB_CMDPEG_STATE, 0); | 726 | NXWR32(adapter, CRB_CMDPEG_STATE, 0); |
| 723 | netxen_pinit_from_rom(adapter, 0); | 727 | netxen_pinit_from_rom(adapter, 0); |
| @@ -752,6 +756,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) | |||
| 752 | | (_NETXEN_NIC_LINUX_SUBVERSION); | 756 | | (_NETXEN_NIC_LINUX_SUBVERSION); |
| 753 | NXWR32(adapter, CRB_DRIVER_VERSION, val); | 757 | NXWR32(adapter, CRB_DRIVER_VERSION, val); |
| 754 | 758 | ||
| 759 | wait_init: | ||
| 755 | /* Handshake with the card before we register the devices. */ | 760 | /* Handshake with the card before we register the devices. */ |
| 756 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); | 761 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); |
| 757 | if (err) { | 762 | if (err) { |
| @@ -1178,6 +1183,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
| 1178 | free_netdev(netdev); | 1183 | free_netdev(netdev); |
| 1179 | } | 1184 | } |
| 1180 | 1185 | ||
| 1186 | #ifdef CONFIG_PM | ||
| 1181 | static int | 1187 | static int |
| 1182 | netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) | 1188 | netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) |
| 1183 | { | 1189 | { |
| @@ -1242,6 +1248,7 @@ netxen_nic_resume(struct pci_dev *pdev) | |||
| 1242 | 1248 | ||
| 1243 | return 0; | 1249 | return 0; |
| 1244 | } | 1250 | } |
| 1251 | #endif | ||
| 1245 | 1252 | ||
| 1246 | static int netxen_nic_open(struct net_device *netdev) | 1253 | static int netxen_nic_open(struct net_device *netdev) |
| 1247 | { | 1254 | { |
| @@ -1771,8 +1778,10 @@ static struct pci_driver netxen_driver = { | |||
| 1771 | .id_table = netxen_pci_tbl, | 1778 | .id_table = netxen_pci_tbl, |
| 1772 | .probe = netxen_nic_probe, | 1779 | .probe = netxen_nic_probe, |
| 1773 | .remove = __devexit_p(netxen_nic_remove), | 1780 | .remove = __devexit_p(netxen_nic_remove), |
| 1781 | #ifdef CONFIG_PM | ||
| 1774 | .suspend = netxen_nic_suspend, | 1782 | .suspend = netxen_nic_suspend, |
| 1775 | .resume = netxen_nic_resume | 1783 | .resume = netxen_nic_resume |
| 1784 | #endif | ||
| 1776 | }; | 1785 | }; |
| 1777 | 1786 | ||
| 1778 | /* Driver Registration on NetXen card */ | 1787 | /* Driver Registration on NetXen card */ |
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 8c1f6988f398..89f7b2ad5231 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c | |||
| @@ -105,7 +105,7 @@ IVc. Errata | |||
| 105 | 105 | ||
| 106 | static char version[] __devinitdata = | 106 | static char version[] __devinitdata = |
| 107 | KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" | 107 | KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" |
| 108 | KERN_INFO " Support available from http://foo.com/bar/baz.html\n"; | 108 | " Support available from http://foo.com/bar/baz.html\n"; |
| 109 | 109 | ||
| 110 | /* define to 1 to enable PIO instead of MMIO */ | 110 | /* define to 1 to enable PIO instead of MMIO */ |
| 111 | #undef USE_IO_OPS | 111 | #undef USE_IO_OPS |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index f51944b28cfa..06618af1a468 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
| @@ -298,14 +298,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) | |||
| 298 | 298 | ||
| 299 | strcpy(info->node.dev_name, dev->name); | 299 | strcpy(info->node.dev_name, dev->name); |
| 300 | 300 | ||
| 301 | printk(KERN_INFO "%s: port %#3lx, irq %d,", | 301 | printk(KERN_INFO |
| 302 | dev->name, dev->base_addr, dev->irq); | 302 | "%s: port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", |
| 303 | printk (" mmio %#5lx,", (u_long)ti->mmio); | 303 | dev->name, dev->base_addr, dev->irq, |
| 304 | printk (" sram %#5lx,", (u_long)ti->sram_base << 12); | 304 | (u_long)ti->mmio, (u_long)(ti->sram_base << 12), |
| 305 | printk ("\n" KERN_INFO " hwaddr="); | 305 | dev->dev_addr); |
| 306 | for (i = 0; i < TR_ALEN; i++) | ||
| 307 | printk("%02X", dev->dev_addr[i]); | ||
| 308 | printk("\n"); | ||
| 309 | return 0; | 306 | return 0; |
| 310 | 307 | ||
| 311 | cs_failed: | 308 | cs_failed: |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 02ef63ed1f99..36de91baf238 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
| @@ -1425,15 +1425,12 @@ static void BuildLAF(int *ladrf, int *adr) | |||
| 1425 | ladrf[byte] |= (1 << (hashcode & 7)); | 1425 | ladrf[byte] |= (1 << (hashcode & 7)); |
| 1426 | 1426 | ||
| 1427 | #ifdef PCMCIA_DEBUG | 1427 | #ifdef PCMCIA_DEBUG |
| 1428 | if (pc_debug > 2) { | 1428 | if (pc_debug > 2) |
| 1429 | printk(KERN_DEBUG " adr ="); | 1429 | printk(KERN_DEBUG " adr =%pM\n", adr); |
| 1430 | for (i = 0; i < 6; i++) | 1430 | printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode); |
| 1431 | printk(" %02X", adr[i]); | 1431 | for (i = 0; i < 8; i++) |
| 1432 | printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]" | 1432 | printk(KERN_CONT " %02X", ladrf[i]); |
| 1433 | " =", hashcode); | 1433 | printk(KERN_CONT "\n"); |
| 1434 | for (i = 0; i < 8; i++) | ||
| 1435 | printk(" %02X", ladrf[i]); | ||
| 1436 | printk("\n"); | ||
| 1437 | } | 1434 | } |
| 1438 | #endif | 1435 | #endif |
| 1439 | } /* BuildLAF */ | 1436 | } /* BuildLAF */ |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 652a36888361..9ef1c1bfa83d 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
| @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = { | |||
| 1727 | PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), | 1727 | PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), |
| 1728 | PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), | 1728 | PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), |
| 1729 | PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), | 1729 | PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), |
| 1730 | PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826), | ||
| 1730 | PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), | 1731 | PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), |
| 1731 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), | 1732 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), |
| 1732 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), | 1733 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), |
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 1c35e1d637a0..28368157dac4 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
| @@ -485,7 +485,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, | |||
| 485 | &new_ring_dma_addr); | 485 | &new_ring_dma_addr); |
| 486 | if (new_tx_ring == NULL) { | 486 | if (new_tx_ring == NULL) { |
| 487 | if (netif_msg_drv(lp)) | 487 | if (netif_msg_drv(lp)) |
| 488 | printk("\n" KERN_ERR | 488 | printk(KERN_ERR |
| 489 | "%s: Consistent memory allocation failed.\n", | 489 | "%s: Consistent memory allocation failed.\n", |
| 490 | dev->name); | 490 | dev->name); |
| 491 | return; | 491 | return; |
| @@ -496,7 +496,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, | |||
| 496 | GFP_ATOMIC); | 496 | GFP_ATOMIC); |
| 497 | if (!new_dma_addr_list) { | 497 | if (!new_dma_addr_list) { |
| 498 | if (netif_msg_drv(lp)) | 498 | if (netif_msg_drv(lp)) |
| 499 | printk("\n" KERN_ERR | 499 | printk(KERN_ERR |
| 500 | "%s: Memory allocation failed.\n", dev->name); | 500 | "%s: Memory allocation failed.\n", dev->name); |
| 501 | goto free_new_tx_ring; | 501 | goto free_new_tx_ring; |
| 502 | } | 502 | } |
| @@ -505,7 +505,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, | |||
| 505 | GFP_ATOMIC); | 505 | GFP_ATOMIC); |
| 506 | if (!new_skb_list) { | 506 | if (!new_skb_list) { |
| 507 | if (netif_msg_drv(lp)) | 507 | if (netif_msg_drv(lp)) |
| 508 | printk("\n" KERN_ERR | 508 | printk(KERN_ERR |
| 509 | "%s: Memory allocation failed.\n", dev->name); | 509 | "%s: Memory allocation failed.\n", dev->name); |
| 510 | goto free_new_lists; | 510 | goto free_new_lists; |
| 511 | } | 511 | } |
| @@ -563,7 +563,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, | |||
| 563 | &new_ring_dma_addr); | 563 | &new_ring_dma_addr); |
| 564 | if (new_rx_ring == NULL) { | 564 | if (new_rx_ring == NULL) { |
| 565 | if (netif_msg_drv(lp)) | 565 | if (netif_msg_drv(lp)) |
| 566 | printk("\n" KERN_ERR | 566 | printk(KERN_ERR |
| 567 | "%s: Consistent memory allocation failed.\n", | 567 | "%s: Consistent memory allocation failed.\n", |
| 568 | dev->name); | 568 | dev->name); |
| 569 | return; | 569 | return; |
| @@ -574,7 +574,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, | |||
| 574 | GFP_ATOMIC); | 574 | GFP_ATOMIC); |
| 575 | if (!new_dma_addr_list) { | 575 | if (!new_dma_addr_list) { |
| 576 | if (netif_msg_drv(lp)) | 576 | if (netif_msg_drv(lp)) |
| 577 | printk("\n" KERN_ERR | 577 | printk(KERN_ERR |
| 578 | "%s: Memory allocation failed.\n", dev->name); | 578 | "%s: Memory allocation failed.\n", dev->name); |
| 579 | goto free_new_rx_ring; | 579 | goto free_new_rx_ring; |
| 580 | } | 580 | } |
| @@ -583,7 +583,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, | |||
| 583 | GFP_ATOMIC); | 583 | GFP_ATOMIC); |
| 584 | if (!new_skb_list) { | 584 | if (!new_skb_list) { |
| 585 | if (netif_msg_drv(lp)) | 585 | if (netif_msg_drv(lp)) |
| 586 | printk("\n" KERN_ERR | 586 | printk(KERN_ERR |
| 587 | "%s: Memory allocation failed.\n", dev->name); | 587 | "%s: Memory allocation failed.\n", dev->name); |
| 588 | goto free_new_lists; | 588 | goto free_new_lists; |
| 589 | } | 589 | } |
| @@ -1766,38 +1766,38 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1766 | /* Version 0x2623 and 0x2624 */ | 1766 | /* Version 0x2623 and 0x2624 */ |
| 1767 | if (((chip_version + 1) & 0xfffe) == 0x2624) { | 1767 | if (((chip_version + 1) & 0xfffe) == 0x2624) { |
| 1768 | i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ | 1768 | i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ |
| 1769 | printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i); | 1769 | printk(KERN_INFO " tx_start_pt(0x%04x):", i); |
| 1770 | switch (i >> 10) { | 1770 | switch (i >> 10) { |
| 1771 | case 0: | 1771 | case 0: |
| 1772 | printk(" 20 bytes,"); | 1772 | printk(KERN_CONT " 20 bytes,"); |
| 1773 | break; | 1773 | break; |
| 1774 | case 1: | 1774 | case 1: |
| 1775 | printk(" 64 bytes,"); | 1775 | printk(KERN_CONT " 64 bytes,"); |
| 1776 | break; | 1776 | break; |
| 1777 | case 2: | 1777 | case 2: |
| 1778 | printk(" 128 bytes,"); | 1778 | printk(KERN_CONT " 128 bytes,"); |
| 1779 | break; | 1779 | break; |
| 1780 | case 3: | 1780 | case 3: |
| 1781 | printk("~220 bytes,"); | 1781 | printk(KERN_CONT "~220 bytes,"); |
| 1782 | break; | 1782 | break; |
| 1783 | } | 1783 | } |
| 1784 | i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ | 1784 | i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ |
| 1785 | printk(" BCR18(%x):", i & 0xffff); | 1785 | printk(KERN_CONT " BCR18(%x):", i & 0xffff); |
| 1786 | if (i & (1 << 5)) | 1786 | if (i & (1 << 5)) |
| 1787 | printk("BurstWrEn "); | 1787 | printk(KERN_CONT "BurstWrEn "); |
| 1788 | if (i & (1 << 6)) | 1788 | if (i & (1 << 6)) |
| 1789 | printk("BurstRdEn "); | 1789 | printk(KERN_CONT "BurstRdEn "); |
| 1790 | if (i & (1 << 7)) | 1790 | if (i & (1 << 7)) |
| 1791 | printk("DWordIO "); | 1791 | printk(KERN_CONT "DWordIO "); |
| 1792 | if (i & (1 << 11)) | 1792 | if (i & (1 << 11)) |
| 1793 | printk("NoUFlow "); | 1793 | printk(KERN_CONT "NoUFlow "); |
| 1794 | i = a->read_bcr(ioaddr, 25); | 1794 | i = a->read_bcr(ioaddr, 25); |
| 1795 | printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8); | 1795 | printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8); |
| 1796 | i = a->read_bcr(ioaddr, 26); | 1796 | i = a->read_bcr(ioaddr, 26); |
| 1797 | printk(" SRAM_BND=0x%04x,", i << 8); | 1797 | printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8); |
| 1798 | i = a->read_bcr(ioaddr, 27); | 1798 | i = a->read_bcr(ioaddr, 27); |
| 1799 | if (i & (1 << 14)) | 1799 | if (i & (1 << 14)) |
| 1800 | printk("LowLatRx"); | 1800 | printk(KERN_CONT "LowLatRx"); |
| 1801 | } | 1801 | } |
| 1802 | } | 1802 | } |
| 1803 | 1803 | ||
| @@ -1996,7 +1996,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 1996 | &lp->tx_ring_dma_addr); | 1996 | &lp->tx_ring_dma_addr); |
| 1997 | if (lp->tx_ring == NULL) { | 1997 | if (lp->tx_ring == NULL) { |
| 1998 | if (netif_msg_drv(lp)) | 1998 | if (netif_msg_drv(lp)) |
| 1999 | printk("\n" KERN_ERR PFX | 1999 | printk(KERN_ERR PFX |
| 2000 | "%s: Consistent memory allocation failed.\n", | 2000 | "%s: Consistent memory allocation failed.\n", |
| 2001 | name); | 2001 | name); |
| 2002 | return -ENOMEM; | 2002 | return -ENOMEM; |
| @@ -2008,7 +2008,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 2008 | &lp->rx_ring_dma_addr); | 2008 | &lp->rx_ring_dma_addr); |
| 2009 | if (lp->rx_ring == NULL) { | 2009 | if (lp->rx_ring == NULL) { |
| 2010 | if (netif_msg_drv(lp)) | 2010 | if (netif_msg_drv(lp)) |
| 2011 | printk("\n" KERN_ERR PFX | 2011 | printk(KERN_ERR PFX |
| 2012 | "%s: Consistent memory allocation failed.\n", | 2012 | "%s: Consistent memory allocation failed.\n", |
| 2013 | name); | 2013 | name); |
| 2014 | return -ENOMEM; | 2014 | return -ENOMEM; |
| @@ -2018,7 +2018,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 2018 | GFP_ATOMIC); | 2018 | GFP_ATOMIC); |
| 2019 | if (!lp->tx_dma_addr) { | 2019 | if (!lp->tx_dma_addr) { |
| 2020 | if (netif_msg_drv(lp)) | 2020 | if (netif_msg_drv(lp)) |
| 2021 | printk("\n" KERN_ERR PFX | 2021 | printk(KERN_ERR PFX |
| 2022 | "%s: Memory allocation failed.\n", name); | 2022 | "%s: Memory allocation failed.\n", name); |
| 2023 | return -ENOMEM; | 2023 | return -ENOMEM; |
| 2024 | } | 2024 | } |
| @@ -2027,7 +2027,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 2027 | GFP_ATOMIC); | 2027 | GFP_ATOMIC); |
| 2028 | if (!lp->rx_dma_addr) { | 2028 | if (!lp->rx_dma_addr) { |
| 2029 | if (netif_msg_drv(lp)) | 2029 | if (netif_msg_drv(lp)) |
| 2030 | printk("\n" KERN_ERR PFX | 2030 | printk(KERN_ERR PFX |
| 2031 | "%s: Memory allocation failed.\n", name); | 2031 | "%s: Memory allocation failed.\n", name); |
| 2032 | return -ENOMEM; | 2032 | return -ENOMEM; |
| 2033 | } | 2033 | } |
| @@ -2036,7 +2036,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 2036 | GFP_ATOMIC); | 2036 | GFP_ATOMIC); |
| 2037 | if (!lp->tx_skbuff) { | 2037 | if (!lp->tx_skbuff) { |
| 2038 | if (netif_msg_drv(lp)) | 2038 | if (netif_msg_drv(lp)) |
| 2039 | printk("\n" KERN_ERR PFX | 2039 | printk(KERN_ERR PFX |
| 2040 | "%s: Memory allocation failed.\n", name); | 2040 | "%s: Memory allocation failed.\n", name); |
| 2041 | return -ENOMEM; | 2041 | return -ENOMEM; |
| 2042 | } | 2042 | } |
| @@ -2045,7 +2045,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) | |||
| 2045 | GFP_ATOMIC); | 2045 | GFP_ATOMIC); |
| 2046 | if (!lp->rx_skbuff) { | 2046 | if (!lp->rx_skbuff) { |
| 2047 | if (netif_msg_drv(lp)) | 2047 | if (netif_msg_drv(lp)) |
| 2048 | printk("\n" KERN_ERR PFX | 2048 | printk(KERN_ERR PFX |
| 2049 | "%s: Memory allocation failed.\n", name); | 2049 | "%s: Memory allocation failed.\n", name); |
| 2050 | return -ENOMEM; | 2050 | return -ENOMEM; |
| 2051 | } | 2051 | } |
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 61755cbd978e..eda94fcd4065 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
| @@ -928,13 +928,32 @@ static void phy_state_machine(struct work_struct *work) | |||
| 928 | * Otherwise, it's 0, and we're | 928 | * Otherwise, it's 0, and we're |
| 929 | * still waiting for AN */ | 929 | * still waiting for AN */ |
| 930 | if (err > 0) { | 930 | if (err > 0) { |
| 931 | phydev->state = PHY_RUNNING; | 931 | err = phy_read_status(phydev); |
| 932 | if (err) | ||
| 933 | break; | ||
| 934 | |||
| 935 | if (phydev->link) { | ||
| 936 | phydev->state = PHY_RUNNING; | ||
| 937 | netif_carrier_on(phydev->attached_dev); | ||
| 938 | } else | ||
| 939 | phydev->state = PHY_NOLINK; | ||
| 940 | phydev->adjust_link(phydev->attached_dev); | ||
| 932 | } else { | 941 | } else { |
| 933 | phydev->state = PHY_AN; | 942 | phydev->state = PHY_AN; |
| 934 | phydev->link_timeout = PHY_AN_TIMEOUT; | 943 | phydev->link_timeout = PHY_AN_TIMEOUT; |
| 935 | } | 944 | } |
| 936 | } else | 945 | } else { |
| 937 | phydev->state = PHY_RUNNING; | 946 | err = phy_read_status(phydev); |
| 947 | if (err) | ||
| 948 | break; | ||
| 949 | |||
| 950 | if (phydev->link) { | ||
| 951 | phydev->state = PHY_RUNNING; | ||
| 952 | netif_carrier_on(phydev->attached_dev); | ||
| 953 | } else | ||
| 954 | phydev->state = PHY_NOLINK; | ||
| 955 | phydev->adjust_link(phydev->attached_dev); | ||
| 956 | } | ||
| 938 | break; | 957 | break; |
| 939 | } | 958 | } |
| 940 | 959 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index eba937c46376..b10fedd82143 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -134,8 +134,10 @@ int phy_scan_fixups(struct phy_device *phydev) | |||
| 134 | 134 | ||
| 135 | err = fixup->run(phydev); | 135 | err = fixup->run(phydev); |
| 136 | 136 | ||
| 137 | if (err < 0) | 137 | if (err < 0) { |
| 138 | mutex_unlock(&phy_fixup_lock); | ||
| 138 | return err; | 139 | return err; |
| 140 | } | ||
| 139 | } | 141 | } |
| 140 | } | 142 | } |
| 141 | mutex_unlock(&phy_fixup_lock); | 143 | mutex_unlock(&phy_fixup_lock); |
diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 7a62f781fef2..2ca8b0d84ee2 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c | |||
| @@ -270,6 +270,9 @@ static const struct net_device_ops plip_netdev_ops = { | |||
| 270 | .ndo_stop = plip_close, | 270 | .ndo_stop = plip_close, |
| 271 | .ndo_start_xmit = plip_tx_packet, | 271 | .ndo_start_xmit = plip_tx_packet, |
| 272 | .ndo_do_ioctl = plip_ioctl, | 272 | .ndo_do_ioctl = plip_ioctl, |
| 273 | .ndo_change_mtu = eth_change_mtu, | ||
| 274 | .ndo_set_mac_address = eth_mac_addr, | ||
| 275 | .ndo_validate_addr = eth_validate_addr, | ||
| 273 | }; | 276 | }; |
| 274 | 277 | ||
| 275 | /* Entry point of PLIP driver. | 278 | /* Entry point of PLIP driver. |
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 17c116bb332c..6de8399d6dd9 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c | |||
| @@ -356,6 +356,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
| 356 | if (!skb_queue_empty(&ap->rqueue)) | 356 | if (!skb_queue_empty(&ap->rqueue)) |
| 357 | tasklet_schedule(&ap->tsk); | 357 | tasklet_schedule(&ap->tsk); |
| 358 | ap_put(ap); | 358 | ap_put(ap); |
| 359 | tty_unthrottle(tty); | ||
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | static void | 362 | static void |
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index aa3d39f38e22..d2fa2db13586 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c | |||
| @@ -397,6 +397,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, | |||
| 397 | if (!skb_queue_empty(&ap->rqueue)) | 397 | if (!skb_queue_empty(&ap->rqueue)) |
| 398 | tasklet_schedule(&ap->tsk); | 398 | tasklet_schedule(&ap->tsk); |
| 399 | sp_put(ap); | 399 | sp_put(ap); |
| 400 | tty_unthrottle(tty); | ||
| 400 | } | 401 | } |
| 401 | 402 | ||
| 402 | static void | 403 | static void |
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index d1a5fb4d6acb..a3932c9f3406 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c | |||
| @@ -1411,6 +1411,7 @@ static const struct net_device_ops gelic_netdevice_ops = { | |||
| 1411 | .ndo_set_multicast_list = gelic_net_set_multi, | 1411 | .ndo_set_multicast_list = gelic_net_set_multi, |
| 1412 | .ndo_change_mtu = gelic_net_change_mtu, | 1412 | .ndo_change_mtu = gelic_net_change_mtu, |
| 1413 | .ndo_tx_timeout = gelic_net_tx_timeout, | 1413 | .ndo_tx_timeout = gelic_net_tx_timeout, |
| 1414 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1414 | .ndo_validate_addr = eth_validate_addr, | 1415 | .ndo_validate_addr = eth_validate_addr, |
| 1415 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1416 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 1416 | .ndo_poll_controller = gelic_net_poll_controller, | 1417 | .ndo_poll_controller = gelic_net_poll_controller, |
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index b6b3ca9bdb21..6932b08d746b 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c | |||
| @@ -2707,6 +2707,7 @@ static const struct net_device_ops gelic_wl_netdevice_ops = { | |||
| 2707 | .ndo_set_multicast_list = gelic_net_set_multi, | 2707 | .ndo_set_multicast_list = gelic_net_set_multi, |
| 2708 | .ndo_change_mtu = gelic_net_change_mtu, | 2708 | .ndo_change_mtu = gelic_net_change_mtu, |
| 2709 | .ndo_tx_timeout = gelic_net_tx_timeout, | 2709 | .ndo_tx_timeout = gelic_net_tx_timeout, |
| 2710 | .ndo_set_mac_address = eth_mac_addr, | ||
| 2710 | .ndo_validate_addr = eth_validate_addr, | 2711 | .ndo_validate_addr = eth_validate_addr, |
| 2711 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2712 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 2712 | .ndo_poll_controller = gelic_net_poll_controller, | 2713 | .ndo_poll_controller = gelic_net_poll_controller, |
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index bbc6d4d3cc94..3e4b67aaa6ea 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
| @@ -3142,6 +3142,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) | |||
| 3142 | (void __iomem *)port_regs; | 3142 | (void __iomem *)port_regs; |
| 3143 | u32 delay = 10; | 3143 | u32 delay = 10; |
| 3144 | int status = 0; | 3144 | int status = 0; |
| 3145 | unsigned long hw_flags = 0; | ||
| 3145 | 3146 | ||
| 3146 | if(ql_mii_setup(qdev)) | 3147 | if(ql_mii_setup(qdev)) |
| 3147 | return -1; | 3148 | return -1; |
| @@ -3150,7 +3151,8 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) | |||
| 3150 | ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, | 3151 | ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg, |
| 3151 | (ISP_SERIAL_PORT_IF_WE | | 3152 | (ISP_SERIAL_PORT_IF_WE | |
| 3152 | (ISP_SERIAL_PORT_IF_WE << 16))); | 3153 | (ISP_SERIAL_PORT_IF_WE << 16))); |
| 3153 | 3154 | /* Give the PHY time to come out of reset. */ | |
| 3155 | mdelay(100); | ||
| 3154 | qdev->port_link_state = LS_DOWN; | 3156 | qdev->port_link_state = LS_DOWN; |
| 3155 | netif_carrier_off(qdev->ndev); | 3157 | netif_carrier_off(qdev->ndev); |
| 3156 | 3158 | ||
| @@ -3350,7 +3352,9 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) | |||
| 3350 | value = ql_read_page0_reg(qdev, &port_regs->portStatus); | 3352 | value = ql_read_page0_reg(qdev, &port_regs->portStatus); |
| 3351 | if (value & PORT_STATUS_IC) | 3353 | if (value & PORT_STATUS_IC) |
| 3352 | break; | 3354 | break; |
| 3355 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | ||
| 3353 | msleep(500); | 3356 | msleep(500); |
| 3357 | spin_lock_irqsave(&qdev->hw_lock, hw_flags); | ||
| 3354 | } while (--delay); | 3358 | } while (--delay); |
| 3355 | 3359 | ||
| 3356 | if (delay == 0) { | 3360 | if (delay == 0) { |
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 156e02e8905d..6ed5317ab1c0 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
| @@ -1607,6 +1607,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev); | |||
| 1607 | int ql_cam_route_initialize(struct ql_adapter *qdev); | 1607 | int ql_cam_route_initialize(struct ql_adapter *qdev); |
| 1608 | int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); | 1608 | int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); |
| 1609 | int ql_mb_about_fw(struct ql_adapter *qdev); | 1609 | int ql_mb_about_fw(struct ql_adapter *qdev); |
| 1610 | void ql_link_on(struct ql_adapter *qdev); | ||
| 1611 | void ql_link_off(struct ql_adapter *qdev); | ||
| 1610 | 1612 | ||
| 1611 | #if 1 | 1613 | #if 1 |
| 1612 | #define QL_ALL_DUMP | 1614 | #define QL_ALL_DUMP |
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 37c99fe79770..eb6a9ee640ed 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c | |||
| @@ -59,7 +59,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) | |||
| 59 | cqicb->pkt_delay = | 59 | cqicb->pkt_delay = |
| 60 | cpu_to_le16(qdev->tx_max_coalesced_frames); | 60 | cpu_to_le16(qdev->tx_max_coalesced_frames); |
| 61 | cqicb->flags = FLAGS_LI; | 61 | cqicb->flags = FLAGS_LI; |
| 62 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), | 62 | status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), |
| 63 | CFG_LCQ, rx_ring->cq_id); | 63 | CFG_LCQ, rx_ring->cq_id); |
| 64 | if (status) { | 64 | if (status) { |
| 65 | QPRINTK(qdev, IFUP, ERR, | 65 | QPRINTK(qdev, IFUP, ERR, |
| @@ -82,7 +82,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) | |||
| 82 | cqicb->pkt_delay = | 82 | cqicb->pkt_delay = |
| 83 | cpu_to_le16(qdev->rx_max_coalesced_frames); | 83 | cpu_to_le16(qdev->rx_max_coalesced_frames); |
| 84 | cqicb->flags = FLAGS_LI; | 84 | cqicb->flags = FLAGS_LI; |
| 85 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), | 85 | status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), |
| 86 | CFG_LCQ, rx_ring->cq_id); | 86 | CFG_LCQ, rx_ring->cq_id); |
| 87 | if (status) { | 87 | if (status) { |
| 88 | QPRINTK(qdev, IFUP, ERR, | 88 | QPRINTK(qdev, IFUP, ERR, |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 90d1f76c0e8b..5768af17f168 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
| @@ -214,6 +214,10 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, | |||
| 214 | return -ENOMEM; | 214 | return -ENOMEM; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | status = ql_sem_spinlock(qdev, SEM_ICB_MASK); | ||
| 218 | if (status) | ||
| 219 | return status; | ||
| 220 | |||
| 217 | status = ql_wait_cfg(qdev, bit); | 221 | status = ql_wait_cfg(qdev, bit); |
| 218 | if (status) { | 222 | if (status) { |
| 219 | QPRINTK(qdev, IFUP, ERR, | 223 | QPRINTK(qdev, IFUP, ERR, |
| @@ -221,12 +225,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, | |||
| 221 | goto exit; | 225 | goto exit; |
| 222 | } | 226 | } |
| 223 | 227 | ||
| 224 | status = ql_sem_spinlock(qdev, SEM_ICB_MASK); | ||
| 225 | if (status) | ||
| 226 | goto exit; | ||
| 227 | ql_write32(qdev, ICB_L, (u32) map); | 228 | ql_write32(qdev, ICB_L, (u32) map); |
| 228 | ql_write32(qdev, ICB_H, (u32) (map >> 32)); | 229 | ql_write32(qdev, ICB_H, (u32) (map >> 32)); |
| 229 | ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ | ||
| 230 | 230 | ||
| 231 | mask = CFG_Q_MASK | (bit << 16); | 231 | mask = CFG_Q_MASK | (bit << 16); |
| 232 | value = bit | (q_id << CFG_Q_SHIFT); | 232 | value = bit | (q_id << CFG_Q_SHIFT); |
| @@ -237,6 +237,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, | |||
| 237 | */ | 237 | */ |
| 238 | status = ql_wait_cfg(qdev, bit); | 238 | status = ql_wait_cfg(qdev, bit); |
| 239 | exit: | 239 | exit: |
| 240 | ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ | ||
| 240 | pci_unmap_single(qdev->pdev, map, size, direction); | 241 | pci_unmap_single(qdev->pdev, map, size, direction); |
| 241 | return status; | 242 | return status; |
| 242 | } | 243 | } |
| @@ -412,6 +413,57 @@ exit: | |||
| 412 | return status; | 413 | return status; |
| 413 | } | 414 | } |
| 414 | 415 | ||
| 416 | /* Set or clear MAC address in hardware. We sometimes | ||
| 417 | * have to clear it to prevent wrong frame routing | ||
| 418 | * especially in a bonding environment. | ||
| 419 | */ | ||
| 420 | static int ql_set_mac_addr(struct ql_adapter *qdev, int set) | ||
| 421 | { | ||
| 422 | int status; | ||
| 423 | char zero_mac_addr[ETH_ALEN]; | ||
| 424 | char *addr; | ||
| 425 | |||
| 426 | if (set) { | ||
| 427 | addr = &qdev->ndev->dev_addr[0]; | ||
| 428 | QPRINTK(qdev, IFUP, DEBUG, | ||
| 429 | "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 430 | addr[0], addr[1], addr[2], addr[3], | ||
| 431 | addr[4], addr[5]); | ||
| 432 | } else { | ||
| 433 | memset(zero_mac_addr, 0, ETH_ALEN); | ||
| 434 | addr = &zero_mac_addr[0]; | ||
| 435 | QPRINTK(qdev, IFUP, DEBUG, | ||
| 436 | "Clearing MAC address on %s\n", | ||
| 437 | qdev->ndev->name); | ||
| 438 | } | ||
| 439 | status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); | ||
| 440 | if (status) | ||
| 441 | return status; | ||
| 442 | status = ql_set_mac_addr_reg(qdev, (u8 *) addr, | ||
| 443 | MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); | ||
| 444 | ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); | ||
| 445 | if (status) | ||
| 446 | QPRINTK(qdev, IFUP, ERR, "Failed to init mac " | ||
| 447 | "address.\n"); | ||
| 448 | return status; | ||
| 449 | } | ||
| 450 | |||
| 451 | void ql_link_on(struct ql_adapter *qdev) | ||
| 452 | { | ||
| 453 | QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n", | ||
| 454 | qdev->ndev->name); | ||
| 455 | netif_carrier_on(qdev->ndev); | ||
| 456 | ql_set_mac_addr(qdev, 1); | ||
| 457 | } | ||
| 458 | |||
| 459 | void ql_link_off(struct ql_adapter *qdev) | ||
| 460 | { | ||
| 461 | QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n", | ||
| 462 | qdev->ndev->name); | ||
| 463 | netif_carrier_off(qdev->ndev); | ||
| 464 | ql_set_mac_addr(qdev, 0); | ||
| 465 | } | ||
| 466 | |||
| 415 | /* Get a specific frame routing value from the CAM. | 467 | /* Get a specific frame routing value from the CAM. |
| 416 | * Used for debug and reg dump. | 468 | * Used for debug and reg dump. |
| 417 | */ | 469 | */ |
| @@ -1628,7 +1680,7 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, | |||
| 1628 | tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; | 1680 | tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; |
| 1629 | tx_ring_desc = &tx_ring->q[mac_rsp->tid]; | 1681 | tx_ring_desc = &tx_ring->q[mac_rsp->tid]; |
| 1630 | ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); | 1682 | ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); |
| 1631 | qdev->stats.tx_bytes += tx_ring_desc->map_cnt; | 1683 | qdev->stats.tx_bytes += (tx_ring_desc->skb)->len; |
| 1632 | qdev->stats.tx_packets++; | 1684 | qdev->stats.tx_packets++; |
| 1633 | dev_kfree_skb(tx_ring_desc->skb); | 1685 | dev_kfree_skb(tx_ring_desc->skb); |
| 1634 | tx_ring_desc->skb = NULL; | 1686 | tx_ring_desc->skb = NULL; |
| @@ -1660,13 +1712,13 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, | |||
| 1660 | /* Fire up a handler to reset the MPI processor. */ | 1712 | /* Fire up a handler to reset the MPI processor. */ |
| 1661 | void ql_queue_fw_error(struct ql_adapter *qdev) | 1713 | void ql_queue_fw_error(struct ql_adapter *qdev) |
| 1662 | { | 1714 | { |
| 1663 | netif_carrier_off(qdev->ndev); | 1715 | ql_link_off(qdev); |
| 1664 | queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); | 1716 | queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); |
| 1665 | } | 1717 | } |
| 1666 | 1718 | ||
| 1667 | void ql_queue_asic_error(struct ql_adapter *qdev) | 1719 | void ql_queue_asic_error(struct ql_adapter *qdev) |
| 1668 | { | 1720 | { |
| 1669 | netif_carrier_off(qdev->ndev); | 1721 | ql_link_off(qdev); |
| 1670 | ql_disable_interrupts(qdev); | 1722 | ql_disable_interrupts(qdev); |
| 1671 | /* Clear adapter up bit to signal the recovery | 1723 | /* Clear adapter up bit to signal the recovery |
| 1672 | * process that it shouldn't kill the reset worker | 1724 | * process that it shouldn't kill the reset worker |
| @@ -2104,7 +2156,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) | |||
| 2104 | } | 2156 | } |
| 2105 | tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; | 2157 | tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; |
| 2106 | mac_iocb_ptr = tx_ring_desc->queue_entry; | 2158 | mac_iocb_ptr = tx_ring_desc->queue_entry; |
| 2107 | memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr)); | 2159 | memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr)); |
| 2108 | 2160 | ||
| 2109 | mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; | 2161 | mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; |
| 2110 | mac_iocb_ptr->tid = tx_ring_desc->index; | 2162 | mac_iocb_ptr->tid = tx_ring_desc->index; |
| @@ -2743,7 +2795,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) | |||
| 2743 | 2795 | ||
| 2744 | ql_init_tx_ring(qdev, tx_ring); | 2796 | ql_init_tx_ring(qdev, tx_ring); |
| 2745 | 2797 | ||
| 2746 | err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ, | 2798 | err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ, |
| 2747 | (u16) tx_ring->wq_id); | 2799 | (u16) tx_ring->wq_id); |
| 2748 | if (err) { | 2800 | if (err) { |
| 2749 | QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); | 2801 | QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); |
| @@ -3008,7 +3060,7 @@ static int ql_start_rss(struct ql_adapter *qdev) | |||
| 3008 | int i; | 3060 | int i; |
| 3009 | u8 *hash_id = (u8 *) ricb->hash_cq_id; | 3061 | u8 *hash_id = (u8 *) ricb->hash_cq_id; |
| 3010 | 3062 | ||
| 3011 | memset((void *)ricb, 0, sizeof(ricb)); | 3063 | memset((void *)ricb, 0, sizeof(*ricb)); |
| 3012 | 3064 | ||
| 3013 | ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; | 3065 | ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; |
| 3014 | ricb->flags = | 3066 | ricb->flags = |
| @@ -3030,7 +3082,7 @@ static int ql_start_rss(struct ql_adapter *qdev) | |||
| 3030 | 3082 | ||
| 3031 | QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); | 3083 | QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); |
| 3032 | 3084 | ||
| 3033 | status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); | 3085 | status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0); |
| 3034 | if (status) { | 3086 | if (status) { |
| 3035 | QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); | 3087 | QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); |
| 3036 | return status; | 3088 | return status; |
| @@ -3039,25 +3091,40 @@ static int ql_start_rss(struct ql_adapter *qdev) | |||
| 3039 | return status; | 3091 | return status; |
| 3040 | } | 3092 | } |
| 3041 | 3093 | ||
| 3042 | /* Initialize the frame-to-queue routing. */ | 3094 | static int ql_clear_routing_entries(struct ql_adapter *qdev) |
| 3043 | static int ql_route_initialize(struct ql_adapter *qdev) | ||
| 3044 | { | 3095 | { |
| 3045 | int status = 0; | 3096 | int i, status = 0; |
| 3046 | int i; | ||
| 3047 | 3097 | ||
| 3048 | status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); | 3098 | status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); |
| 3049 | if (status) | 3099 | if (status) |
| 3050 | return status; | 3100 | return status; |
| 3051 | |||
| 3052 | /* Clear all the entries in the routing table. */ | 3101 | /* Clear all the entries in the routing table. */ |
| 3053 | for (i = 0; i < 16; i++) { | 3102 | for (i = 0; i < 16; i++) { |
| 3054 | status = ql_set_routing_reg(qdev, i, 0, 0); | 3103 | status = ql_set_routing_reg(qdev, i, 0, 0); |
| 3055 | if (status) { | 3104 | if (status) { |
| 3056 | QPRINTK(qdev, IFUP, ERR, | 3105 | QPRINTK(qdev, IFUP, ERR, |
| 3057 | "Failed to init routing register for CAM packets.\n"); | 3106 | "Failed to init routing register for CAM " |
| 3058 | goto exit; | 3107 | "packets.\n"); |
| 3108 | break; | ||
| 3059 | } | 3109 | } |
| 3060 | } | 3110 | } |
| 3111 | ql_sem_unlock(qdev, SEM_RT_IDX_MASK); | ||
| 3112 | return status; | ||
| 3113 | } | ||
| 3114 | |||
| 3115 | /* Initialize the frame-to-queue routing. */ | ||
| 3116 | static int ql_route_initialize(struct ql_adapter *qdev) | ||
| 3117 | { | ||
| 3118 | int status = 0; | ||
| 3119 | |||
| 3120 | status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); | ||
| 3121 | if (status) | ||
| 3122 | return status; | ||
| 3123 | |||
| 3124 | /* Clear all the entries in the routing table. */ | ||
| 3125 | status = ql_clear_routing_entries(qdev); | ||
| 3126 | if (status) | ||
| 3127 | goto exit; | ||
| 3061 | 3128 | ||
| 3062 | status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); | 3129 | status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); |
| 3063 | if (status) { | 3130 | if (status) { |
| @@ -3096,14 +3163,15 @@ exit: | |||
| 3096 | 3163 | ||
| 3097 | int ql_cam_route_initialize(struct ql_adapter *qdev) | 3164 | int ql_cam_route_initialize(struct ql_adapter *qdev) |
| 3098 | { | 3165 | { |
| 3099 | int status; | 3166 | int status, set; |
| 3100 | 3167 | ||
| 3101 | status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); | 3168 | /* If check if the link is up and use to |
| 3102 | if (status) | 3169 | * determine if we are setting or clearing |
| 3103 | return status; | 3170 | * the MAC address in the CAM. |
| 3104 | status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, | 3171 | */ |
| 3105 | MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); | 3172 | set = ql_read32(qdev, STS); |
| 3106 | ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); | 3173 | set &= qdev->port_link_up; |
| 3174 | status = ql_set_mac_addr(qdev, set); | ||
| 3107 | if (status) { | 3175 | if (status) { |
| 3108 | QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); | 3176 | QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); |
| 3109 | return status; | 3177 | return status; |
| @@ -3210,9 +3278,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev) | |||
| 3210 | { | 3278 | { |
| 3211 | u32 value; | 3279 | u32 value; |
| 3212 | int status = 0; | 3280 | int status = 0; |
| 3213 | unsigned long end_jiffies = jiffies + | 3281 | unsigned long end_jiffies; |
| 3214 | max((unsigned long)1, usecs_to_jiffies(30)); | ||
| 3215 | 3282 | ||
| 3283 | /* Clear all the entries in the routing table. */ | ||
| 3284 | status = ql_clear_routing_entries(qdev); | ||
| 3285 | if (status) { | ||
| 3286 | QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n"); | ||
| 3287 | return status; | ||
| 3288 | } | ||
| 3289 | |||
| 3290 | end_jiffies = jiffies + | ||
| 3291 | max((unsigned long)1, usecs_to_jiffies(30)); | ||
| 3216 | ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); | 3292 | ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); |
| 3217 | 3293 | ||
| 3218 | do { | 3294 | do { |
| @@ -3252,7 +3328,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) | |||
| 3252 | int i, status = 0; | 3328 | int i, status = 0; |
| 3253 | struct rx_ring *rx_ring; | 3329 | struct rx_ring *rx_ring; |
| 3254 | 3330 | ||
| 3255 | netif_carrier_off(qdev->ndev); | 3331 | ql_link_off(qdev); |
| 3256 | 3332 | ||
| 3257 | /* Don't kill the reset worker thread if we | 3333 | /* Don't kill the reset worker thread if we |
| 3258 | * are in the process of recovery. | 3334 | * are in the process of recovery. |
| @@ -3319,8 +3395,12 @@ static int ql_adapter_up(struct ql_adapter *qdev) | |||
| 3319 | } | 3395 | } |
| 3320 | set_bit(QL_ADAPTER_UP, &qdev->flags); | 3396 | set_bit(QL_ADAPTER_UP, &qdev->flags); |
| 3321 | ql_alloc_rx_buffers(qdev); | 3397 | ql_alloc_rx_buffers(qdev); |
| 3322 | if ((ql_read32(qdev, STS) & qdev->port_init)) | 3398 | /* If the port is initialized and the |
| 3323 | netif_carrier_on(qdev->ndev); | 3399 | * link is up the turn on the carrier. |
| 3400 | */ | ||
| 3401 | if ((ql_read32(qdev, STS) & qdev->port_init) && | ||
| 3402 | (ql_read32(qdev, STS) & qdev->port_link_up)) | ||
| 3403 | ql_link_on(qdev); | ||
| 3324 | ql_enable_interrupts(qdev); | 3404 | ql_enable_interrupts(qdev); |
| 3325 | ql_enable_all_completion_interrupts(qdev); | 3405 | ql_enable_all_completion_interrupts(qdev); |
| 3326 | netif_tx_start_all_queues(qdev->ndev); | 3406 | netif_tx_start_all_queues(qdev->ndev); |
| @@ -3346,11 +3426,6 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev) | |||
| 3346 | return -ENOMEM; | 3426 | return -ENOMEM; |
| 3347 | } | 3427 | } |
| 3348 | status = ql_request_irq(qdev); | 3428 | status = ql_request_irq(qdev); |
| 3349 | if (status) | ||
| 3350 | goto err_irq; | ||
| 3351 | return status; | ||
| 3352 | err_irq: | ||
| 3353 | ql_free_mem_resources(qdev); | ||
| 3354 | return status; | 3429 | return status; |
| 3355 | } | 3430 | } |
| 3356 | 3431 | ||
| @@ -3414,7 +3489,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) | |||
| 3414 | 3489 | ||
| 3415 | for (i = 0; i < qdev->tx_ring_count; i++) { | 3490 | for (i = 0; i < qdev->tx_ring_count; i++) { |
| 3416 | tx_ring = &qdev->tx_ring[i]; | 3491 | tx_ring = &qdev->tx_ring[i]; |
| 3417 | memset((void *)tx_ring, 0, sizeof(tx_ring)); | 3492 | memset((void *)tx_ring, 0, sizeof(*tx_ring)); |
| 3418 | tx_ring->qdev = qdev; | 3493 | tx_ring->qdev = qdev; |
| 3419 | tx_ring->wq_id = i; | 3494 | tx_ring->wq_id = i; |
| 3420 | tx_ring->wq_len = qdev->tx_ring_size; | 3495 | tx_ring->wq_len = qdev->tx_ring_size; |
| @@ -3430,7 +3505,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) | |||
| 3430 | 3505 | ||
| 3431 | for (i = 0; i < qdev->rx_ring_count; i++) { | 3506 | for (i = 0; i < qdev->rx_ring_count; i++) { |
| 3432 | rx_ring = &qdev->rx_ring[i]; | 3507 | rx_ring = &qdev->rx_ring[i]; |
| 3433 | memset((void *)rx_ring, 0, sizeof(rx_ring)); | 3508 | memset((void *)rx_ring, 0, sizeof(*rx_ring)); |
| 3434 | rx_ring->qdev = qdev; | 3509 | rx_ring->qdev = qdev; |
| 3435 | rx_ring->cq_id = i; | 3510 | rx_ring->cq_id = i; |
| 3436 | rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ | 3511 | rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ |
| @@ -3789,7 +3864,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
| 3789 | int pos, err = 0; | 3864 | int pos, err = 0; |
| 3790 | u16 val16; | 3865 | u16 val16; |
| 3791 | 3866 | ||
| 3792 | memset((void *)qdev, 0, sizeof(qdev)); | 3867 | memset((void *)qdev, 0, sizeof(*qdev)); |
| 3793 | err = pci_enable_device(pdev); | 3868 | err = pci_enable_device(pdev); |
| 3794 | if (err) { | 3869 | if (err) { |
| 3795 | dev_err(&pdev->dev, "PCI device enable failed.\n"); | 3870 | dev_err(&pdev->dev, "PCI device enable failed.\n"); |
| @@ -3976,7 +4051,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, | |||
| 3976 | pci_disable_device(pdev); | 4051 | pci_disable_device(pdev); |
| 3977 | return err; | 4052 | return err; |
| 3978 | } | 4053 | } |
| 3979 | netif_carrier_off(ndev); | 4054 | ql_link_off(qdev); |
| 3980 | ql_display_dev_info(ndev); | 4055 | ql_display_dev_info(ndev); |
| 3981 | cards_found++; | 4056 | cards_found++; |
| 3982 | return 0; | 4057 | return 0; |
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 71afbf8b9c50..6685bd97da91 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
| @@ -238,7 +238,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
| 238 | &qdev->mpi_port_cfg_work, 0); | 238 | &qdev->mpi_port_cfg_work, 0); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | netif_carrier_on(qdev->ndev); | 241 | ql_link_on(qdev); |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) | 244 | static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) |
| @@ -251,7 +251,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
| 251 | if (status) | 251 | if (status) |
| 252 | QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); | 252 | QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); |
| 253 | 253 | ||
| 254 | netif_carrier_off(qdev->ndev); | 254 | ql_link_off(qdev); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) | 257 | static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) |
| @@ -849,7 +849,7 @@ void ql_mpi_idc_work(struct work_struct *work) | |||
| 849 | case MB_CMD_PORT_RESET: | 849 | case MB_CMD_PORT_RESET: |
| 850 | case MB_CMD_SET_PORT_CFG: | 850 | case MB_CMD_SET_PORT_CFG: |
| 851 | case MB_CMD_STOP_FW: | 851 | case MB_CMD_STOP_FW: |
| 852 | netif_carrier_off(qdev->ndev); | 852 | ql_link_off(qdev); |
| 853 | /* Signal the resulting link up AEN | 853 | /* Signal the resulting link up AEN |
| 854 | * that the frame routing and mac addr | 854 | * that the frame routing and mac addr |
| 855 | * needs to be set. | 855 | * needs to be set. |
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index ed63d23a6452..961b5397a531 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
| @@ -49,8 +49,8 @@ | |||
| 49 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
| 50 | 50 | ||
| 51 | #define DRV_NAME "r6040" | 51 | #define DRV_NAME "r6040" |
| 52 | #define DRV_VERSION "0.23" | 52 | #define DRV_VERSION "0.24" |
| 53 | #define DRV_RELDATE "05May2009" | 53 | #define DRV_RELDATE "08Jul2009" |
| 54 | 54 | ||
| 55 | /* PHY CHIP Address */ | 55 | /* PHY CHIP Address */ |
| 56 | #define PHY1_ADDR 1 /* For MAC1 */ | 56 | #define PHY1_ADDR 1 /* For MAC1 */ |
| @@ -704,8 +704,11 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) | |||
| 704 | /* Read MISR status and clear */ | 704 | /* Read MISR status and clear */ |
| 705 | status = ioread16(ioaddr + MISR); | 705 | status = ioread16(ioaddr + MISR); |
| 706 | 706 | ||
| 707 | if (status == 0x0000 || status == 0xffff) | 707 | if (status == 0x0000 || status == 0xffff) { |
| 708 | /* Restore RDC MAC interrupt */ | ||
| 709 | iowrite16(misr, ioaddr + MIER); | ||
| 708 | return IRQ_NONE; | 710 | return IRQ_NONE; |
| 711 | } | ||
| 709 | 712 | ||
| 710 | /* RX interrupt request */ | 713 | /* RX interrupt request */ |
| 711 | if (status & RX_INTS) { | 714 | if (status & RX_INTS) { |
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 341882f959f3..a2d82ddb3b4d 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c | |||
| @@ -865,8 +865,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) | |||
| 865 | struct sh_eth_private *mdp = netdev_priv(ndev); | 865 | struct sh_eth_private *mdp = netdev_priv(ndev); |
| 866 | struct sh_eth_cpu_data *cd = mdp->cd; | 866 | struct sh_eth_cpu_data *cd = mdp->cd; |
| 867 | irqreturn_t ret = IRQ_NONE; | 867 | irqreturn_t ret = IRQ_NONE; |
| 868 | u32 ioaddr, boguscnt = RX_RING_SIZE; | 868 | u32 ioaddr, intr_status = 0; |
| 869 | u32 intr_status = 0; | ||
| 870 | 869 | ||
| 871 | ioaddr = ndev->base_addr; | 870 | ioaddr = ndev->base_addr; |
| 872 | spin_lock(&mdp->lock); | 871 | spin_lock(&mdp->lock); |
| @@ -901,12 +900,6 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) | |||
| 901 | if (intr_status & cd->eesr_err_check) | 900 | if (intr_status & cd->eesr_err_check) |
| 902 | sh_eth_error(ndev, intr_status); | 901 | sh_eth_error(ndev, intr_status); |
| 903 | 902 | ||
| 904 | if (--boguscnt < 0) { | ||
| 905 | printk(KERN_WARNING | ||
| 906 | "%s: Too much work at interrupt, status=0x%4.4x.\n", | ||
| 907 | ndev->name, intr_status); | ||
| 908 | } | ||
| 909 | |||
| 910 | other_irq: | 903 | other_irq: |
| 911 | spin_unlock(&mdp->lock); | 904 | spin_unlock(&mdp->lock); |
| 912 | 905 | ||
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7681d28c53d7..daf961ab68bc 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -2495,7 +2495,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) | |||
| 2495 | if (likely(status >> 16 == (status & 0xffff))) { | 2495 | if (likely(status >> 16 == (status & 0xffff))) { |
| 2496 | skb = sky2->rx_ring[sky2->rx_next].skb; | 2496 | skb = sky2->rx_ring[sky2->rx_next].skb; |
| 2497 | skb->ip_summed = CHECKSUM_COMPLETE; | 2497 | skb->ip_summed = CHECKSUM_COMPLETE; |
| 2498 | skb->csum = status & 0xffff; | 2498 | skb->csum = le16_to_cpu(status); |
| 2499 | } else { | 2499 | } else { |
| 2500 | printk(KERN_NOTICE PFX "%s: hardware receive " | 2500 | printk(KERN_NOTICE PFX "%s: hardware receive " |
| 2501 | "checksum problem (status = %#x)\n", | 2501 | "checksum problem (status = %#x)\n", |
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index fdcbaf8dfa73..1c70e999cc50 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
| @@ -1774,6 +1774,7 @@ static const struct net_device_ops smc_netdev_ops = { | |||
| 1774 | .ndo_start_xmit = smc_hard_start_xmit, | 1774 | .ndo_start_xmit = smc_hard_start_xmit, |
| 1775 | .ndo_tx_timeout = smc_timeout, | 1775 | .ndo_tx_timeout = smc_timeout, |
| 1776 | .ndo_set_multicast_list = smc_set_multicast_list, | 1776 | .ndo_set_multicast_list = smc_set_multicast_list, |
| 1777 | .ndo_change_mtu = eth_change_mtu, | ||
| 1777 | .ndo_validate_addr = eth_validate_addr, | 1778 | .ndo_validate_addr = eth_validate_addr, |
| 1778 | .ndo_set_mac_address = eth_mac_addr, | 1779 | .ndo_set_mac_address = eth_mac_addr, |
| 1779 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1780 | #ifdef CONFIG_NET_POLL_CONTROLLER |
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b60639bd181b..94b6d2658ddc 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
| @@ -1779,6 +1779,7 @@ static const struct net_device_ops smsc911x_netdev_ops = { | |||
| 1779 | .ndo_get_stats = smsc911x_get_stats, | 1779 | .ndo_get_stats = smsc911x_get_stats, |
| 1780 | .ndo_set_multicast_list = smsc911x_set_multicast_list, | 1780 | .ndo_set_multicast_list = smsc911x_set_multicast_list, |
| 1781 | .ndo_do_ioctl = smsc911x_do_ioctl, | 1781 | .ndo_do_ioctl = smsc911x_do_ioctl, |
| 1782 | .ndo_change_mtu = eth_change_mtu, | ||
| 1782 | .ndo_validate_addr = eth_validate_addr, | 1783 | .ndo_validate_addr = eth_validate_addr, |
| 1783 | .ndo_set_mac_address = smsc911x_set_mac_address, | 1784 | .ndo_set_mac_address = smsc911x_set_mac_address, |
| 1784 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1785 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| @@ -1938,7 +1939,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) | |||
| 1938 | if (!res) | 1939 | if (!res) |
| 1939 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1940 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1940 | 1941 | ||
| 1941 | release_mem_region(res->start, res->end - res->start); | 1942 | release_mem_region(res->start, resource_size(res)); |
| 1942 | 1943 | ||
| 1943 | iounmap(pdata->ioaddr); | 1944 | iounmap(pdata->ioaddr); |
| 1944 | 1945 | ||
| @@ -1976,7 +1977,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
| 1976 | retval = -ENODEV; | 1977 | retval = -ENODEV; |
| 1977 | goto out_0; | 1978 | goto out_0; |
| 1978 | } | 1979 | } |
| 1979 | res_size = res->end - res->start + 1; | 1980 | res_size = resource_size(res); |
| 1980 | 1981 | ||
| 1981 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1982 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 1982 | if (!irq_res) { | 1983 | if (!irq_res) { |
| @@ -2104,7 +2105,7 @@ out_unmap_io_3: | |||
| 2104 | out_free_netdev_2: | 2105 | out_free_netdev_2: |
| 2105 | free_netdev(dev); | 2106 | free_netdev(dev); |
| 2106 | out_release_io_1: | 2107 | out_release_io_1: |
| 2107 | release_mem_region(res->start, res->end - res->start); | 2108 | release_mem_region(res->start, resource_size(res)); |
| 2108 | out_0: | 2109 | out_0: |
| 2109 | return retval; | 2110 | return retval; |
| 2110 | } | 2111 | } |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 838cce8b8fff..669253c7bd41 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
| @@ -180,7 +180,7 @@ static int full_duplex[MAX_UNITS] = {0, }; | |||
| 180 | /* These identify the driver base version and may not be removed. */ | 180 | /* These identify the driver base version and may not be removed. */ |
| 181 | static const char version[] __devinitconst = | 181 | static const char version[] __devinitconst = |
| 182 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" | 182 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" |
| 183 | KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; | 183 | " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; |
| 184 | 184 | ||
| 185 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); | 185 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); |
| 186 | MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); | 186 | MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); |
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 545f81b34ad7..d1521c3875b2 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c | |||
| @@ -1698,13 +1698,13 @@ static int netdev_close(struct net_device *dev) | |||
| 1698 | 1698 | ||
| 1699 | #ifdef __i386__ | 1699 | #ifdef __i386__ |
| 1700 | if (netif_msg_hw(np)) { | 1700 | if (netif_msg_hw(np)) { |
| 1701 | printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", | 1701 | printk(KERN_DEBUG " Tx ring at %8.8x:\n", |
| 1702 | (int)(np->tx_ring_dma)); | 1702 | (int)(np->tx_ring_dma)); |
| 1703 | for (i = 0; i < TX_RING_SIZE; i++) | 1703 | for (i = 0; i < TX_RING_SIZE; i++) |
| 1704 | printk(" #%d desc. %4.4x %8.8x %8.8x.\n", | 1704 | printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n", |
| 1705 | i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr, | 1705 | i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr, |
| 1706 | np->tx_ring[i].frag[0].length); | 1706 | np->tx_ring[i].frag[0].length); |
| 1707 | printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", | 1707 | printk(KERN_DEBUG " Rx ring %8.8x:\n", |
| 1708 | (int)(np->rx_ring_dma)); | 1708 | (int)(np->rx_ring_dma)); |
| 1709 | for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) { | 1709 | for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) { |
| 1710 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", | 1710 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", |
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index a82fb2aca4cb..f1e5e4542c2a 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c | |||
| @@ -1016,7 +1016,9 @@ static const struct net_device_ops vnet_ops = { | |||
| 1016 | .ndo_open = vnet_open, | 1016 | .ndo_open = vnet_open, |
| 1017 | .ndo_stop = vnet_close, | 1017 | .ndo_stop = vnet_close, |
| 1018 | .ndo_set_multicast_list = vnet_set_rx_mode, | 1018 | .ndo_set_multicast_list = vnet_set_rx_mode, |
| 1019 | .ndo_change_mtu = eth_change_mtu, | ||
| 1019 | .ndo_set_mac_address = vnet_set_mac_addr, | 1020 | .ndo_set_mac_address = vnet_set_mac_addr, |
| 1021 | .ndo_validate_addr = eth_validate_addr, | ||
| 1020 | .ndo_tx_timeout = vnet_tx_timeout, | 1022 | .ndo_tx_timeout = vnet_tx_timeout, |
| 1021 | .ndo_change_mtu = vnet_change_mtu, | 1023 | .ndo_change_mtu = vnet_change_mtu, |
| 1022 | .ndo_start_xmit = vnet_start_xmit, | 1024 | .ndo_start_xmit = vnet_start_xmit, |
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 0f78f99f9b20..7030bd5e9848 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c | |||
| @@ -1132,7 +1132,9 @@ static int tsi108_get_mac(struct net_device *dev) | |||
| 1132 | } | 1132 | } |
| 1133 | 1133 | ||
| 1134 | if (!is_valid_ether_addr(dev->dev_addr)) { | 1134 | if (!is_valid_ether_addr(dev->dev_addr)) { |
| 1135 | printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2); | 1135 | printk(KERN_ERR |
| 1136 | "%s: Invalid MAC address. word1: %08x, word2: %08x\n", | ||
| 1137 | dev->name, word1, word2); | ||
| 1136 | return -EINVAL; | 1138 | return -EINVAL; |
| 1137 | } | 1139 | } |
| 1138 | 1140 | ||
| @@ -1201,8 +1203,8 @@ static void tsi108_set_rx_mode(struct net_device *dev) | |||
| 1201 | __set_bit(hash, &data->mc_hash[0]); | 1203 | __set_bit(hash, &data->mc_hash[0]); |
| 1202 | } else { | 1204 | } else { |
| 1203 | printk(KERN_ERR | 1205 | printk(KERN_ERR |
| 1204 | "%s: got multicast address of length %d " | 1206 | "%s: got multicast address of length %d instead of 6.\n", |
| 1205 | "instead of 6.\n", dev->name, | 1207 | dev->name, |
| 1206 | mc->dmi_addrlen); | 1208 | mc->dmi_addrlen); |
| 1207 | } | 1209 | } |
| 1208 | 1210 | ||
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 81f054dbb88d..ef49744a5085 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c | |||
| @@ -944,9 +944,10 @@ static void de_set_media (struct de_private *de) | |||
| 944 | macmode &= ~FullDuplex; | 944 | macmode &= ~FullDuplex; |
| 945 | 945 | ||
| 946 | if (netif_msg_link(de)) { | 946 | if (netif_msg_link(de)) { |
| 947 | printk(KERN_INFO "%s: set link %s\n" | 947 | printk(KERN_INFO |
| 948 | KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" | 948 | "%s: set link %s\n" |
| 949 | KERN_INFO "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", | 949 | "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" |
| 950 | "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", | ||
| 950 | de->dev->name, media_name[media], | 951 | de->dev->name, media_name[media], |
| 951 | de->dev->name, dr32(MacMode), dr32(SIAStatus), | 952 | de->dev->name, dr32(MacMode), dr32(SIAStatus), |
| 952 | dr32(CSR13), dr32(CSR14), dr32(CSR15), | 953 | dr32(CSR13), dr32(CSR14), dr32(CSR15), |
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 2abb5d3becc6..99a63649f4fc 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c | |||
| @@ -570,16 +570,18 @@ static void tulip_tx_timeout(struct net_device *dev) | |||
| 570 | (unsigned int)tp->rx_ring[i].buffer2, | 570 | (unsigned int)tp->rx_ring[i].buffer2, |
| 571 | buf[0], buf[1], buf[2]); | 571 | buf[0], buf[1], buf[2]); |
| 572 | for (j = 0; buf[j] != 0xee && j < 1600; j++) | 572 | for (j = 0; buf[j] != 0xee && j < 1600; j++) |
| 573 | if (j < 100) printk(" %2.2x", buf[j]); | 573 | if (j < 100) |
| 574 | printk(" j=%d.\n", j); | 574 | printk(KERN_CONT " %2.2x", buf[j]); |
| 575 | printk(KERN_CONT " j=%d.\n", j); | ||
| 575 | } | 576 | } |
| 576 | printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); | 577 | printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); |
| 577 | for (i = 0; i < RX_RING_SIZE; i++) | 578 | for (i = 0; i < RX_RING_SIZE; i++) |
| 578 | printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); | 579 | printk(KERN_CONT " %8.8x", |
| 579 | printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); | 580 | (unsigned int)tp->rx_ring[i].status); |
| 581 | printk(KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); | ||
| 580 | for (i = 0; i < TX_RING_SIZE; i++) | 582 | for (i = 0; i < TX_RING_SIZE; i++) |
| 581 | printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); | 583 | printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status); |
| 582 | printk("\n"); | 584 | printk(KERN_CONT "\n"); |
| 583 | } | 585 | } |
| 584 | #endif | 586 | #endif |
| 585 | 587 | ||
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 842b1a2c40d4..0f15773dae52 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c | |||
| @@ -142,7 +142,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; | |||
| 142 | static const char version[] __initconst = | 142 | static const char version[] __initconst = |
| 143 | KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " | 143 | KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " |
| 144 | DRV_RELDATE " Donald Becker <becker@scyld.com>\n" | 144 | DRV_RELDATE " Donald Becker <becker@scyld.com>\n" |
| 145 | KERN_INFO " http://www.scyld.com/network/drivers.html\n"; | 145 | " http://www.scyld.com/network/drivers.html\n"; |
| 146 | 146 | ||
| 147 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); | 147 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); |
| 148 | MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver"); | 148 | MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver"); |
| @@ -939,7 +939,7 @@ static void tx_timeout(struct net_device *dev) | |||
| 939 | printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); | 939 | printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); |
| 940 | for (i = 0; i < RX_RING_SIZE; i++) | 940 | for (i = 0; i < RX_RING_SIZE; i++) |
| 941 | printk(" %8.8x", (unsigned int)np->rx_ring[i].status); | 941 | printk(" %8.8x", (unsigned int)np->rx_ring[i].status); |
| 942 | printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); | 942 | printk(KERN_DEBUG" Tx ring %p: ", np->tx_ring); |
| 943 | for (i = 0; i < TX_RING_SIZE; i++) | 943 | for (i = 0; i < TX_RING_SIZE; i++) |
| 944 | printk(" %8.8x", np->tx_ring[i].status); | 944 | printk(" %8.8x", np->tx_ring[i].status); |
| 945 | printk("\n"); | 945 | printk("\n"); |
| @@ -1520,7 +1520,7 @@ static int netdev_close(struct net_device *dev) | |||
| 1520 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n", | 1520 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n", |
| 1521 | i, np->tx_ring[i].length, | 1521 | i, np->tx_ring[i].length, |
| 1522 | np->tx_ring[i].status, np->tx_ring[i].buffer1); | 1522 | np->tx_ring[i].status, np->tx_ring[i].buffer1); |
| 1523 | printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", | 1523 | printk(KERN_DEBUG " Rx ring %8.8x:\n", |
| 1524 | (int)np->rx_ring); | 1524 | (int)np->rx_ring); |
| 1525 | for (i = 0; i < RX_RING_SIZE; i++) { | 1525 | for (i = 0; i < RX_RING_SIZE; i++) { |
| 1526 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", | 1526 | printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 11a0ba47b677..027f7aba26af 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) | |||
| 486 | { | 486 | { |
| 487 | struct tun_file *tfile = file->private_data; | 487 | struct tun_file *tfile = file->private_data; |
| 488 | struct tun_struct *tun = __tun_get(tfile); | 488 | struct tun_struct *tun = __tun_get(tfile); |
| 489 | struct sock *sk = tun->sk; | 489 | struct sock *sk; |
| 490 | unsigned int mask = 0; | 490 | unsigned int mask = 0; |
| 491 | 491 | ||
| 492 | if (!tun) | 492 | if (!tun) |
| 493 | return POLLERR; | 493 | return POLLERR; |
| 494 | 494 | ||
| 495 | sk = tun->sk; | ||
| 496 | |||
| 495 | DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); | 497 | DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); |
| 496 | 498 | ||
| 497 | poll_wait(file, &tun->socket.wait, wait); | 499 | poll_wait(file, &tun->socket.wait, wait); |
| @@ -1324,20 +1326,22 @@ static int tun_chr_close(struct inode *inode, struct file *file) | |||
| 1324 | struct tun_file *tfile = file->private_data; | 1326 | struct tun_file *tfile = file->private_data; |
| 1325 | struct tun_struct *tun; | 1327 | struct tun_struct *tun; |
| 1326 | 1328 | ||
| 1327 | |||
| 1328 | rtnl_lock(); | ||
| 1329 | tun = __tun_get(tfile); | 1329 | tun = __tun_get(tfile); |
| 1330 | if (tun) { | 1330 | if (tun) { |
| 1331 | DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); | 1331 | struct net_device *dev = tun->dev; |
| 1332 | |||
| 1333 | DBG(KERN_INFO "%s: tun_chr_close\n", dev->name); | ||
| 1332 | 1334 | ||
| 1333 | __tun_detach(tun); | 1335 | __tun_detach(tun); |
| 1334 | 1336 | ||
| 1335 | /* If desireable, unregister the netdevice. */ | 1337 | /* If desireable, unregister the netdevice. */ |
| 1336 | if (!(tun->flags & TUN_PERSIST)) | 1338 | if (!(tun->flags & TUN_PERSIST)) { |
| 1337 | unregister_netdevice(tun->dev); | 1339 | rtnl_lock(); |
| 1338 | 1340 | if (dev->reg_state == NETREG_REGISTERED) | |
| 1341 | unregister_netdevice(dev); | ||
| 1342 | rtnl_unlock(); | ||
| 1343 | } | ||
| 1339 | } | 1344 | } |
| 1340 | rtnl_unlock(); | ||
| 1341 | 1345 | ||
| 1342 | tun = tfile->tun; | 1346 | tun = tfile->tun; |
| 1343 | if (tun) | 1347 | if (tun) |
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 80e01778dd3b..cd35d50e46d4 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c | |||
| @@ -319,7 +319,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 319 | return crc == crc2; | 319 | return crc == crc2; |
| 320 | 320 | ||
| 321 | if (unlikely(crc != crc2)) { | 321 | if (unlikely(crc != crc2)) { |
| 322 | dev->stats.rx_errors++; | 322 | dev->net->stats.rx_errors++; |
| 323 | dev_kfree_skb_any(skb2); | 323 | dev_kfree_skb_any(skb2); |
| 324 | } else | 324 | } else |
| 325 | usbnet_skb_return(dev, skb2); | 325 | usbnet_skb_return(dev, skb2); |
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 7ae82446b93a..1d3730d6690f 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
| @@ -513,11 +513,11 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 513 | len = (skb->data[1] | (skb->data[2] << 8)) - 4; | 513 | len = (skb->data[1] | (skb->data[2] << 8)) - 4; |
| 514 | 514 | ||
| 515 | if (unlikely(status & 0xbf)) { | 515 | if (unlikely(status & 0xbf)) { |
| 516 | if (status & 0x01) dev->stats.rx_fifo_errors++; | 516 | if (status & 0x01) dev->net->stats.rx_fifo_errors++; |
| 517 | if (status & 0x02) dev->stats.rx_crc_errors++; | 517 | if (status & 0x02) dev->net->stats.rx_crc_errors++; |
| 518 | if (status & 0x04) dev->stats.rx_frame_errors++; | 518 | if (status & 0x04) dev->net->stats.rx_frame_errors++; |
| 519 | if (status & 0x20) dev->stats.rx_missed_errors++; | 519 | if (status & 0x20) dev->net->stats.rx_missed_errors++; |
| 520 | if (status & 0x90) dev->stats.rx_length_errors++; | 520 | if (status & 0x90) dev->net->stats.rx_length_errors++; |
| 521 | return 0; | 521 | return 0; |
| 522 | } | 522 | } |
| 523 | 523 | ||
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index e01314789718..1f9ec29fce50 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c | |||
| @@ -999,6 +999,9 @@ static const struct net_device_ops kaweth_netdev_ops = { | |||
| 999 | .ndo_tx_timeout = kaweth_tx_timeout, | 999 | .ndo_tx_timeout = kaweth_tx_timeout, |
| 1000 | .ndo_set_multicast_list = kaweth_set_rx_mode, | 1000 | .ndo_set_multicast_list = kaweth_set_rx_mode, |
| 1001 | .ndo_get_stats = kaweth_netdev_stats, | 1001 | .ndo_get_stats = kaweth_netdev_stats, |
| 1002 | .ndo_change_mtu = eth_change_mtu, | ||
| 1003 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1004 | .ndo_validate_addr = eth_validate_addr, | ||
| 1002 | }; | 1005 | }; |
| 1003 | 1006 | ||
| 1004 | static int kaweth_probe( | 1007 | static int kaweth_probe( |
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 034e8a73ca6b..aeb1ab03a9ee 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c | |||
| @@ -433,7 +433,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 433 | dbg("rx framesize %d range %d..%d mtu %d", skb->len, | 433 | dbg("rx framesize %d range %d..%d mtu %d", skb->len, |
| 434 | net->hard_header_len, dev->hard_mtu, net->mtu); | 434 | net->hard_header_len, dev->hard_mtu, net->mtu); |
| 435 | #endif | 435 | #endif |
| 436 | dev->stats.rx_frame_errors++; | 436 | dev->net->stats.rx_frame_errors++; |
| 437 | nc_ensure_sync(dev); | 437 | nc_ensure_sync(dev); |
| 438 | return 0; | 438 | return 0; |
| 439 | } | 439 | } |
| @@ -442,12 +442,12 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 442 | hdr_len = le16_to_cpup(&header->hdr_len); | 442 | hdr_len = le16_to_cpup(&header->hdr_len); |
| 443 | packet_len = le16_to_cpup(&header->packet_len); | 443 | packet_len = le16_to_cpup(&header->packet_len); |
| 444 | if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) { | 444 | if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) { |
| 445 | dev->stats.rx_frame_errors++; | 445 | dev->net->stats.rx_frame_errors++; |
| 446 | dbg("packet too big, %d", packet_len); | 446 | dbg("packet too big, %d", packet_len); |
| 447 | nc_ensure_sync(dev); | 447 | nc_ensure_sync(dev); |
| 448 | return 0; | 448 | return 0; |
| 449 | } else if (hdr_len < MIN_HEADER) { | 449 | } else if (hdr_len < MIN_HEADER) { |
| 450 | dev->stats.rx_frame_errors++; | 450 | dev->net->stats.rx_frame_errors++; |
| 451 | dbg("header too short, %d", hdr_len); | 451 | dbg("header too short, %d", hdr_len); |
| 452 | nc_ensure_sync(dev); | 452 | nc_ensure_sync(dev); |
| 453 | return 0; | 453 | return 0; |
| @@ -465,21 +465,21 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 465 | 465 | ||
| 466 | if ((packet_len & 0x01) == 0) { | 466 | if ((packet_len & 0x01) == 0) { |
| 467 | if (skb->data [packet_len] != PAD_BYTE) { | 467 | if (skb->data [packet_len] != PAD_BYTE) { |
| 468 | dev->stats.rx_frame_errors++; | 468 | dev->net->stats.rx_frame_errors++; |
| 469 | dbg("bad pad"); | 469 | dbg("bad pad"); |
| 470 | return 0; | 470 | return 0; |
| 471 | } | 471 | } |
| 472 | skb_trim(skb, skb->len - 1); | 472 | skb_trim(skb, skb->len - 1); |
| 473 | } | 473 | } |
| 474 | if (skb->len != packet_len) { | 474 | if (skb->len != packet_len) { |
| 475 | dev->stats.rx_frame_errors++; | 475 | dev->net->stats.rx_frame_errors++; |
| 476 | dbg("bad packet len %d (expected %d)", | 476 | dbg("bad packet len %d (expected %d)", |
| 477 | skb->len, packet_len); | 477 | skb->len, packet_len); |
| 478 | nc_ensure_sync(dev); | 478 | nc_ensure_sync(dev); |
| 479 | return 0; | 479 | return 0; |
| 480 | } | 480 | } |
| 481 | if (header->packet_id != get_unaligned(&trailer->packet_id)) { | 481 | if (header->packet_id != get_unaligned(&trailer->packet_id)) { |
| 482 | dev->stats.rx_fifo_errors++; | 482 | dev->net->stats.rx_fifo_errors++; |
| 483 | dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", | 483 | dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", |
| 484 | le16_to_cpu(header->packet_id), | 484 | le16_to_cpu(header->packet_id), |
| 485 | le16_to_cpu(trailer->packet_id)); | 485 | le16_to_cpu(trailer->packet_id)); |
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 73acbd244aa1..631d269ac980 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c | |||
| @@ -1493,6 +1493,9 @@ static const struct net_device_ops pegasus_netdev_ops = { | |||
| 1493 | .ndo_set_multicast_list = pegasus_set_multicast, | 1493 | .ndo_set_multicast_list = pegasus_set_multicast, |
| 1494 | .ndo_get_stats = pegasus_netdev_stats, | 1494 | .ndo_get_stats = pegasus_netdev_stats, |
| 1495 | .ndo_tx_timeout = pegasus_tx_timeout, | 1495 | .ndo_tx_timeout = pegasus_tx_timeout, |
| 1496 | .ndo_change_mtu = eth_change_mtu, | ||
| 1497 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1498 | .ndo_validate_addr = eth_validate_addr, | ||
| 1496 | }; | 1499 | }; |
| 1497 | 1500 | ||
| 1498 | static struct usb_driver pegasus_driver = { | 1501 | static struct usb_driver pegasus_driver = { |
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 1bf243ef950e..2232232b7989 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c | |||
| @@ -487,7 +487,7 @@ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 487 | if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET | 487 | if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET |
| 488 | || skb->len < msg_len | 488 | || skb->len < msg_len |
| 489 | || (data_offset + data_len + 8) > msg_len)) { | 489 | || (data_offset + data_len + 8) > msg_len)) { |
| 490 | dev->stats.rx_frame_errors++; | 490 | dev->net->stats.rx_frame_errors++; |
| 491 | devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d", | 491 | devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d", |
| 492 | le32_to_cpu(hdr->msg_type), | 492 | le32_to_cpu(hdr->msg_type), |
| 493 | msg_len, data_offset, data_len, skb->len); | 493 | msg_len, data_offset, data_len, skb->len); |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 89a91f8c22de..fe045896406b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c | |||
| @@ -1108,18 +1108,18 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 1108 | if (unlikely(header & RX_STS_ES_)) { | 1108 | if (unlikely(header & RX_STS_ES_)) { |
| 1109 | if (netif_msg_rx_err(dev)) | 1109 | if (netif_msg_rx_err(dev)) |
| 1110 | devdbg(dev, "Error header=0x%08x", header); | 1110 | devdbg(dev, "Error header=0x%08x", header); |
| 1111 | dev->stats.rx_errors++; | 1111 | dev->net->stats.rx_errors++; |
| 1112 | dev->stats.rx_dropped++; | 1112 | dev->net->stats.rx_dropped++; |
| 1113 | 1113 | ||
| 1114 | if (header & RX_STS_CRC_) { | 1114 | if (header & RX_STS_CRC_) { |
| 1115 | dev->stats.rx_crc_errors++; | 1115 | dev->net->stats.rx_crc_errors++; |
| 1116 | } else { | 1116 | } else { |
| 1117 | if (header & (RX_STS_TL_ | RX_STS_RF_)) | 1117 | if (header & (RX_STS_TL_ | RX_STS_RF_)) |
| 1118 | dev->stats.rx_frame_errors++; | 1118 | dev->net->stats.rx_frame_errors++; |
| 1119 | 1119 | ||
| 1120 | if ((header & RX_STS_LE_) && | 1120 | if ((header & RX_STS_LE_) && |
| 1121 | (!(header & RX_STS_FT_))) | 1121 | (!(header & RX_STS_FT_))) |
| 1122 | dev->stats.rx_length_errors++; | 1122 | dev->net->stats.rx_length_errors++; |
| 1123 | } | 1123 | } |
| 1124 | } else { | 1124 | } else { |
| 1125 | /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ | 1125 | /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 22c0585a0319..edfd9e10ceba 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -234,8 +234,8 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) | |||
| 234 | int status; | 234 | int status; |
| 235 | 235 | ||
| 236 | skb->protocol = eth_type_trans (skb, dev->net); | 236 | skb->protocol = eth_type_trans (skb, dev->net); |
| 237 | dev->stats.rx_packets++; | 237 | dev->net->stats.rx_packets++; |
| 238 | dev->stats.rx_bytes += skb->len; | 238 | dev->net->stats.rx_bytes += skb->len; |
| 239 | 239 | ||
| 240 | if (netif_msg_rx_status (dev)) | 240 | if (netif_msg_rx_status (dev)) |
| 241 | devdbg (dev, "< rx, len %zu, type 0x%x", | 241 | devdbg (dev, "< rx, len %zu, type 0x%x", |
| @@ -397,7 +397,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) | |||
| 397 | if (netif_msg_rx_err (dev)) | 397 | if (netif_msg_rx_err (dev)) |
| 398 | devdbg (dev, "drop"); | 398 | devdbg (dev, "drop"); |
| 399 | error: | 399 | error: |
| 400 | dev->stats.rx_errors++; | 400 | dev->net->stats.rx_errors++; |
| 401 | skb_queue_tail (&dev->done, skb); | 401 | skb_queue_tail (&dev->done, skb); |
| 402 | } | 402 | } |
| 403 | } | 403 | } |
| @@ -420,8 +420,8 @@ static void rx_complete (struct urb *urb) | |||
| 420 | case 0: | 420 | case 0: |
| 421 | if (skb->len < dev->net->hard_header_len) { | 421 | if (skb->len < dev->net->hard_header_len) { |
| 422 | entry->state = rx_cleanup; | 422 | entry->state = rx_cleanup; |
| 423 | dev->stats.rx_errors++; | 423 | dev->net->stats.rx_errors++; |
| 424 | dev->stats.rx_length_errors++; | 424 | dev->net->stats.rx_length_errors++; |
| 425 | if (netif_msg_rx_err (dev)) | 425 | if (netif_msg_rx_err (dev)) |
| 426 | devdbg (dev, "rx length %d", skb->len); | 426 | devdbg (dev, "rx length %d", skb->len); |
| 427 | } | 427 | } |
| @@ -433,7 +433,7 @@ static void rx_complete (struct urb *urb) | |||
| 433 | * storm, recovering as needed. | 433 | * storm, recovering as needed. |
| 434 | */ | 434 | */ |
| 435 | case -EPIPE: | 435 | case -EPIPE: |
| 436 | dev->stats.rx_errors++; | 436 | dev->net->stats.rx_errors++; |
| 437 | usbnet_defer_kevent (dev, EVENT_RX_HALT); | 437 | usbnet_defer_kevent (dev, EVENT_RX_HALT); |
| 438 | // FALLTHROUGH | 438 | // FALLTHROUGH |
| 439 | 439 | ||
| @@ -451,7 +451,7 @@ static void rx_complete (struct urb *urb) | |||
| 451 | case -EPROTO: | 451 | case -EPROTO: |
| 452 | case -ETIME: | 452 | case -ETIME: |
| 453 | case -EILSEQ: | 453 | case -EILSEQ: |
| 454 | dev->stats.rx_errors++; | 454 | dev->net->stats.rx_errors++; |
| 455 | if (!timer_pending (&dev->delay)) { | 455 | if (!timer_pending (&dev->delay)) { |
| 456 | mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); | 456 | mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); |
| 457 | if (netif_msg_link (dev)) | 457 | if (netif_msg_link (dev)) |
| @@ -465,12 +465,12 @@ block: | |||
| 465 | 465 | ||
| 466 | /* data overrun ... flush fifo? */ | 466 | /* data overrun ... flush fifo? */ |
| 467 | case -EOVERFLOW: | 467 | case -EOVERFLOW: |
| 468 | dev->stats.rx_over_errors++; | 468 | dev->net->stats.rx_over_errors++; |
| 469 | // FALLTHROUGH | 469 | // FALLTHROUGH |
| 470 | 470 | ||
| 471 | default: | 471 | default: |
| 472 | entry->state = rx_cleanup; | 472 | entry->state = rx_cleanup; |
| 473 | dev->stats.rx_errors++; | 473 | dev->net->stats.rx_errors++; |
| 474 | if (netif_msg_rx_err (dev)) | 474 | if (netif_msg_rx_err (dev)) |
| 475 | devdbg (dev, "rx status %d", urb_status); | 475 | devdbg (dev, "rx status %d", urb_status); |
| 476 | break; | 476 | break; |
| @@ -583,8 +583,8 @@ int usbnet_stop (struct net_device *net) | |||
| 583 | 583 | ||
| 584 | if (netif_msg_ifdown (dev)) | 584 | if (netif_msg_ifdown (dev)) |
| 585 | devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", | 585 | devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", |
| 586 | dev->stats.rx_packets, dev->stats.tx_packets, | 586 | net->stats.rx_packets, net->stats.tx_packets, |
| 587 | dev->stats.rx_errors, dev->stats.tx_errors | 587 | net->stats.rx_errors, net->stats.tx_errors |
| 588 | ); | 588 | ); |
| 589 | 589 | ||
| 590 | // ensure there are no more active urbs | 590 | // ensure there are no more active urbs |
| @@ -891,10 +891,10 @@ static void tx_complete (struct urb *urb) | |||
| 891 | struct usbnet *dev = entry->dev; | 891 | struct usbnet *dev = entry->dev; |
| 892 | 892 | ||
| 893 | if (urb->status == 0) { | 893 | if (urb->status == 0) { |
| 894 | dev->stats.tx_packets++; | 894 | dev->net->stats.tx_packets++; |
| 895 | dev->stats.tx_bytes += entry->length; | 895 | dev->net->stats.tx_bytes += entry->length; |
| 896 | } else { | 896 | } else { |
| 897 | dev->stats.tx_errors++; | 897 | dev->net->stats.tx_errors++; |
| 898 | 898 | ||
| 899 | switch (urb->status) { | 899 | switch (urb->status) { |
| 900 | case -EPIPE: | 900 | case -EPIPE: |
| @@ -1020,7 +1020,7 @@ int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
| 1020 | devdbg (dev, "drop, code %d", retval); | 1020 | devdbg (dev, "drop, code %d", retval); |
| 1021 | drop: | 1021 | drop: |
| 1022 | retval = NET_XMIT_SUCCESS; | 1022 | retval = NET_XMIT_SUCCESS; |
| 1023 | dev->stats.tx_dropped++; | 1023 | dev->net->stats.tx_dropped++; |
| 1024 | if (skb) | 1024 | if (skb) |
| 1025 | dev_kfree_skb_any (skb); | 1025 | dev_kfree_skb_any (skb); |
| 1026 | usb_free_urb (urb); | 1026 | usb_free_urb (urb); |
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 87197dd9c788..1097c72e44d5 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -208,11 +208,14 @@ rx_drop: | |||
| 208 | 208 | ||
| 209 | static struct net_device_stats *veth_get_stats(struct net_device *dev) | 209 | static struct net_device_stats *veth_get_stats(struct net_device *dev) |
| 210 | { | 210 | { |
| 211 | struct veth_priv *priv = netdev_priv(dev); | 211 | struct veth_priv *priv; |
| 212 | struct net_device_stats *dev_stats = &dev->stats; | 212 | struct net_device_stats *dev_stats; |
| 213 | unsigned int cpu; | 213 | int cpu; |
| 214 | struct veth_net_stats *stats; | 214 | struct veth_net_stats *stats; |
| 215 | 215 | ||
| 216 | priv = netdev_priv(dev); | ||
| 217 | dev_stats = &dev->stats; | ||
| 218 | |||
| 216 | dev_stats->rx_packets = 0; | 219 | dev_stats->rx_packets = 0; |
| 217 | dev_stats->tx_packets = 0; | 220 | dev_stats->tx_packets = 0; |
| 218 | dev_stats->rx_bytes = 0; | 221 | dev_stats->rx_bytes = 0; |
| @@ -220,17 +223,16 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) | |||
| 220 | dev_stats->tx_dropped = 0; | 223 | dev_stats->tx_dropped = 0; |
| 221 | dev_stats->rx_dropped = 0; | 224 | dev_stats->rx_dropped = 0; |
| 222 | 225 | ||
| 223 | if (priv->stats) | 226 | for_each_online_cpu(cpu) { |
| 224 | for_each_online_cpu(cpu) { | 227 | stats = per_cpu_ptr(priv->stats, cpu); |
| 225 | stats = per_cpu_ptr(priv->stats, cpu); | ||
| 226 | 228 | ||
| 227 | dev_stats->rx_packets += stats->rx_packets; | 229 | dev_stats->rx_packets += stats->rx_packets; |
| 228 | dev_stats->tx_packets += stats->tx_packets; | 230 | dev_stats->tx_packets += stats->tx_packets; |
| 229 | dev_stats->rx_bytes += stats->rx_bytes; | 231 | dev_stats->rx_bytes += stats->rx_bytes; |
| 230 | dev_stats->tx_bytes += stats->tx_bytes; | 232 | dev_stats->tx_bytes += stats->tx_bytes; |
| 231 | dev_stats->tx_dropped += stats->tx_dropped; | 233 | dev_stats->tx_dropped += stats->tx_dropped; |
| 232 | dev_stats->rx_dropped += stats->rx_dropped; | 234 | dev_stats->rx_dropped += stats->rx_dropped; |
| 233 | } | 235 | } |
| 234 | 236 | ||
| 235 | return dev_stats; | 237 | return dev_stats; |
| 236 | } | 238 | } |
| @@ -257,8 +259,6 @@ static int veth_close(struct net_device *dev) | |||
| 257 | netif_carrier_off(dev); | 259 | netif_carrier_off(dev); |
| 258 | netif_carrier_off(priv->peer); | 260 | netif_carrier_off(priv->peer); |
| 259 | 261 | ||
| 260 | free_percpu(priv->stats); | ||
| 261 | priv->stats = NULL; | ||
| 262 | return 0; | 262 | return 0; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| @@ -289,6 +289,15 @@ static int veth_dev_init(struct net_device *dev) | |||
| 289 | return 0; | 289 | return 0; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static void veth_dev_free(struct net_device *dev) | ||
| 293 | { | ||
| 294 | struct veth_priv *priv; | ||
| 295 | |||
| 296 | priv = netdev_priv(dev); | ||
| 297 | free_percpu(priv->stats); | ||
| 298 | free_netdev(dev); | ||
| 299 | } | ||
| 300 | |||
| 292 | static const struct net_device_ops veth_netdev_ops = { | 301 | static const struct net_device_ops veth_netdev_ops = { |
| 293 | .ndo_init = veth_dev_init, | 302 | .ndo_init = veth_dev_init, |
| 294 | .ndo_open = veth_open, | 303 | .ndo_open = veth_open, |
| @@ -306,7 +315,7 @@ static void veth_setup(struct net_device *dev) | |||
| 306 | dev->netdev_ops = &veth_netdev_ops; | 315 | dev->netdev_ops = &veth_netdev_ops; |
| 307 | dev->ethtool_ops = &veth_ethtool_ops; | 316 | dev->ethtool_ops = &veth_ethtool_ops; |
| 308 | dev->features |= NETIF_F_LLTX; | 317 | dev->features |= NETIF_F_LLTX; |
| 309 | dev->destructor = free_netdev; | 318 | dev->destructor = veth_dev_free; |
| 310 | } | 319 | } |
| 311 | 320 | ||
| 312 | /* | 321 | /* |
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index d3489a3c4c03..88c30a58b4bd 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
| @@ -621,6 +621,7 @@ static const struct net_device_ops rhine_netdev_ops = { | |||
| 621 | .ndo_start_xmit = rhine_start_tx, | 621 | .ndo_start_xmit = rhine_start_tx, |
| 622 | .ndo_get_stats = rhine_get_stats, | 622 | .ndo_get_stats = rhine_get_stats, |
| 623 | .ndo_set_multicast_list = rhine_set_rx_mode, | 623 | .ndo_set_multicast_list = rhine_set_rx_mode, |
| 624 | .ndo_change_mtu = eth_change_mtu, | ||
| 624 | .ndo_validate_addr = eth_validate_addr, | 625 | .ndo_validate_addr = eth_validate_addr, |
| 625 | .ndo_set_mac_address = eth_mac_addr, | 626 | .ndo_set_mac_address = eth_mac_addr, |
| 626 | .ndo_do_ioctl = netdev_ioctl, | 627 | .ndo_do_ioctl = netdev_ioctl, |
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c index 223238de475c..1ea1ef6c3b96 100644 --- a/drivers/net/wan/hd64570.c +++ b/drivers/net/wan/hd64570.c | |||
| @@ -584,8 +584,9 @@ static void sca_dump_rings(struct net_device *dev) | |||
| 584 | sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in"); | 584 | sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in"); |
| 585 | for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) | 585 | for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) |
| 586 | printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); | 586 | printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); |
| 587 | printk(KERN_CONT "\n"); | ||
| 587 | 588 | ||
| 588 | printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " | 589 | printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " |
| 589 | "last=%u %sactive", | 590 | "last=%u %sactive", |
| 590 | sca_inw(get_dmac_tx(port) + CDAL, card), | 591 | sca_inw(get_dmac_tx(port) + CDAL, card), |
| 591 | sca_inw(get_dmac_tx(port) + EDAL, card), | 592 | sca_inw(get_dmac_tx(port) + EDAL, card), |
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c index 497b003d7239..f099c34a3ae2 100644 --- a/drivers/net/wan/hd64572.c +++ b/drivers/net/wan/hd64572.c | |||
| @@ -529,8 +529,9 @@ static void sca_dump_rings(struct net_device *dev) | |||
| 529 | sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in"); | 529 | sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in"); |
| 530 | for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++) | 530 | for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++) |
| 531 | printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); | 531 | printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); |
| 532 | printk(KERN_CONT "\n"); | ||
| 532 | 533 | ||
| 533 | printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " | 534 | printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " |
| 534 | "last=%u %sactive", | 535 | "last=%u %sactive", |
| 535 | sca_inl(get_dmac_tx(port) + CDAL, card), | 536 | sca_inl(get_dmac_tx(port) + CDAL, card), |
| 536 | sca_inl(get_dmac_tx(port) + EDAL, card), | 537 | sca_inl(get_dmac_tx(port) + EDAL, card), |
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 3fb9dbc88a1a..d14e95a08d66 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c | |||
| @@ -326,11 +326,9 @@ sbni_pci_probe( struct net_device *dev ) | |||
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs) | 328 | if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs) |
| 329 | printk( KERN_WARNING " WARNING: The PCI BIOS assigned " | 329 | printk( KERN_WARNING |
| 330 | "this PCI card to IRQ %d, which is unlikely " | 330 | " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n" |
| 331 | "to work!.\n" | 331 | " You should use the PCI BIOS setup to assign a valid IRQ line.\n", |
| 332 | KERN_WARNING " You should use the PCI BIOS " | ||
| 333 | "setup to assign a valid IRQ line.\n", | ||
| 334 | pci_irq_line ); | 332 | pci_irq_line ); |
| 335 | 333 | ||
| 336 | /* avoiding re-enable dual adapters */ | 334 | /* avoiding re-enable dual adapters */ |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index d26e7b485315..eb0337c49546 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config ATH_COMMON | 1 | config ATH_COMMON |
| 2 | tristate "Atheros Wireless Cards" | 2 | tristate "Atheros Wireless Cards" |
| 3 | depends on WLAN_80211 | ||
| 3 | depends on ATH5K || ATH9K || AR9170_USB | 4 | depends on ATH5K || ATH9K || AR9170_USB |
| 4 | 5 | ||
| 5 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 6 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b61a071788a5..4ccf48e396df 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | if (bf_next == NULL) { | 357 | if (bf_next == NULL) { |
| 358 | INIT_LIST_HEAD(&bf_head); | 358 | /* |
| 359 | * Make sure the last desc is reclaimed if it | ||
| 360 | * not a holding desc. | ||
| 361 | */ | ||
| 362 | if (!bf_last->bf_stale) | ||
| 363 | list_move_tail(&bf->list, &bf_head); | ||
| 364 | else | ||
| 365 | INIT_LIST_HEAD(&bf_head); | ||
| 359 | } else { | 366 | } else { |
| 360 | ASSERT(!list_empty(bf_q)); | 367 | ASSERT(!list_empty(bf_q)); |
| 361 | list_move_tail(&bf->list, &bf_head); | 368 | list_move_tail(&bf->list, &bf_head); |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f580c2812d91..40448067e4cc 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -648,6 +648,7 @@ struct b43_wl { | |||
| 648 | u8 nr_devs; | 648 | u8 nr_devs; |
| 649 | 649 | ||
| 650 | bool radiotap_enabled; | 650 | bool radiotap_enabled; |
| 651 | bool radio_enabled; | ||
| 651 | 652 | ||
| 652 | /* The beacon we are currently using (AP or IBSS mode). | 653 | /* The beacon we are currently using (AP or IBSS mode). |
| 653 | * This beacon stuff is protected by the irq_lock. */ | 654 | * This beacon stuff is protected by the irq_lock. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6456afebdba1..e71c8d9cd706 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -3497,8 +3497,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 3497 | if (phy->ops->set_rx_antenna) | 3497 | if (phy->ops->set_rx_antenna) |
| 3498 | phy->ops->set_rx_antenna(dev, antenna); | 3498 | phy->ops->set_rx_antenna(dev, antenna); |
| 3499 | 3499 | ||
| 3500 | if (!!conf->radio_enabled != phy->radio_on) { | 3500 | if (wl->radio_enabled != phy->radio_on) { |
| 3501 | if (conf->radio_enabled) { | 3501 | if (wl->radio_enabled) { |
| 3502 | b43_software_rfkill(dev, false); | 3502 | b43_software_rfkill(dev, false); |
| 3503 | b43info(dev->wl, "Radio turned on by software\n"); | 3503 | b43info(dev->wl, "Radio turned on by software\n"); |
| 3504 | if (!dev->radio_hw_enable) { | 3504 | if (!dev->radio_hw_enable) { |
| @@ -4339,6 +4339,7 @@ static int b43_op_start(struct ieee80211_hw *hw) | |||
| 4339 | wl->beacon0_uploaded = 0; | 4339 | wl->beacon0_uploaded = 0; |
| 4340 | wl->beacon1_uploaded = 0; | 4340 | wl->beacon1_uploaded = 0; |
| 4341 | wl->beacon_templates_virgin = 1; | 4341 | wl->beacon_templates_virgin = 1; |
| 4342 | wl->radio_enabled = 1; | ||
| 4342 | 4343 | ||
| 4343 | mutex_lock(&wl->mutex); | 4344 | mutex_lock(&wl->mutex); |
| 4344 | 4345 | ||
| @@ -4378,6 +4379,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
| 4378 | if (b43_status(dev) >= B43_STAT_STARTED) | 4379 | if (b43_status(dev) >= B43_STAT_STARTED) |
| 4379 | b43_wireless_core_stop(dev); | 4380 | b43_wireless_core_stop(dev); |
| 4380 | b43_wireless_core_exit(dev); | 4381 | b43_wireless_core_exit(dev); |
| 4382 | wl->radio_enabled = 0; | ||
| 4381 | mutex_unlock(&wl->mutex); | 4383 | mutex_unlock(&wl->mutex); |
| 4382 | 4384 | ||
| 4383 | cancel_work_sync(&(wl->txpower_adjust_work)); | 4385 | cancel_work_sync(&(wl->txpower_adjust_work)); |
| @@ -4560,6 +4562,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
| 4560 | B43_WARN_ON(1); | 4562 | B43_WARN_ON(1); |
| 4561 | 4563 | ||
| 4562 | dev->phy.gmode = have_2ghz_phy; | 4564 | dev->phy.gmode = have_2ghz_phy; |
| 4565 | dev->phy.radio_on = 1; | ||
| 4563 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; | 4566 | tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; |
| 4564 | b43_wireless_core_reset(dev, tmp); | 4567 | b43_wireless_core_reset(dev, tmp); |
| 4565 | 4568 | ||
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 3cfc30307a27..6c3a74964ab8 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { | 36 | static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { |
| 37 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), | 37 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), |
| 38 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), | ||
| 38 | PCMCIA_DEVICE_NULL, | 39 | PCMCIA_DEVICE_NULL, |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 77fda148ac46..038baa8869e2 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
| @@ -607,6 +607,7 @@ struct b43legacy_wl { | |||
| 607 | u8 nr_devs; | 607 | u8 nr_devs; |
| 608 | 608 | ||
| 609 | bool radiotap_enabled; | 609 | bool radiotap_enabled; |
| 610 | bool radio_enabled; | ||
| 610 | 611 | ||
| 611 | /* The beacon we are currently using (AP or IBSS mode). | 612 | /* The beacon we are currently using (AP or IBSS mode). |
| 612 | * This beacon stuff is protected by the irq_lock. */ | 613 | * This beacon stuff is protected by the irq_lock. */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index e5136fb65ddd..c4973c1942bf 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
| @@ -2689,8 +2689,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, | |||
| 2689 | /* Antennas for RX and management frame TX. */ | 2689 | /* Antennas for RX and management frame TX. */ |
| 2690 | b43legacy_mgmtframe_txantenna(dev, antenna_tx); | 2690 | b43legacy_mgmtframe_txantenna(dev, antenna_tx); |
| 2691 | 2691 | ||
| 2692 | if (!!conf->radio_enabled != phy->radio_on) { | 2692 | if (wl->radio_enabled != phy->radio_on) { |
| 2693 | if (conf->radio_enabled) { | 2693 | if (wl->radio_enabled) { |
| 2694 | b43legacy_radio_turn_on(dev); | 2694 | b43legacy_radio_turn_on(dev); |
| 2695 | b43legacyinfo(dev->wl, "Radio turned on by software\n"); | 2695 | b43legacyinfo(dev->wl, "Radio turned on by software\n"); |
| 2696 | if (!dev->radio_hw_enable) | 2696 | if (!dev->radio_hw_enable) |
| @@ -3441,6 +3441,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) | |||
| 3441 | wl->beacon0_uploaded = 0; | 3441 | wl->beacon0_uploaded = 0; |
| 3442 | wl->beacon1_uploaded = 0; | 3442 | wl->beacon1_uploaded = 0; |
| 3443 | wl->beacon_templates_virgin = 1; | 3443 | wl->beacon_templates_virgin = 1; |
| 3444 | wl->radio_enabled = 1; | ||
| 3444 | 3445 | ||
| 3445 | mutex_lock(&wl->mutex); | 3446 | mutex_lock(&wl->mutex); |
| 3446 | 3447 | ||
| @@ -3479,6 +3480,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) | |||
| 3479 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) | 3480 | if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) |
| 3480 | b43legacy_wireless_core_stop(dev); | 3481 | b43legacy_wireless_core_stop(dev); |
| 3481 | b43legacy_wireless_core_exit(dev); | 3482 | b43legacy_wireless_core_exit(dev); |
| 3483 | wl->radio_enabled = 0; | ||
| 3482 | mutex_unlock(&wl->mutex); | 3484 | mutex_unlock(&wl->mutex); |
| 3483 | } | 3485 | } |
| 3484 | 3486 | ||
| @@ -3620,6 +3622,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) | |||
| 3620 | have_bphy = 1; | 3622 | have_bphy = 1; |
| 3621 | 3623 | ||
| 3622 | dev->phy.gmode = (have_gphy || have_bphy); | 3624 | dev->phy.gmode = (have_gphy || have_bphy); |
| 3625 | dev->phy.radio_on = 1; | ||
| 3623 | tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; | 3626 | tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; |
| 3624 | b43legacy_wireless_core_reset(dev, tmp); | 3627 | b43legacy_wireless_core_reset(dev, tmp); |
| 3625 | 3628 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 1eccb6df46dd..030401d367d3 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig | |||
| @@ -4,6 +4,15 @@ config IWM | |||
| 4 | depends on CFG80211 | 4 | depends on CFG80211 |
| 5 | select WIRELESS_EXT | 5 | select WIRELESS_EXT |
| 6 | select FW_LOADER | 6 | select FW_LOADER |
| 7 | help | ||
| 8 | The Intel Wireless Multicomm 3200 hardware is a combo | ||
| 9 | card with GPS, Bluetooth, WiMax and 802.11 radios. It | ||
| 10 | runs over SDIO and is typically found on Moorestown | ||
| 11 | based platform. This driver takes care of the 802.11 | ||
| 12 | part, which is a fullmac one. | ||
| 13 | |||
| 14 | If you choose to build it as a module, it'll be called | ||
| 15 | iwmc3200wifi.ko. | ||
| 7 | 16 | ||
| 8 | config IWM_DEBUG | 17 | config IWM_DEBUG |
| 9 | bool "Enable full debugging output in iwmc3200wifi" | 18 | bool "Enable full debugging output in iwmc3200wifi" |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e789c6e9938c..a111bda392e2 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
| @@ -418,6 +418,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
| 418 | continue; | 418 | continue; |
| 419 | 419 | ||
| 420 | if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || | 420 | if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || |
| 421 | !data->channel || !data2->channel || | ||
| 421 | data->channel->center_freq != data2->channel->center_freq || | 422 | data->channel->center_freq != data2->channel->center_freq || |
| 422 | !(data->group & data2->group)) | 423 | !(data->group & data2->group)) |
| 423 | continue; | 424 | continue; |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 345593c4accb..a370e510f19f 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
| @@ -2521,6 +2521,8 @@ static const struct net_device_ops orinoco_netdev_ops = { | |||
| 2521 | .ndo_start_xmit = orinoco_xmit, | 2521 | .ndo_start_xmit = orinoco_xmit, |
| 2522 | .ndo_set_multicast_list = orinoco_set_multicast_list, | 2522 | .ndo_set_multicast_list = orinoco_set_multicast_list, |
| 2523 | .ndo_change_mtu = orinoco_change_mtu, | 2523 | .ndo_change_mtu = orinoco_change_mtu, |
| 2524 | .ndo_set_mac_address = eth_mac_addr, | ||
| 2525 | .ndo_validate_addr = eth_validate_addr, | ||
| 2524 | .ndo_tx_timeout = orinoco_tx_timeout, | 2526 | .ndo_tx_timeout = orinoco_tx_timeout, |
| 2525 | .ndo_get_stats = orinoco_get_stats, | 2527 | .ndo_get_stats = orinoco_get_stats, |
| 2526 | }; | 2528 | }; |
| @@ -2555,7 +2557,6 @@ struct net_device | |||
| 2555 | priv->wireless_data.spy_data = &priv->spy_data; | 2557 | priv->wireless_data.spy_data = &priv->spy_data; |
| 2556 | dev->wireless_data = &priv->wireless_data; | 2558 | dev->wireless_data = &priv->wireless_data; |
| 2557 | #endif | 2559 | #endif |
| 2558 | /* we use the default eth_mac_addr for setting the MAC addr */ | ||
| 2559 | 2560 | ||
| 2560 | /* Reserve space in skb for the SNAP header */ | 2561 | /* Reserve space in skb for the SNAP header */ |
| 2561 | dev->hard_header_len += ENCAPS_OVERHEAD; | 2562 | dev->hard_header_len += ENCAPS_OVERHEAD; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b618bd14583f..22ca122bd798 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
| @@ -823,30 +823,30 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 823 | struct p54_tx_info *range; | 823 | struct p54_tx_info *range; |
| 824 | unsigned long flags; | 824 | unsigned long flags; |
| 825 | 825 | ||
| 826 | if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue))) | 826 | if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) |
| 827 | return; | 827 | return; |
| 828 | 828 | ||
| 829 | /* There used to be a check here to see if the SKB was on the | 829 | /* |
| 830 | * TX queue or not. This can never happen because all SKBs we | 830 | * don't try to free an already unlinked skb |
| 831 | * see here successfully went through p54_assign_address() | ||
| 832 | * which means the SKB is on the ->tx_queue. | ||
| 833 | */ | 831 | */ |
| 832 | if (unlikely((!skb->next) || (!skb->prev))) | ||
| 833 | return; | ||
| 834 | 834 | ||
| 835 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 835 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
| 836 | info = IEEE80211_SKB_CB(skb); | 836 | info = IEEE80211_SKB_CB(skb); |
| 837 | range = (void *)info->rate_driver_data; | 837 | range = (void *)info->rate_driver_data; |
| 838 | if (!skb_queue_is_first(&priv->tx_queue, skb)) { | 838 | if (skb->prev != (struct sk_buff *)&priv->tx_queue) { |
| 839 | struct ieee80211_tx_info *ni; | 839 | struct ieee80211_tx_info *ni; |
| 840 | struct p54_tx_info *mr; | 840 | struct p54_tx_info *mr; |
| 841 | 841 | ||
| 842 | ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb)); | 842 | ni = IEEE80211_SKB_CB(skb->prev); |
| 843 | mr = (struct p54_tx_info *)ni->rate_driver_data; | 843 | mr = (struct p54_tx_info *)ni->rate_driver_data; |
| 844 | } | 844 | } |
| 845 | if (!skb_queue_is_last(&priv->tx_queue, skb)) { | 845 | if (skb->next != (struct sk_buff *)&priv->tx_queue) { |
| 846 | struct ieee80211_tx_info *ni; | 846 | struct ieee80211_tx_info *ni; |
| 847 | struct p54_tx_info *mr; | 847 | struct p54_tx_info *mr; |
| 848 | 848 | ||
| 849 | ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb)); | 849 | ni = IEEE80211_SKB_CB(skb->next); |
| 850 | mr = (struct p54_tx_info *)ni->rate_driver_data; | 850 | mr = (struct p54_tx_info *)ni->rate_driver_data; |
| 851 | } | 851 | } |
| 852 | __skb_unlink(skb, &priv->tx_queue); | 852 | __skb_unlink(skb, &priv->tx_queue); |
| @@ -864,13 +864,15 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, | |||
| 864 | unsigned long flags; | 864 | unsigned long flags; |
| 865 | 865 | ||
| 866 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 866 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
| 867 | skb_queue_walk(&priv->tx_queue, entry) { | 867 | entry = priv->tx_queue.next; |
| 868 | while (entry != (struct sk_buff *)&priv->tx_queue) { | ||
| 868 | struct p54_hdr *hdr = (struct p54_hdr *) entry->data; | 869 | struct p54_hdr *hdr = (struct p54_hdr *) entry->data; |
| 869 | 870 | ||
| 870 | if (hdr->req_id == req_id) { | 871 | if (hdr->req_id == req_id) { |
| 871 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 872 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
| 872 | return entry; | 873 | return entry; |
| 873 | } | 874 | } |
| 875 | entry = entry->next; | ||
| 874 | } | 876 | } |
| 875 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 877 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
| 876 | return NULL; | 878 | return NULL; |
| @@ -888,33 +890,36 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 888 | int count, idx; | 890 | int count, idx; |
| 889 | 891 | ||
| 890 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 892 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
| 891 | skb_queue_walk(&priv->tx_queue, entry) { | 893 | entry = (struct sk_buff *) priv->tx_queue.next; |
| 894 | while (entry != (struct sk_buff *)&priv->tx_queue) { | ||
| 892 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); | 895 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); |
| 893 | struct p54_hdr *entry_hdr; | 896 | struct p54_hdr *entry_hdr; |
| 894 | struct p54_tx_data *entry_data; | 897 | struct p54_tx_data *entry_data; |
| 895 | unsigned int pad = 0, frame_len; | 898 | unsigned int pad = 0, frame_len; |
| 896 | 899 | ||
| 897 | range = (void *)info->rate_driver_data; | 900 | range = (void *)info->rate_driver_data; |
| 898 | if (range->start_addr != addr) | 901 | if (range->start_addr != addr) { |
| 902 | entry = entry->next; | ||
| 899 | continue; | 903 | continue; |
| 904 | } | ||
| 900 | 905 | ||
| 901 | if (!skb_queue_is_last(&priv->tx_queue, entry)) { | 906 | if (entry->next != (struct sk_buff *)&priv->tx_queue) { |
| 902 | struct ieee80211_tx_info *ni; | 907 | struct ieee80211_tx_info *ni; |
| 903 | struct p54_tx_info *mr; | 908 | struct p54_tx_info *mr; |
| 904 | 909 | ||
| 905 | ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, | 910 | ni = IEEE80211_SKB_CB(entry->next); |
| 906 | entry)); | ||
| 907 | mr = (struct p54_tx_info *)ni->rate_driver_data; | 911 | mr = (struct p54_tx_info *)ni->rate_driver_data; |
| 908 | } | 912 | } |
| 909 | 913 | ||
| 910 | __skb_unlink(entry, &priv->tx_queue); | 914 | __skb_unlink(entry, &priv->tx_queue); |
| 911 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
| 912 | 915 | ||
| 913 | frame_len = entry->len; | 916 | frame_len = entry->len; |
| 914 | entry_hdr = (struct p54_hdr *) entry->data; | 917 | entry_hdr = (struct p54_hdr *) entry->data; |
| 915 | entry_data = (struct p54_tx_data *) entry_hdr->data; | 918 | entry_data = (struct p54_tx_data *) entry_hdr->data; |
| 916 | priv->tx_stats[entry_data->hw_queue].len--; | 919 | if (priv->tx_stats[entry_data->hw_queue].len) |
| 920 | priv->tx_stats[entry_data->hw_queue].len--; | ||
| 917 | priv->stats.dot11ACKFailureCount += payload->tries - 1; | 921 | priv->stats.dot11ACKFailureCount += payload->tries - 1; |
| 922 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
| 918 | 923 | ||
| 919 | /* | 924 | /* |
| 920 | * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are | 925 | * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are |
| @@ -1164,21 +1169,23 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
| 1164 | } | 1169 | } |
| 1165 | } | 1170 | } |
| 1166 | 1171 | ||
| 1167 | skb_queue_walk(&priv->tx_queue, entry) { | 1172 | entry = priv->tx_queue.next; |
| 1173 | while (left--) { | ||
| 1168 | u32 hole_size; | 1174 | u32 hole_size; |
| 1169 | info = IEEE80211_SKB_CB(entry); | 1175 | info = IEEE80211_SKB_CB(entry); |
| 1170 | range = (void *)info->rate_driver_data; | 1176 | range = (void *)info->rate_driver_data; |
| 1171 | hole_size = range->start_addr - last_addr; | 1177 | hole_size = range->start_addr - last_addr; |
| 1172 | if (!target_skb && hole_size >= len) { | 1178 | if (!target_skb && hole_size >= len) { |
| 1173 | target_skb = skb_queue_prev(&priv->tx_queue, entry); | 1179 | target_skb = entry->prev; |
| 1174 | hole_size -= len; | 1180 | hole_size -= len; |
| 1175 | target_addr = last_addr; | 1181 | target_addr = last_addr; |
| 1176 | } | 1182 | } |
| 1177 | largest_hole = max(largest_hole, hole_size); | 1183 | largest_hole = max(largest_hole, hole_size); |
| 1178 | last_addr = range->end_addr; | 1184 | last_addr = range->end_addr; |
| 1185 | entry = entry->next; | ||
| 1179 | } | 1186 | } |
| 1180 | if (!target_skb && priv->rx_end - last_addr >= len) { | 1187 | if (!target_skb && priv->rx_end - last_addr >= len) { |
| 1181 | target_skb = skb_peek_tail(&priv->tx_queue); | 1188 | target_skb = priv->tx_queue.prev; |
| 1182 | largest_hole = max(largest_hole, priv->rx_end - last_addr - len); | 1189 | largest_hole = max(largest_hole, priv->rx_end - last_addr - len); |
| 1183 | if (!skb_queue_empty(&priv->tx_queue)) { | 1190 | if (!skb_queue_empty(&priv->tx_queue)) { |
| 1184 | info = IEEE80211_SKB_CB(target_skb); | 1191 | info = IEEE80211_SKB_CB(target_skb); |
| @@ -2084,6 +2091,7 @@ out: | |||
| 2084 | static void p54_stop(struct ieee80211_hw *dev) | 2091 | static void p54_stop(struct ieee80211_hw *dev) |
| 2085 | { | 2092 | { |
| 2086 | struct p54_common *priv = dev->priv; | 2093 | struct p54_common *priv = dev->priv; |
| 2094 | struct sk_buff *skb; | ||
| 2087 | 2095 | ||
| 2088 | mutex_lock(&priv->conf_mutex); | 2096 | mutex_lock(&priv->conf_mutex); |
| 2089 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 2097 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
| @@ -2098,7 +2106,8 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
| 2098 | p54_tx_cancel(dev, priv->cached_beacon); | 2106 | p54_tx_cancel(dev, priv->cached_beacon); |
| 2099 | 2107 | ||
| 2100 | priv->stop(dev); | 2108 | priv->stop(dev); |
| 2101 | skb_queue_purge(&priv->tx_queue); | 2109 | while ((skb = skb_dequeue(&priv->tx_queue))) |
| 2110 | kfree_skb(skb); | ||
| 2102 | priv->cached_beacon = NULL; | 2111 | priv->cached_beacon = NULL; |
| 2103 | priv->tsf_high32 = priv->tsf_low32 = 0; | 2112 | priv->tsf_high32 = priv->tsf_low32 = 0; |
| 2104 | mutex_unlock(&priv->conf_mutex); | 2113 | mutex_unlock(&priv->conf_mutex); |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index b10b0383dfa5..698b11b1cadb 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
| @@ -2427,11 +2427,10 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) | |||
| 2427 | 2427 | ||
| 2428 | #ifdef PCMCIA_DEBUG | 2428 | #ifdef PCMCIA_DEBUG |
| 2429 | if (pc_debug > 3) { | 2429 | if (pc_debug > 3) { |
| 2430 | int i; | 2430 | print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ", |
| 2431 | printk(KERN_DEBUG "skb->data before untranslate"); | 2431 | DUMP_PREFIX_NONE, 16, 1, |
| 2432 | for (i = 0; i < 64; i++) | 2432 | skb->data, 64, true); |
| 2433 | printk("%02x ", skb->data[i]); | 2433 | printk(KERN_DEBUG |
| 2434 | printk("\n" KERN_DEBUG | ||
| 2435 | "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", | 2434 | "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", |
| 2436 | ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, | 2435 | ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, |
| 2437 | psnap->org[0], psnap->org[1], psnap->org[2]); | 2436 | psnap->org[0], psnap->org[1], psnap->org[2]); |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 6af706408ac0..c6d300666ad8 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
| @@ -3556,17 +3556,8 @@ wv_82593_config(struct net_device * dev) | |||
| 3556 | cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ | 3556 | cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ |
| 3557 | 3557 | ||
| 3558 | #ifdef DEBUG_I82593_SHOW | 3558 | #ifdef DEBUG_I82593_SHOW |
| 3559 | { | 3559 | print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE, |
| 3560 | u_char *c = (u_char *) &cfblk; | 3560 | 16, 1, &cfblk, sizeof(struct i82593_conf_block), false); |
| 3561 | int i; | ||
| 3562 | printk(KERN_DEBUG "wavelan_cs: config block:"); | ||
| 3563 | for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++) | ||
| 3564 | { | ||
| 3565 | if((i % 16) == 0) printk("\n" KERN_DEBUG); | ||
| 3566 | printk("%02x ", *c); | ||
| 3567 | } | ||
| 3568 | printk("\n"); | ||
| 3569 | } | ||
| 3570 | #endif | 3561 | #endif |
| 3571 | 3562 | ||
| 3572 | /* Copy the config block to the i82593 */ | 3563 | /* Copy the config block to the i82593 */ |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 14a19baff214..0e6e44689cc6 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -38,7 +38,6 @@ static struct usb_device_id usb_ids[] = { | |||
| 38 | /* ZD1211 */ | 38 | /* ZD1211 */ |
| 39 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, | 39 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, |
| 40 | { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, | 40 | { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, |
| 41 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, | ||
| 42 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, | 41 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, |
| 43 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, | 42 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, |
| 44 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | 43 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, |
| @@ -61,6 +60,7 @@ static struct usb_device_id usb_ids[] = { | |||
| 61 | { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, | 60 | { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, |
| 62 | { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, | 61 | { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, |
| 63 | /* ZD1211B */ | 62 | /* ZD1211B */ |
| 63 | { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B }, | ||
| 64 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | 64 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, |
| 65 | { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, | 65 | { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, |
| 66 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | 66 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, |
| @@ -87,6 +87,7 @@ static struct usb_device_id usb_ids[] = { | |||
| 87 | { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, | 87 | { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, |
| 88 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, | 88 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, |
| 89 | { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, | 89 | { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, |
| 90 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, | ||
| 90 | /* "Driverless" devices that need ejecting */ | 91 | /* "Driverless" devices that need ejecting */ |
| 91 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, | 92 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, |
| 92 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, | 93 | { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, |
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 3c7a5053f1da..a07580138e81 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c | |||
| @@ -109,7 +109,7 @@ static int gx_fix; | |||
| 109 | /* These identify the driver base version and may not be removed. */ | 109 | /* These identify the driver base version and may not be removed. */ |
| 110 | static const char version[] __devinitconst = | 110 | static const char version[] __devinitconst = |
| 111 | KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n" | 111 | KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n" |
| 112 | KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; | 112 | " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; |
| 113 | 113 | ||
| 114 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); | 114 | MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); |
| 115 | MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); | 115 | MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); |
| @@ -700,12 +700,15 @@ static void yellowfin_tx_timeout(struct net_device *dev) | |||
| 700 | int i; | 700 | int i; |
| 701 | printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring); | 701 | printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring); |
| 702 | for (i = 0; i < RX_RING_SIZE; i++) | 702 | for (i = 0; i < RX_RING_SIZE; i++) |
| 703 | printk(" %8.8x", yp->rx_ring[i].result_status); | 703 | printk(KERN_CONT " %8.8x", |
| 704 | printk("\n"KERN_WARNING" Tx ring %p: ", yp->tx_ring); | 704 | yp->rx_ring[i].result_status); |
| 705 | printk(KERN_CONT "\n"); | ||
| 706 | printk(KERN_WARNING" Tx ring %p: ", yp->tx_ring); | ||
| 705 | for (i = 0; i < TX_RING_SIZE; i++) | 707 | for (i = 0; i < TX_RING_SIZE; i++) |
| 706 | printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs, | 708 | printk(KERN_CONT " %4.4x /%8.8x", |
| 707 | yp->tx_ring[i].result_status); | 709 | yp->tx_status[i].tx_errs, |
| 708 | printk("\n"); | 710 | yp->tx_ring[i].result_status); |
| 711 | printk(KERN_CONT "\n"); | ||
| 709 | } | 712 | } |
| 710 | 713 | ||
| 711 | /* If the hardware is found to hang regularly, we will update the code | 714 | /* If the hardware is found to hang regularly, we will update the code |
| @@ -1216,20 +1219,20 @@ static int yellowfin_close(struct net_device *dev) | |||
| 1216 | 1219 | ||
| 1217 | #if defined(__i386__) | 1220 | #if defined(__i386__) |
| 1218 | if (yellowfin_debug > 2) { | 1221 | if (yellowfin_debug > 2) { |
| 1219 | printk("\n"KERN_DEBUG" Tx ring at %8.8llx:\n", | 1222 | printk(KERN_DEBUG" Tx ring at %8.8llx:\n", |
| 1220 | (unsigned long long)yp->tx_ring_dma); | 1223 | (unsigned long long)yp->tx_ring_dma); |
| 1221 | for (i = 0; i < TX_RING_SIZE*2; i++) | 1224 | for (i = 0; i < TX_RING_SIZE*2; i++) |
| 1222 | printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", | 1225 | printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", |
| 1223 | ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', | 1226 | ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', |
| 1224 | i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, | 1227 | i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, |
| 1225 | yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); | 1228 | yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); |
| 1226 | printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); | 1229 | printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); |
| 1227 | for (i = 0; i < TX_RING_SIZE; i++) | 1230 | for (i = 0; i < TX_RING_SIZE; i++) |
| 1228 | printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n", | 1231 | printk(KERN_DEBUG " #%d status %4.4x %4.4x %4.4x %4.4x.\n", |
| 1229 | i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, | 1232 | i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, |
| 1230 | yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); | 1233 | yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); |
| 1231 | 1234 | ||
| 1232 | printk("\n"KERN_DEBUG " Rx ring %8.8llx:\n", | 1235 | printk(KERN_DEBUG " Rx ring %8.8llx:\n", |
| 1233 | (unsigned long long)yp->rx_ring_dma); | 1236 | (unsigned long long)yp->rx_ring_dma); |
| 1234 | for (i = 0; i < RX_RING_SIZE; i++) { | 1237 | for (i = 0; i < RX_RING_SIZE; i++) { |
| 1235 | printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", | 1238 | printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", |
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index e1f6ce03705e..3c2270a8300c 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c | |||
| @@ -33,6 +33,7 @@ void oprofile_reset_stats(void) | |||
| 33 | atomic_set(&oprofile_stats.sample_lost_no_mm, 0); | 33 | atomic_set(&oprofile_stats.sample_lost_no_mm, 0); |
| 34 | atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); | 34 | atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); |
| 35 | atomic_set(&oprofile_stats.event_lost_overflow, 0); | 35 | atomic_set(&oprofile_stats.event_lost_overflow, 0); |
| 36 | atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | 39 | ||
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 5d610cbcfe80..0f0e0b919ef4 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c | |||
| @@ -1134,7 +1134,7 @@ static const struct file_operations ccio_proc_bitmap_fops = { | |||
| 1134 | .llseek = seq_lseek, | 1134 | .llseek = seq_lseek, |
| 1135 | .release = single_release, | 1135 | .release = single_release, |
| 1136 | }; | 1136 | }; |
| 1137 | #endif | 1137 | #endif /* CONFIG_PROC_FS */ |
| 1138 | 1138 | ||
| 1139 | /** | 1139 | /** |
| 1140 | * ccio_find_ioc - Find the ioc in the ioc_list | 1140 | * ccio_find_ioc - Find the ioc in the ioc_list |
| @@ -1568,14 +1568,15 @@ static int __init ccio_probe(struct parisc_device *dev) | |||
| 1568 | /* if this fails, no I/O cards will work, so may as well bug */ | 1568 | /* if this fails, no I/O cards will work, so may as well bug */ |
| 1569 | BUG_ON(dev->dev.platform_data == NULL); | 1569 | BUG_ON(dev->dev.platform_data == NULL); |
| 1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; | 1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; |
| 1571 | 1571 | ||
| 1572 | #ifdef CONFIG_PROC_FS | ||
| 1572 | if (ioc_count == 0) { | 1573 | if (ioc_count == 0) { |
| 1573 | proc_create(MODULE_NAME, 0, proc_runway_root, | 1574 | proc_create(MODULE_NAME, 0, proc_runway_root, |
| 1574 | &ccio_proc_info_fops); | 1575 | &ccio_proc_info_fops); |
| 1575 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, | 1576 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, |
| 1576 | &ccio_proc_bitmap_fops); | 1577 | &ccio_proc_bitmap_fops); |
| 1577 | } | 1578 | } |
| 1578 | 1579 | #endif | |
| 1579 | ioc_count++; | 1580 | ioc_count++; |
| 1580 | 1581 | ||
| 1581 | parisc_has_iommu(); | 1582 | parisc_has_iommu(); |
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 52ae0b1d470c..c590974e9815 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c | |||
| @@ -353,7 +353,7 @@ static unsigned int dino_startup_irq(unsigned int irq) | |||
| 353 | return 0; | 353 | return 0; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static struct hw_interrupt_type dino_interrupt_type = { | 356 | static struct irq_chip dino_interrupt_type = { |
| 357 | .typename = "GSC-PCI", | 357 | .typename = "GSC-PCI", |
| 358 | .startup = dino_startup_irq, | 358 | .startup = dino_startup_irq, |
| 359 | .shutdown = dino_disable_irq, | 359 | .shutdown = dino_disable_irq, |
| @@ -1019,22 +1019,22 @@ static int __init dino_probe(struct parisc_device *dev) | |||
| 1019 | ** It's not used to avoid chicken/egg problems | 1019 | ** It's not used to avoid chicken/egg problems |
| 1020 | ** with configuration accessor functions. | 1020 | ** with configuration accessor functions. |
| 1021 | */ | 1021 | */ |
| 1022 | bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, | 1022 | dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev, |
| 1023 | &dino_cfg_ops, NULL); | 1023 | dino_current_bus, &dino_cfg_ops, NULL); |
| 1024 | |||
| 1024 | if(bus) { | 1025 | if(bus) { |
| 1025 | pci_bus_add_devices(bus); | ||
| 1026 | /* This code *depends* on scanning being single threaded | 1026 | /* This code *depends* on scanning being single threaded |
| 1027 | * if it isn't, this global bus number count will fail | 1027 | * if it isn't, this global bus number count will fail |
| 1028 | */ | 1028 | */ |
| 1029 | dino_current_bus = bus->subordinate + 1; | 1029 | dino_current_bus = bus->subordinate + 1; |
| 1030 | pci_bus_assign_resources(bus); | 1030 | pci_bus_assign_resources(bus); |
| 1031 | pci_bus_add_devices(bus); | ||
| 1031 | } else { | 1032 | } else { |
| 1032 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", | 1033 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", |
| 1033 | dev_name(&dev->dev), dino_current_bus); | 1034 | dev_name(&dev->dev), dino_current_bus); |
| 1034 | /* increment the bus number in case of duplicates */ | 1035 | /* increment the bus number in case of duplicates */ |
| 1035 | dino_current_bus++; | 1036 | dino_current_bus++; |
| 1036 | } | 1037 | } |
| 1037 | dino_dev->hba.hba_bus = bus; | ||
| 1038 | return 0; | 1038 | return 0; |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 5b89f404e668..51220749cb65 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c | |||
| @@ -188,7 +188,7 @@ static unsigned int eisa_startup_irq(unsigned int irq) | |||
| 188 | return 0; | 188 | return 0; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static struct hw_interrupt_type eisa_interrupt_type = { | 191 | static struct irq_chip eisa_interrupt_type = { |
| 192 | .typename = "EISA", | 192 | .typename = "EISA", |
| 193 | .startup = eisa_startup_irq, | 193 | .startup = eisa_startup_irq, |
| 194 | .shutdown = eisa_disable_irq, | 194 | .shutdown = eisa_disable_irq, |
diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index c709ecc2b7f7..0be1d50645ab 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c | |||
| @@ -101,7 +101,7 @@ static int configure_memory(const unsigned char *buf, | |||
| 101 | printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); | 101 | printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); |
| 102 | result = request_resource(mem_parent, res); | 102 | result = request_resource(mem_parent, res); |
| 103 | if (result < 0) { | 103 | if (result < 0) { |
| 104 | printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); | 104 | printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); |
| 105 | return result; | 105 | return result; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| @@ -191,7 +191,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, | |||
| 191 | printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); | 191 | printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); |
| 192 | result = request_resource(io_parent, res); | 192 | result = request_resource(io_parent, res); |
| 193 | if (result < 0) { | 193 | if (result < 0) { |
| 194 | printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); | 194 | printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); |
| 195 | return result; | 195 | return result; |
| 196 | } | 196 | } |
| 197 | } | 197 | } |
| @@ -224,7 +224,7 @@ static int configure_port_init(const unsigned char *buf) | |||
| 224 | case HPEE_PORT_INIT_WIDTH_BYTE: | 224 | case HPEE_PORT_INIT_WIDTH_BYTE: |
| 225 | s=1; | 225 | s=1; |
| 226 | if (c & HPEE_PORT_INIT_MASK) { | 226 | if (c & HPEE_PORT_INIT_MASK) { |
| 227 | printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); | 227 | printk(KERN_WARNING "port_init: unverified mask attribute\n"); |
| 228 | outb((inb(get_16(buf+len+1) & | 228 | outb((inb(get_16(buf+len+1) & |
| 229 | get_8(buf+len+3)) | | 229 | get_8(buf+len+3)) | |
| 230 | get_8(buf+len+4)), get_16(buf+len+1)); | 230 | get_8(buf+len+4)), get_16(buf+len+1)); |
| @@ -249,7 +249,7 @@ static int configure_port_init(const unsigned char *buf) | |||
| 249 | case HPEE_PORT_INIT_WIDTH_DWORD: | 249 | case HPEE_PORT_INIT_WIDTH_DWORD: |
| 250 | s=4; | 250 | s=4; |
| 251 | if (c & HPEE_PORT_INIT_MASK) { | 251 | if (c & HPEE_PORT_INIT_MASK) { |
| 252 | printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); | 252 | printk(KERN_WARNING "port_init: unverified mask attribute\n"); |
| 253 | outl((inl(get_16(buf+len+1) & | 253 | outl((inl(get_16(buf+len+1) & |
| 254 | get_32(buf+len+3)) | | 254 | get_32(buf+len+3)) | |
| 255 | get_32(buf+len+7)), get_16(buf+len+1)); | 255 | get_32(buf+len+7)), get_16(buf+len+1)); |
| @@ -259,7 +259,7 @@ static int configure_port_init(const unsigned char *buf) | |||
| 259 | 259 | ||
| 260 | break; | 260 | break; |
| 261 | default: | 261 | default: |
| 262 | printk("\n" KERN_ERR "Invalid port init word %02x\n", c); | 262 | printk(KERN_ERR "Invalid port init word %02x\n", c); |
| 263 | return 0; | 263 | return 0; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| @@ -297,7 +297,7 @@ static int configure_type_string(const unsigned char *buf) | |||
| 297 | /* just skip past the type field */ | 297 | /* just skip past the type field */ |
| 298 | len = get_8(buf); | 298 | len = get_8(buf); |
| 299 | if (len > 80) { | 299 | if (len > 80) { |
| 300 | printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); | 300 | printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | return 1+len; | 303 | return 1+len; |
| @@ -398,7 +398,7 @@ static int parse_slot_config(int slot, | |||
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | if (p0 + function_len < pos) { | 400 | if (p0 + function_len < pos) { |
| 401 | printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match " | 401 | printk(KERN_ERR "eisa_enumerator: function %d length mis-match " |
| 402 | "got %d, expected %d\n", | 402 | "got %d, expected %d\n", |
| 403 | num_func, pos-p0, function_len); | 403 | num_func, pos-p0, function_len); |
| 404 | res=-1; | 404 | res=-1; |
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index d33632917696..647adc9f85ad 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c | |||
| @@ -148,7 +148,7 @@ static unsigned int gsc_asic_startup_irq(unsigned int irq) | |||
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static struct hw_interrupt_type gsc_asic_interrupt_type = { | 151 | static struct irq_chip gsc_asic_interrupt_type = { |
| 152 | .typename = "GSC-ASIC", | 152 | .typename = "GSC-ASIC", |
| 153 | .startup = gsc_asic_startup_irq, | 153 | .startup = gsc_asic_startup_irq, |
| 154 | .shutdown = gsc_asic_disable_irq, | 154 | .shutdown = gsc_asic_disable_irq, |
| @@ -158,7 +158,7 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = { | |||
| 158 | .end = no_end_irq, | 158 | .end = no_end_irq, |
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data) | 161 | int gsc_assign_irq(struct irq_chip *type, void *data) |
| 162 | { | 162 | { |
| 163 | static int irq = GSC_IRQ_BASE; | 163 | static int irq = GSC_IRQ_BASE; |
| 164 | struct irq_desc *desc; | 164 | struct irq_desc *desc; |
diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h index 762a1babad60..b9d7bfb68e24 100644 --- a/drivers/parisc/gsc.h +++ b/drivers/parisc/gsc.h | |||
| @@ -38,7 +38,7 @@ struct gsc_asic { | |||
| 38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); | 38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); |
| 39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ | 39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ |
| 40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ | 40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ |
| 41 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data); | 41 | int gsc_assign_irq(struct irq_chip *type, void *data); |
| 42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); | 42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); |
| 43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, | 43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, |
| 44 | void (*choose)(struct parisc_device *child, void *ctrl)); | 44 | void (*choose)(struct parisc_device *child, void *ctrl)); |
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 4a9cc92d4d18..88e333553212 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
| @@ -729,7 +729,7 @@ static int iosapic_set_affinity_irq(unsigned int irq, | |||
| 729 | } | 729 | } |
| 730 | #endif | 730 | #endif |
| 731 | 731 | ||
| 732 | static struct hw_interrupt_type iosapic_interrupt_type = { | 732 | static struct irq_chip iosapic_interrupt_type = { |
| 733 | .typename = "IO-SAPIC-level", | 733 | .typename = "IO-SAPIC-level", |
| 734 | .startup = iosapic_startup_irq, | 734 | .startup = iosapic_startup_irq, |
| 735 | .shutdown = iosapic_disable_irq, | 735 | .shutdown = iosapic_disable_irq, |
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 59fbbf128365..ede614616f8e 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
| @@ -980,28 +980,38 @@ static void | |||
| 980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | 980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) |
| 981 | { | 981 | { |
| 982 | unsigned long bytecnt; | 982 | unsigned long bytecnt; |
| 983 | pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ | ||
| 984 | pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ | ||
| 985 | long io_count; | 983 | long io_count; |
| 986 | long status; /* PDC return status */ | 984 | long status; /* PDC return status */ |
| 987 | long pa_count; | 985 | long pa_count; |
| 986 | pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ | ||
| 987 | pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ | ||
| 988 | int i; | 988 | int i; |
| 989 | 989 | ||
| 990 | pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
| 991 | if (!pa_pdc_cell) | ||
| 992 | return; | ||
| 993 | |||
| 994 | io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
| 995 | if (!pa_pdc_cell) { | ||
| 996 | kfree(pa_pdc_cell); | ||
| 997 | return; | ||
| 998 | } | ||
| 999 | |||
| 990 | /* return cell module (IO view) */ | 1000 | /* return cell module (IO view) */ |
| 991 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1001 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
| 992 | PA_VIEW, & pa_pdc_cell); | 1002 | PA_VIEW, pa_pdc_cell); |
| 993 | pa_count = pa_pdc_cell.mod[1]; | 1003 | pa_count = pa_pdc_cell->mod[1]; |
| 994 | 1004 | ||
| 995 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1005 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
| 996 | IO_VIEW, &io_pdc_cell); | 1006 | IO_VIEW, io_pdc_cell); |
| 997 | io_count = io_pdc_cell.mod[1]; | 1007 | io_count = io_pdc_cell->mod[1]; |
| 998 | 1008 | ||
| 999 | /* We've already done this once for device discovery...*/ | 1009 | /* We've already done this once for device discovery...*/ |
| 1000 | if (status != PDC_OK) { | 1010 | if (status != PDC_OK) { |
| 1001 | panic("pdc_pat_cell_module() call failed for LBA!\n"); | 1011 | panic("pdc_pat_cell_module() call failed for LBA!\n"); |
| 1002 | } | 1012 | } |
| 1003 | 1013 | ||
| 1004 | if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { | 1014 | if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { |
| 1005 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); | 1015 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); |
| 1006 | } | 1016 | } |
| 1007 | 1017 | ||
| @@ -1016,8 +1026,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
| 1016 | } *p, *io; | 1026 | } *p, *io; |
| 1017 | struct resource *r; | 1027 | struct resource *r; |
| 1018 | 1028 | ||
| 1019 | p = (void *) &(pa_pdc_cell.mod[2+i*3]); | 1029 | p = (void *) &(pa_pdc_cell->mod[2+i*3]); |
| 1020 | io = (void *) &(io_pdc_cell.mod[2+i*3]); | 1030 | io = (void *) &(io_pdc_cell->mod[2+i*3]); |
| 1021 | 1031 | ||
| 1022 | /* Convert the PAT range data to PCI "struct resource" */ | 1032 | /* Convert the PAT range data to PCI "struct resource" */ |
| 1023 | switch(p->type & 0xff) { | 1033 | switch(p->type & 0xff) { |
| @@ -1096,6 +1106,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
| 1096 | break; | 1106 | break; |
| 1097 | } | 1107 | } |
| 1098 | } | 1108 | } |
| 1109 | |||
| 1110 | kfree(pa_pdc_cell); | ||
| 1111 | kfree(io_pdc_cell); | ||
| 1099 | } | 1112 | } |
| 1100 | #else | 1113 | #else |
| 1101 | /* keep compiler from complaining about missing declarations */ | 1114 | /* keep compiler from complaining about missing declarations */ |
| @@ -1509,10 +1522,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
| 1509 | lba_bus = lba_dev->hba.hba_bus = | 1522 | lba_bus = lba_dev->hba.hba_bus = |
| 1510 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, | 1523 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, |
| 1511 | cfg_ops, NULL); | 1524 | cfg_ops, NULL); |
| 1512 | if (lba_bus) { | ||
| 1513 | lba_next_bus = lba_bus->subordinate + 1; | ||
| 1514 | pci_bus_add_devices(lba_bus); | ||
| 1515 | } | ||
| 1516 | 1525 | ||
| 1517 | /* This is in lieu of calling pci_assign_unassigned_resources() */ | 1526 | /* This is in lieu of calling pci_assign_unassigned_resources() */ |
| 1518 | if (is_pdc_pat()) { | 1527 | if (is_pdc_pat()) { |
| @@ -1533,7 +1542,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
| 1533 | } | 1542 | } |
| 1534 | pci_enable_bridges(lba_bus); | 1543 | pci_enable_bridges(lba_bus); |
| 1535 | 1544 | ||
| 1536 | |||
| 1537 | /* | 1545 | /* |
| 1538 | ** Once PCI register ops has walked the bus, access to config | 1546 | ** Once PCI register ops has walked the bus, access to config |
| 1539 | ** space is restricted. Avoids master aborts on config cycles. | 1547 | ** space is restricted. Avoids master aborts on config cycles. |
| @@ -1543,6 +1551,11 @@ lba_driver_probe(struct parisc_device *dev) | |||
| 1543 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; | 1551 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; |
| 1544 | } | 1552 | } |
| 1545 | 1553 | ||
| 1554 | if (lba_bus) { | ||
| 1555 | lba_next_bus = lba_bus->subordinate + 1; | ||
| 1556 | pci_bus_add_devices(lba_bus); | ||
| 1557 | } | ||
| 1558 | |||
| 1546 | /* Whew! Finally done! Tell services we got this one covered. */ | 1559 | /* Whew! Finally done! Tell services we got this one covered. */ |
| 1547 | return 0; | 1560 | return 0; |
| 1548 | } | 1561 | } |
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index d46dd57450ac..123d8fe3427d 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
| @@ -2057,6 +2057,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) | |||
| 2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; | 2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; |
| 2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); | 2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); |
| 2059 | r->end = r->start + size; | 2059 | r->end = r->start + size; |
| 2060 | r->flags = IORESOURCE_MEM; | ||
| 2060 | } | 2061 | } |
| 2061 | } | 2062 | } |
| 2062 | 2063 | ||
| @@ -2093,4 +2094,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) | |||
| 2093 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; | 2094 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; |
| 2094 | r->start += rope * (size + 1); /* adjust base for this rope */ | 2095 | r->start += rope * (size + 1); /* adjust base for this rope */ |
| 2095 | r->end = r->start + size; | 2096 | r->end = r->start + size; |
| 2097 | r->flags = IORESOURCE_MEM; | ||
| 2096 | } | 2098 | } |
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 33e5ade774ca..675f04e6597a 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c | |||
| @@ -325,7 +325,7 @@ static unsigned int superio_startup_irq(unsigned int irq) | |||
| 325 | return 0; | 325 | return 0; |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | static struct hw_interrupt_type superio_interrupt_type = { | 328 | static struct irq_chip superio_interrupt_type = { |
| 329 | .typename = SUPERIO, | 329 | .typename = SUPERIO, |
| 330 | .startup = superio_startup_irq, | 330 | .startup = superio_startup_irq, |
| 331 | .shutdown = superio_disable_irq, | 331 | .shutdown = superio_disable_irq, |
| @@ -434,8 +434,8 @@ static void __init superio_parport_init(void) | |||
| 434 | 0 /*base_hi*/, | 434 | 0 /*base_hi*/, |
| 435 | PAR_IRQ, | 435 | PAR_IRQ, |
| 436 | PARPORT_DMA_NONE /* dma */, | 436 | PARPORT_DMA_NONE /* dma */, |
| 437 | NULL /*struct pci_dev* */), | 437 | NULL /*struct pci_dev* */, |
| 438 | 0 /* shared irq flags */ ) | 438 | 0 /* shared irq flags */)) |
| 439 | 439 | ||
| 440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); | 440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); |
| 441 | #endif /* CONFIG_PARPORT_PC */ | 441 | #endif /* CONFIG_PARPORT_PC */ |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 1032d5fdbd42..2597145a066e 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
| @@ -2907,6 +2907,7 @@ enum parport_pc_pci_cards { | |||
| 2907 | netmos_9755, | 2907 | netmos_9755, |
| 2908 | netmos_9805, | 2908 | netmos_9805, |
| 2909 | netmos_9815, | 2909 | netmos_9815, |
| 2910 | netmos_9901, | ||
| 2910 | quatech_sppxp100, | 2911 | quatech_sppxp100, |
| 2911 | }; | 2912 | }; |
| 2912 | 2913 | ||
| @@ -2987,7 +2988,7 @@ static struct parport_pc_pci { | |||
| 2987 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, | 2988 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, |
| 2988 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, | 2989 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, |
| 2989 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, | 2990 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, |
| 2990 | 2991 | /* netmos_9901 */ { 1, { { 0, -1 }, } }, | |
| 2991 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | 2992 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, |
| 2992 | }; | 2993 | }; |
| 2993 | 2994 | ||
| @@ -3089,6 +3090,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
| 3089 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, | 3090 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, |
| 3090 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, | 3091 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, |
| 3091 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 3092 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
| 3093 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | ||
| 3094 | 0xA000, 0x2000, 0, 0, netmos_9901 }, | ||
| 3092 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ | 3095 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ |
| 3093 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, | 3096 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, |
| 3094 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | 3097 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index fbc63d5e459f..eb159587d0bf 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -354,7 +354,7 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
| 354 | status = acpi_run_hpp(handle, hpp); | 354 | status = acpi_run_hpp(handle, hpp); |
| 355 | if (ACPI_SUCCESS(status)) | 355 | if (ACPI_SUCCESS(status)) |
| 356 | break; | 356 | break; |
| 357 | if (acpi_root_bridge(handle)) | 357 | if (acpi_is_root_bridge(handle)) |
| 358 | break; | 358 | break; |
| 359 | status = acpi_get_parent(handle, &phandle); | 359 | status = acpi_get_parent(handle, &phandle); |
| 360 | if (ACPI_FAILURE(status)) | 360 | if (ACPI_FAILURE(status)) |
| @@ -428,7 +428,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
| 428 | status = acpi_run_oshp(handle); | 428 | status = acpi_run_oshp(handle); |
| 429 | if (ACPI_SUCCESS(status)) | 429 | if (ACPI_SUCCESS(status)) |
| 430 | goto got_one; | 430 | goto got_one; |
| 431 | if (acpi_root_bridge(handle)) | 431 | if (acpi_is_root_bridge(handle)) |
| 432 | break; | 432 | break; |
| 433 | chandle = handle; | 433 | chandle = handle; |
| 434 | status = acpi_get_parent(chandle, &handle); | 434 | status = acpi_get_parent(chandle, &handle); |
| @@ -449,42 +449,6 @@ got_one: | |||
| 449 | } | 449 | } |
| 450 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); | 450 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); |
| 451 | 451 | ||
| 452 | /* acpi_root_bridge - check to see if this acpi object is a root bridge | ||
| 453 | * | ||
| 454 | * @handle - the acpi object in question. | ||
| 455 | */ | ||
| 456 | int acpi_root_bridge(acpi_handle handle) | ||
| 457 | { | ||
| 458 | acpi_status status; | ||
| 459 | struct acpi_device_info *info; | ||
| 460 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 461 | int i; | ||
| 462 | |||
| 463 | status = acpi_get_object_info(handle, &buffer); | ||
| 464 | if (ACPI_SUCCESS(status)) { | ||
| 465 | info = buffer.pointer; | ||
| 466 | if ((info->valid & ACPI_VALID_HID) && | ||
| 467 | !strcmp(PCI_ROOT_HID_STRING, | ||
| 468 | info->hardware_id.value)) { | ||
| 469 | kfree(buffer.pointer); | ||
| 470 | return 1; | ||
| 471 | } | ||
| 472 | if (info->valid & ACPI_VALID_CID) { | ||
| 473 | for (i=0; i < info->compatibility_id.count; i++) { | ||
| 474 | if (!strcmp(PCI_ROOT_HID_STRING, | ||
| 475 | info->compatibility_id.id[i].value)) { | ||
| 476 | kfree(buffer.pointer); | ||
| 477 | return 1; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | } | ||
| 481 | kfree(buffer.pointer); | ||
| 482 | } | ||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | EXPORT_SYMBOL_GPL(acpi_root_bridge); | ||
| 486 | |||
| 487 | |||
| 488 | static int is_ejectable(acpi_handle handle) | 452 | static int is_ejectable(acpi_handle handle) |
| 489 | { | 453 | { |
| 490 | acpi_status status; | 454 | acpi_status status; |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 3a6064bce561..0cb0f830a993 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -678,18 +678,9 @@ static void remove_bridge(acpi_handle handle) | |||
| 678 | 678 | ||
| 679 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) | 679 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) |
| 680 | { | 680 | { |
| 681 | struct acpi_pci_id id; | ||
| 682 | struct pci_bus *bus; | ||
| 683 | struct pci_dev *dev; | 681 | struct pci_dev *dev; |
| 684 | 682 | ||
| 685 | if (ACPI_FAILURE(acpi_get_pci_id(handle, &id))) | 683 | dev = acpi_get_pci_dev(handle); |
| 686 | return NULL; | ||
| 687 | |||
| 688 | bus = pci_find_bus(id.segment, id.bus); | ||
| 689 | if (!bus) | ||
| 690 | return NULL; | ||
| 691 | |||
| 692 | dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function)); | ||
| 693 | if (!dev) | 684 | if (!dev) |
| 694 | return NULL; | 685 | return NULL; |
| 695 | 686 | ||
| @@ -1396,19 +1387,16 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
| 1396 | /* Program resources in newly inserted bridge */ | 1387 | /* Program resources in newly inserted bridge */ |
| 1397 | static int acpiphp_configure_bridge (acpi_handle handle) | 1388 | static int acpiphp_configure_bridge (acpi_handle handle) |
| 1398 | { | 1389 | { |
| 1399 | struct acpi_pci_id pci_id; | 1390 | struct pci_dev *dev; |
| 1400 | struct pci_bus *bus; | 1391 | struct pci_bus *bus; |
| 1401 | 1392 | ||
| 1402 | if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) { | 1393 | dev = acpi_get_pci_dev(handle); |
| 1394 | if (!dev) { | ||
| 1403 | err("cannot get PCI domain and bus number for bridge\n"); | 1395 | err("cannot get PCI domain and bus number for bridge\n"); |
| 1404 | return -EINVAL; | 1396 | return -EINVAL; |
| 1405 | } | 1397 | } |
| 1406 | bus = pci_find_bus(pci_id.segment, pci_id.bus); | 1398 | |
| 1407 | if (!bus) { | 1399 | bus = dev->bus; |
| 1408 | err("cannot find bus %d:%d\n", | ||
| 1409 | pci_id.segment, pci_id.bus); | ||
| 1410 | return -EINVAL; | ||
| 1411 | } | ||
| 1412 | 1400 | ||
| 1413 | pci_bus_size_bridges(bus); | 1401 | pci_bus_size_bridges(bus); |
| 1414 | pci_bus_assign_resources(bus); | 1402 | pci_bus_assign_resources(bus); |
| @@ -1416,6 +1404,7 @@ static int acpiphp_configure_bridge (acpi_handle handle) | |||
| 1416 | acpiphp_set_hpp_values(handle, bus); | 1404 | acpiphp_set_hpp_values(handle, bus); |
| 1417 | pci_enable_bridges(bus); | 1405 | pci_enable_bridges(bus); |
| 1418 | acpiphp_configure_ioapics(handle); | 1406 | acpiphp_configure_ioapics(handle); |
| 1407 | pci_dev_put(dev); | ||
| 1419 | return 0; | 1408 | return 0; |
| 1420 | } | 1409 | } |
| 1421 | 1410 | ||
| @@ -1631,7 +1620,7 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 1631 | { | 1620 | { |
| 1632 | int *count = (int *)context; | 1621 | int *count = (int *)context; |
| 1633 | 1622 | ||
| 1634 | if (acpi_root_bridge(handle)) { | 1623 | if (acpi_is_root_bridge(handle)) { |
| 1635 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1624 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
| 1636 | handle_hotplug_event_bridge, NULL); | 1625 | handle_hotplug_event_bridge, NULL); |
| 1637 | (*count)++; | 1626 | (*count)++; |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index a5b9f6ae507b..d703e73fffa7 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <linux/pci_hotplug.h> | 32 | #include <linux/pci_hotplug.h> |
| 33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 35 | #include <linux/smp_lock.h> | ||
| 36 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
| 37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
| 38 | #include <linux/kthread.h> | 37 | #include <linux/kthread.h> |
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 2fa47af992a8..0ff689afa757 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
| 36 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
| 37 | #include <linux/smp_lock.h> | ||
| 38 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
| 39 | #include <linux/pci_hotplug.h> | 38 | #include <linux/pci_hotplug.h> |
| 40 | #include <linux/kthread.h> | 39 | #include <linux/kthread.h> |
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 8450f4a6568a..e6089bdb6e5b 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include <linux/pci_hotplug.h> | 35 | #include <linux/pci_hotplug.h> |
| 36 | #include <linux/smp_lock.h> | ||
| 36 | #include <linux/debugfs.h> | 37 | #include <linux/debugfs.h> |
| 37 | #include "cpqphp.h" | 38 | #include "cpqphp.h" |
| 38 | 39 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 844580489d4d..5c5043f239cf 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name) | |||
| 555 | * @slot: pointer to the &struct hotplug_slot to register | 555 | * @slot: pointer to the &struct hotplug_slot to register |
| 556 | * @devnr: device number | 556 | * @devnr: device number |
| 557 | * @name: name registered with kobject core | 557 | * @name: name registered with kobject core |
| 558 | * @owner: caller module owner | ||
| 559 | * @mod_name: caller module name | ||
| 558 | * | 560 | * |
| 559 | * Registers a hotplug slot with the pci hotplug subsystem, which will allow | 561 | * Registers a hotplug slot with the pci hotplug subsystem, which will allow |
| 560 | * userspace interaction to the slot. | 562 | * userspace interaction to the slot. |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index ff4034502d24..8aab8edf123e 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/smp_lock.h> | ||
| 34 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 35 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
| 36 | #include "../pci.h" | 35 | #include "../pci.h" |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 178853a07440..ebc9b8dca881 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -56,14 +56,32 @@ | |||
| 56 | #define MAX_AGAW_WIDTH 64 | 56 | #define MAX_AGAW_WIDTH 64 |
| 57 | 57 | ||
| 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) | 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) |
| 59 | #define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) | ||
| 59 | 60 | ||
| 60 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) | 61 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) |
| 61 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | 62 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) |
| 62 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) | 63 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) |
| 63 | 64 | ||
| 64 | #ifndef PHYSICAL_PAGE_MASK | 65 | |
| 65 | #define PHYSICAL_PAGE_MASK PAGE_MASK | 66 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things |
| 66 | #endif | 67 | are never going to work. */ |
| 68 | static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn) | ||
| 69 | { | ||
| 70 | return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn) | ||
| 74 | { | ||
| 75 | return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
| 76 | } | ||
| 77 | static inline unsigned long page_to_dma_pfn(struct page *pg) | ||
| 78 | { | ||
| 79 | return mm_to_dma_pfn(page_to_pfn(pg)); | ||
| 80 | } | ||
| 81 | static inline unsigned long virt_to_dma_pfn(void *p) | ||
| 82 | { | ||
| 83 | return page_to_dma_pfn(virt_to_page(p)); | ||
| 84 | } | ||
| 67 | 85 | ||
| 68 | /* global iommu list, set NULL for ignored DMAR units */ | 86 | /* global iommu list, set NULL for ignored DMAR units */ |
| 69 | static struct intel_iommu **g_iommus; | 87 | static struct intel_iommu **g_iommus; |
| @@ -204,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot) | |||
| 204 | 222 | ||
| 205 | static inline u64 dma_pte_addr(struct dma_pte *pte) | 223 | static inline u64 dma_pte_addr(struct dma_pte *pte) |
| 206 | { | 224 | { |
| 207 | return (pte->val & VTD_PAGE_MASK); | 225 | #ifdef CONFIG_64BIT |
| 226 | return pte->val & VTD_PAGE_MASK; | ||
| 227 | #else | ||
| 228 | /* Must have a full atomic 64-bit read */ | ||
| 229 | return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; | ||
| 230 | #endif | ||
| 208 | } | 231 | } |
| 209 | 232 | ||
| 210 | static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr) | 233 | static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) |
| 211 | { | 234 | { |
| 212 | pte->val |= (addr & VTD_PAGE_MASK); | 235 | pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT; |
| 213 | } | 236 | } |
| 214 | 237 | ||
| 215 | static inline bool dma_pte_present(struct dma_pte *pte) | 238 | static inline bool dma_pte_present(struct dma_pte *pte) |
| @@ -217,6 +240,19 @@ static inline bool dma_pte_present(struct dma_pte *pte) | |||
| 217 | return (pte->val & 3) != 0; | 240 | return (pte->val & 3) != 0; |
| 218 | } | 241 | } |
| 219 | 242 | ||
| 243 | static inline int first_pte_in_page(struct dma_pte *pte) | ||
| 244 | { | ||
| 245 | return !((unsigned long)pte & ~VTD_PAGE_MASK); | ||
| 246 | } | ||
| 247 | |||
| 248 | /* | ||
| 249 | * This domain is a statically identity mapping domain. | ||
| 250 | * 1. This domain creats a static 1:1 mapping to all usable memory. | ||
| 251 | * 2. It maps to each iommu if successful. | ||
| 252 | * 3. Each iommu mapps to this domain if successful. | ||
| 253 | */ | ||
| 254 | struct dmar_domain *si_domain; | ||
| 255 | |||
| 220 | /* devices under the same p2p bridge are owned in one domain */ | 256 | /* devices under the same p2p bridge are owned in one domain */ |
| 221 | #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) | 257 | #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) |
| 222 | 258 | ||
| @@ -225,6 +261,9 @@ static inline bool dma_pte_present(struct dma_pte *pte) | |||
| 225 | */ | 261 | */ |
| 226 | #define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1) | 262 | #define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1) |
| 227 | 263 | ||
| 264 | /* si_domain contains mulitple devices */ | ||
| 265 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) | ||
| 266 | |||
| 228 | struct dmar_domain { | 267 | struct dmar_domain { |
| 229 | int id; /* domain id */ | 268 | int id; /* domain id */ |
| 230 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ | 269 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ |
| @@ -233,7 +272,6 @@ struct dmar_domain { | |||
| 233 | struct iova_domain iovad; /* iova's that belong to this domain */ | 272 | struct iova_domain iovad; /* iova's that belong to this domain */ |
| 234 | 273 | ||
| 235 | struct dma_pte *pgd; /* virtual address */ | 274 | struct dma_pte *pgd; /* virtual address */ |
| 236 | spinlock_t mapping_lock; /* page table lock */ | ||
| 237 | int gaw; /* max guest address width */ | 275 | int gaw; /* max guest address width */ |
| 238 | 276 | ||
| 239 | /* adjusted guest address width, 0 is level 2 30-bit */ | 277 | /* adjusted guest address width, 0 is level 2 30-bit */ |
| @@ -435,12 +473,14 @@ int iommu_calculate_agaw(struct intel_iommu *iommu) | |||
| 435 | return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH); | 473 | return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
| 436 | } | 474 | } |
| 437 | 475 | ||
| 438 | /* in native case, each domain is related to only one iommu */ | 476 | /* This functionin only returns single iommu in a domain */ |
| 439 | static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | 477 | static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) |
| 440 | { | 478 | { |
| 441 | int iommu_id; | 479 | int iommu_id; |
| 442 | 480 | ||
| 481 | /* si_domain and vm domain should not get here. */ | ||
| 443 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); | 482 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); |
| 483 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); | ||
| 444 | 484 | ||
| 445 | iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | 485 | iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); |
| 446 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) | 486 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) |
| @@ -635,80 +675,78 @@ static inline int width_to_agaw(int width) | |||
| 635 | 675 | ||
| 636 | static inline unsigned int level_to_offset_bits(int level) | 676 | static inline unsigned int level_to_offset_bits(int level) |
| 637 | { | 677 | { |
| 638 | return (12 + (level - 1) * LEVEL_STRIDE); | 678 | return (level - 1) * LEVEL_STRIDE; |
| 639 | } | 679 | } |
| 640 | 680 | ||
| 641 | static inline int address_level_offset(u64 addr, int level) | 681 | static inline int pfn_level_offset(unsigned long pfn, int level) |
| 642 | { | 682 | { |
| 643 | return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); | 683 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; |
| 644 | } | 684 | } |
| 645 | 685 | ||
| 646 | static inline u64 level_mask(int level) | 686 | static inline unsigned long level_mask(int level) |
| 647 | { | 687 | { |
| 648 | return ((u64)-1 << level_to_offset_bits(level)); | 688 | return -1UL << level_to_offset_bits(level); |
| 649 | } | 689 | } |
| 650 | 690 | ||
| 651 | static inline u64 level_size(int level) | 691 | static inline unsigned long level_size(int level) |
| 652 | { | 692 | { |
| 653 | return ((u64)1 << level_to_offset_bits(level)); | 693 | return 1UL << level_to_offset_bits(level); |
| 654 | } | 694 | } |
| 655 | 695 | ||
| 656 | static inline u64 align_to_level(u64 addr, int level) | 696 | static inline unsigned long align_to_level(unsigned long pfn, int level) |
| 657 | { | 697 | { |
| 658 | return ((addr + level_size(level) - 1) & level_mask(level)); | 698 | return (pfn + level_size(level) - 1) & level_mask(level); |
| 659 | } | 699 | } |
| 660 | 700 | ||
| 661 | static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) | 701 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
| 702 | unsigned long pfn) | ||
| 662 | { | 703 | { |
| 663 | int addr_width = agaw_to_width(domain->agaw); | 704 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 664 | struct dma_pte *parent, *pte = NULL; | 705 | struct dma_pte *parent, *pte = NULL; |
| 665 | int level = agaw_to_level(domain->agaw); | 706 | int level = agaw_to_level(domain->agaw); |
| 666 | int offset; | 707 | int offset; |
| 667 | unsigned long flags; | ||
| 668 | 708 | ||
| 669 | BUG_ON(!domain->pgd); | 709 | BUG_ON(!domain->pgd); |
| 670 | 710 | BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); | |
| 671 | addr &= (((u64)1) << addr_width) - 1; | ||
| 672 | parent = domain->pgd; | 711 | parent = domain->pgd; |
| 673 | 712 | ||
| 674 | spin_lock_irqsave(&domain->mapping_lock, flags); | ||
| 675 | while (level > 0) { | 713 | while (level > 0) { |
| 676 | void *tmp_page; | 714 | void *tmp_page; |
| 677 | 715 | ||
| 678 | offset = address_level_offset(addr, level); | 716 | offset = pfn_level_offset(pfn, level); |
| 679 | pte = &parent[offset]; | 717 | pte = &parent[offset]; |
| 680 | if (level == 1) | 718 | if (level == 1) |
| 681 | break; | 719 | break; |
| 682 | 720 | ||
| 683 | if (!dma_pte_present(pte)) { | 721 | if (!dma_pte_present(pte)) { |
| 722 | uint64_t pteval; | ||
| 723 | |||
| 684 | tmp_page = alloc_pgtable_page(); | 724 | tmp_page = alloc_pgtable_page(); |
| 685 | 725 | ||
| 686 | if (!tmp_page) { | 726 | if (!tmp_page) |
| 687 | spin_unlock_irqrestore(&domain->mapping_lock, | ||
| 688 | flags); | ||
| 689 | return NULL; | 727 | return NULL; |
| 728 | |||
| 729 | domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); | ||
| 730 | pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; | ||
| 731 | if (cmpxchg64(&pte->val, 0ULL, pteval)) { | ||
| 732 | /* Someone else set it while we were thinking; use theirs. */ | ||
| 733 | free_pgtable_page(tmp_page); | ||
| 734 | } else { | ||
| 735 | dma_pte_addr(pte); | ||
| 736 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 690 | } | 737 | } |
| 691 | domain_flush_cache(domain, tmp_page, PAGE_SIZE); | ||
| 692 | dma_set_pte_addr(pte, virt_to_phys(tmp_page)); | ||
| 693 | /* | ||
| 694 | * high level table always sets r/w, last level page | ||
| 695 | * table control read/write | ||
| 696 | */ | ||
| 697 | dma_set_pte_readable(pte); | ||
| 698 | dma_set_pte_writable(pte); | ||
| 699 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 700 | } | 738 | } |
| 701 | parent = phys_to_virt(dma_pte_addr(pte)); | 739 | parent = phys_to_virt(dma_pte_addr(pte)); |
| 702 | level--; | 740 | level--; |
| 703 | } | 741 | } |
| 704 | 742 | ||
| 705 | spin_unlock_irqrestore(&domain->mapping_lock, flags); | ||
| 706 | return pte; | 743 | return pte; |
| 707 | } | 744 | } |
| 708 | 745 | ||
| 709 | /* return address's pte at specific level */ | 746 | /* return address's pte at specific level */ |
| 710 | static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | 747 | static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, |
| 711 | int level) | 748 | unsigned long pfn, |
| 749 | int level) | ||
| 712 | { | 750 | { |
| 713 | struct dma_pte *parent, *pte = NULL; | 751 | struct dma_pte *parent, *pte = NULL; |
| 714 | int total = agaw_to_level(domain->agaw); | 752 | int total = agaw_to_level(domain->agaw); |
| @@ -716,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
| 716 | 754 | ||
| 717 | parent = domain->pgd; | 755 | parent = domain->pgd; |
| 718 | while (level <= total) { | 756 | while (level <= total) { |
| 719 | offset = address_level_offset(addr, total); | 757 | offset = pfn_level_offset(pfn, total); |
| 720 | pte = &parent[offset]; | 758 | pte = &parent[offset]; |
| 721 | if (level == total) | 759 | if (level == total) |
| 722 | return pte; | 760 | return pte; |
| @@ -729,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
| 729 | return NULL; | 767 | return NULL; |
| 730 | } | 768 | } |
| 731 | 769 | ||
| 732 | /* clear one page's page table */ | ||
| 733 | static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) | ||
| 734 | { | ||
| 735 | struct dma_pte *pte = NULL; | ||
| 736 | |||
| 737 | /* get last level pte */ | ||
| 738 | pte = dma_addr_level_pte(domain, addr, 1); | ||
| 739 | |||
| 740 | if (pte) { | ||
| 741 | dma_clear_pte(pte); | ||
| 742 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 743 | } | ||
| 744 | } | ||
| 745 | |||
| 746 | /* clear last level pte, a tlb flush should be followed */ | 770 | /* clear last level pte, a tlb flush should be followed */ |
| 747 | static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) | 771 | static void dma_pte_clear_range(struct dmar_domain *domain, |
| 772 | unsigned long start_pfn, | ||
| 773 | unsigned long last_pfn) | ||
| 748 | { | 774 | { |
| 749 | int addr_width = agaw_to_width(domain->agaw); | 775 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 750 | int npages; | 776 | struct dma_pte *first_pte, *pte; |
| 751 | 777 | ||
| 752 | start &= (((u64)1) << addr_width) - 1; | 778 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
| 753 | end &= (((u64)1) << addr_width) - 1; | 779 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
| 754 | /* in case it's partial page */ | ||
| 755 | start &= PAGE_MASK; | ||
| 756 | end = PAGE_ALIGN(end); | ||
| 757 | npages = (end - start) / VTD_PAGE_SIZE; | ||
| 758 | 780 | ||
| 759 | /* we don't need lock here, nobody else touches the iova range */ | 781 | /* we don't need lock here; nobody else touches the iova range */ |
| 760 | while (npages--) { | 782 | while (start_pfn <= last_pfn) { |
| 761 | dma_pte_clear_one(domain, start); | 783 | first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); |
| 762 | start += VTD_PAGE_SIZE; | 784 | if (!pte) { |
| 785 | start_pfn = align_to_level(start_pfn + 1, 2); | ||
| 786 | continue; | ||
| 787 | } | ||
| 788 | do { | ||
| 789 | dma_clear_pte(pte); | ||
| 790 | start_pfn++; | ||
| 791 | pte++; | ||
| 792 | } while (start_pfn <= last_pfn && !first_pte_in_page(pte)); | ||
| 793 | |||
| 794 | domain_flush_cache(domain, first_pte, | ||
| 795 | (void *)pte - (void *)first_pte); | ||
| 763 | } | 796 | } |
| 764 | } | 797 | } |
| 765 | 798 | ||
| 766 | /* free page table pages. last level pte should already be cleared */ | 799 | /* free page table pages. last level pte should already be cleared */ |
| 767 | static void dma_pte_free_pagetable(struct dmar_domain *domain, | 800 | static void dma_pte_free_pagetable(struct dmar_domain *domain, |
| 768 | u64 start, u64 end) | 801 | unsigned long start_pfn, |
| 802 | unsigned long last_pfn) | ||
| 769 | { | 803 | { |
| 770 | int addr_width = agaw_to_width(domain->agaw); | 804 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 771 | struct dma_pte *pte; | 805 | struct dma_pte *first_pte, *pte; |
| 772 | int total = agaw_to_level(domain->agaw); | 806 | int total = agaw_to_level(domain->agaw); |
| 773 | int level; | 807 | int level; |
| 774 | u64 tmp; | 808 | unsigned long tmp; |
| 775 | 809 | ||
| 776 | start &= (((u64)1) << addr_width) - 1; | 810 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
| 777 | end &= (((u64)1) << addr_width) - 1; | 811 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
| 778 | 812 | ||
| 779 | /* we don't need lock here, nobody else touches the iova range */ | 813 | /* We don't need lock here; nobody else touches the iova range */ |
| 780 | level = 2; | 814 | level = 2; |
| 781 | while (level <= total) { | 815 | while (level <= total) { |
| 782 | tmp = align_to_level(start, level); | 816 | tmp = align_to_level(start_pfn, level); |
| 783 | if (tmp >= end || (tmp + level_size(level) > end)) | 817 | |
| 818 | /* If we can't even clear one PTE at this level, we're done */ | ||
| 819 | if (tmp + level_size(level) - 1 > last_pfn) | ||
| 784 | return; | 820 | return; |
| 785 | 821 | ||
| 786 | while (tmp < end) { | 822 | while (tmp + level_size(level) - 1 <= last_pfn) { |
| 787 | pte = dma_addr_level_pte(domain, tmp, level); | 823 | first_pte = pte = dma_pfn_level_pte(domain, tmp, level); |
| 788 | if (pte) { | 824 | if (!pte) { |
| 789 | free_pgtable_page( | 825 | tmp = align_to_level(tmp + 1, level + 1); |
| 790 | phys_to_virt(dma_pte_addr(pte))); | 826 | continue; |
| 791 | dma_clear_pte(pte); | ||
| 792 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
| 793 | } | 827 | } |
| 794 | tmp += level_size(level); | 828 | do { |
| 829 | if (dma_pte_present(pte)) { | ||
| 830 | free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); | ||
| 831 | dma_clear_pte(pte); | ||
| 832 | } | ||
| 833 | pte++; | ||
| 834 | tmp += level_size(level); | ||
| 835 | } while (!first_pte_in_page(pte) && | ||
| 836 | tmp + level_size(level) - 1 <= last_pfn); | ||
| 837 | |||
| 838 | domain_flush_cache(domain, first_pte, | ||
| 839 | (void *)pte - (void *)first_pte); | ||
| 840 | |||
| 795 | } | 841 | } |
| 796 | level++; | 842 | level++; |
| 797 | } | 843 | } |
| 798 | /* free pgd */ | 844 | /* free pgd */ |
| 799 | if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { | 845 | if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { |
| 800 | free_pgtable_page(domain->pgd); | 846 | free_pgtable_page(domain->pgd); |
| 801 | domain->pgd = NULL; | 847 | domain->pgd = NULL; |
| 802 | } | 848 | } |
| @@ -1022,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, | |||
| 1022 | } | 1068 | } |
| 1023 | 1069 | ||
| 1024 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 1070 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
| 1025 | u64 addr, unsigned int pages) | 1071 | unsigned long pfn, unsigned int pages) |
| 1026 | { | 1072 | { |
| 1027 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | 1073 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); |
| 1074 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; | ||
| 1028 | 1075 | ||
| 1029 | BUG_ON(addr & (~VTD_PAGE_MASK)); | ||
| 1030 | BUG_ON(pages == 0); | 1076 | BUG_ON(pages == 0); |
| 1031 | 1077 | ||
| 1032 | /* | 1078 | /* |
| @@ -1041,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
| 1041 | else | 1087 | else |
| 1042 | iommu->flush.flush_iotlb(iommu, did, addr, mask, | 1088 | iommu->flush.flush_iotlb(iommu, did, addr, mask, |
| 1043 | DMA_TLB_PSI_FLUSH); | 1089 | DMA_TLB_PSI_FLUSH); |
| 1044 | if (did) | 1090 | |
| 1091 | /* | ||
| 1092 | * In caching mode, domain ID 0 is reserved for non-present to present | ||
| 1093 | * mapping flush. Device IOTLB doesn't need to be flushed in this case. | ||
| 1094 | */ | ||
| 1095 | if (!cap_caching_mode(iommu->cap) || did) | ||
| 1045 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); | 1096 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); |
| 1046 | } | 1097 | } |
| 1047 | 1098 | ||
| @@ -1189,48 +1240,71 @@ void free_dmar_iommu(struct intel_iommu *iommu) | |||
| 1189 | free_context_table(iommu); | 1240 | free_context_table(iommu); |
| 1190 | } | 1241 | } |
| 1191 | 1242 | ||
| 1192 | static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu) | 1243 | static struct dmar_domain *alloc_domain(void) |
| 1193 | { | 1244 | { |
| 1194 | unsigned long num; | ||
| 1195 | unsigned long ndomains; | ||
| 1196 | struct dmar_domain *domain; | 1245 | struct dmar_domain *domain; |
| 1197 | unsigned long flags; | ||
| 1198 | 1246 | ||
| 1199 | domain = alloc_domain_mem(); | 1247 | domain = alloc_domain_mem(); |
| 1200 | if (!domain) | 1248 | if (!domain) |
| 1201 | return NULL; | 1249 | return NULL; |
| 1202 | 1250 | ||
| 1251 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | ||
| 1252 | domain->flags = 0; | ||
| 1253 | |||
| 1254 | return domain; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | static int iommu_attach_domain(struct dmar_domain *domain, | ||
| 1258 | struct intel_iommu *iommu) | ||
| 1259 | { | ||
| 1260 | int num; | ||
| 1261 | unsigned long ndomains; | ||
| 1262 | unsigned long flags; | ||
| 1263 | |||
| 1203 | ndomains = cap_ndoms(iommu->cap); | 1264 | ndomains = cap_ndoms(iommu->cap); |
| 1204 | 1265 | ||
| 1205 | spin_lock_irqsave(&iommu->lock, flags); | 1266 | spin_lock_irqsave(&iommu->lock, flags); |
| 1267 | |||
| 1206 | num = find_first_zero_bit(iommu->domain_ids, ndomains); | 1268 | num = find_first_zero_bit(iommu->domain_ids, ndomains); |
| 1207 | if (num >= ndomains) { | 1269 | if (num >= ndomains) { |
| 1208 | spin_unlock_irqrestore(&iommu->lock, flags); | 1270 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 1209 | free_domain_mem(domain); | ||
| 1210 | printk(KERN_ERR "IOMMU: no free domain ids\n"); | 1271 | printk(KERN_ERR "IOMMU: no free domain ids\n"); |
| 1211 | return NULL; | 1272 | return -ENOMEM; |
| 1212 | } | 1273 | } |
| 1213 | 1274 | ||
| 1214 | set_bit(num, iommu->domain_ids); | ||
| 1215 | domain->id = num; | 1275 | domain->id = num; |
| 1216 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 1276 | set_bit(num, iommu->domain_ids); |
| 1217 | set_bit(iommu->seq_id, &domain->iommu_bmp); | 1277 | set_bit(iommu->seq_id, &domain->iommu_bmp); |
| 1218 | domain->flags = 0; | ||
| 1219 | iommu->domains[num] = domain; | 1278 | iommu->domains[num] = domain; |
| 1220 | spin_unlock_irqrestore(&iommu->lock, flags); | 1279 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 1221 | 1280 | ||
| 1222 | return domain; | 1281 | return 0; |
| 1223 | } | 1282 | } |
| 1224 | 1283 | ||
| 1225 | static void iommu_free_domain(struct dmar_domain *domain) | 1284 | static void iommu_detach_domain(struct dmar_domain *domain, |
| 1285 | struct intel_iommu *iommu) | ||
| 1226 | { | 1286 | { |
| 1227 | unsigned long flags; | 1287 | unsigned long flags; |
| 1228 | struct intel_iommu *iommu; | 1288 | int num, ndomains; |
| 1229 | 1289 | int found = 0; | |
| 1230 | iommu = domain_get_iommu(domain); | ||
| 1231 | 1290 | ||
| 1232 | spin_lock_irqsave(&iommu->lock, flags); | 1291 | spin_lock_irqsave(&iommu->lock, flags); |
| 1233 | clear_bit(domain->id, iommu->domain_ids); | 1292 | ndomains = cap_ndoms(iommu->cap); |
| 1293 | num = find_first_bit(iommu->domain_ids, ndomains); | ||
| 1294 | for (; num < ndomains; ) { | ||
| 1295 | if (iommu->domains[num] == domain) { | ||
| 1296 | found = 1; | ||
| 1297 | break; | ||
| 1298 | } | ||
| 1299 | num = find_next_bit(iommu->domain_ids, | ||
| 1300 | cap_ndoms(iommu->cap), num+1); | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | if (found) { | ||
| 1304 | clear_bit(num, iommu->domain_ids); | ||
| 1305 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | ||
| 1306 | iommu->domains[num] = NULL; | ||
| 1307 | } | ||
| 1234 | spin_unlock_irqrestore(&iommu->lock, flags); | 1308 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 1235 | } | 1309 | } |
| 1236 | 1310 | ||
| @@ -1243,7 +1317,6 @@ static void dmar_init_reserved_ranges(void) | |||
| 1243 | struct pci_dev *pdev = NULL; | 1317 | struct pci_dev *pdev = NULL; |
| 1244 | struct iova *iova; | 1318 | struct iova *iova; |
| 1245 | int i; | 1319 | int i; |
| 1246 | u64 addr, size; | ||
| 1247 | 1320 | ||
| 1248 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); | 1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
| 1249 | 1322 | ||
| @@ -1266,12 +1339,9 @@ static void dmar_init_reserved_ranges(void) | |||
| 1266 | r = &pdev->resource[i]; | 1339 | r = &pdev->resource[i]; |
| 1267 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) | 1340 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) |
| 1268 | continue; | 1341 | continue; |
| 1269 | addr = r->start; | 1342 | iova = reserve_iova(&reserved_iova_list, |
| 1270 | addr &= PHYSICAL_PAGE_MASK; | 1343 | IOVA_PFN(r->start), |
| 1271 | size = r->end - addr; | 1344 | IOVA_PFN(r->end)); |
| 1272 | size = PAGE_ALIGN(size); | ||
| 1273 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), | ||
| 1274 | IOVA_PFN(size + addr) - 1); | ||
| 1275 | if (!iova) | 1345 | if (!iova) |
| 1276 | printk(KERN_ERR "Reserve iova failed\n"); | 1346 | printk(KERN_ERR "Reserve iova failed\n"); |
| 1277 | } | 1347 | } |
| @@ -1305,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
| 1305 | unsigned long sagaw; | 1375 | unsigned long sagaw; |
| 1306 | 1376 | ||
| 1307 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 1377 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
| 1308 | spin_lock_init(&domain->mapping_lock); | ||
| 1309 | spin_lock_init(&domain->iommu_lock); | 1378 | spin_lock_init(&domain->iommu_lock); |
| 1310 | 1379 | ||
| 1311 | domain_reserve_special_ranges(domain); | 1380 | domain_reserve_special_ranges(domain); |
| @@ -1350,7 +1419,8 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
| 1350 | 1419 | ||
| 1351 | static void domain_exit(struct dmar_domain *domain) | 1420 | static void domain_exit(struct dmar_domain *domain) |
| 1352 | { | 1421 | { |
| 1353 | u64 end; | 1422 | struct dmar_drhd_unit *drhd; |
| 1423 | struct intel_iommu *iommu; | ||
| 1354 | 1424 | ||
| 1355 | /* Domain 0 is reserved, so dont process it */ | 1425 | /* Domain 0 is reserved, so dont process it */ |
| 1356 | if (!domain) | 1426 | if (!domain) |
| @@ -1359,16 +1429,17 @@ static void domain_exit(struct dmar_domain *domain) | |||
| 1359 | domain_remove_dev_info(domain); | 1429 | domain_remove_dev_info(domain); |
| 1360 | /* destroy iovas */ | 1430 | /* destroy iovas */ |
| 1361 | put_iova_domain(&domain->iovad); | 1431 | put_iova_domain(&domain->iovad); |
| 1362 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
| 1363 | end = end & (~PAGE_MASK); | ||
| 1364 | 1432 | ||
| 1365 | /* clear ptes */ | 1433 | /* clear ptes */ |
| 1366 | dma_pte_clear_range(domain, 0, end); | 1434 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 1367 | 1435 | ||
| 1368 | /* free page tables */ | 1436 | /* free page tables */ |
| 1369 | dma_pte_free_pagetable(domain, 0, end); | 1437 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 1438 | |||
| 1439 | for_each_active_iommu(iommu, drhd) | ||
| 1440 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | ||
| 1441 | iommu_detach_domain(domain, iommu); | ||
| 1370 | 1442 | ||
| 1371 | iommu_free_domain(domain); | ||
| 1372 | free_domain_mem(domain); | 1443 | free_domain_mem(domain); |
| 1373 | } | 1444 | } |
| 1374 | 1445 | ||
| @@ -1408,7 +1479,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
| 1408 | id = domain->id; | 1479 | id = domain->id; |
| 1409 | pgd = domain->pgd; | 1480 | pgd = domain->pgd; |
| 1410 | 1481 | ||
| 1411 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) { | 1482 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE || |
| 1483 | domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) { | ||
| 1412 | int found = 0; | 1484 | int found = 0; |
| 1413 | 1485 | ||
| 1414 | /* find an available domain id for this device in iommu */ | 1486 | /* find an available domain id for this device in iommu */ |
| @@ -1433,6 +1505,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
| 1433 | } | 1505 | } |
| 1434 | 1506 | ||
| 1435 | set_bit(num, iommu->domain_ids); | 1507 | set_bit(num, iommu->domain_ids); |
| 1508 | set_bit(iommu->seq_id, &domain->iommu_bmp); | ||
| 1436 | iommu->domains[num] = domain; | 1509 | iommu->domains[num] = domain; |
| 1437 | id = num; | 1510 | id = num; |
| 1438 | } | 1511 | } |
| @@ -1575,42 +1648,86 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
| 1575 | tmp->devfn); | 1648 | tmp->devfn); |
| 1576 | } | 1649 | } |
| 1577 | 1650 | ||
| 1578 | static int | 1651 | static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
| 1579 | domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, | 1652 | struct scatterlist *sg, unsigned long phys_pfn, |
| 1580 | u64 hpa, size_t size, int prot) | 1653 | unsigned long nr_pages, int prot) |
| 1581 | { | 1654 | { |
| 1582 | u64 start_pfn, end_pfn; | 1655 | struct dma_pte *first_pte = NULL, *pte = NULL; |
| 1583 | struct dma_pte *pte; | 1656 | phys_addr_t uninitialized_var(pteval); |
| 1584 | int index; | 1657 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
| 1585 | int addr_width = agaw_to_width(domain->agaw); | 1658 | unsigned long sg_res; |
| 1586 | 1659 | ||
| 1587 | hpa &= (((u64)1) << addr_width) - 1; | 1660 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); |
| 1588 | 1661 | ||
| 1589 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) | 1662 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) |
| 1590 | return -EINVAL; | 1663 | return -EINVAL; |
| 1591 | iova &= PAGE_MASK; | 1664 | |
| 1592 | start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; | 1665 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; |
| 1593 | end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; | 1666 | |
| 1594 | index = 0; | 1667 | if (sg) |
| 1595 | while (start_pfn < end_pfn) { | 1668 | sg_res = 0; |
| 1596 | pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); | 1669 | else { |
| 1597 | if (!pte) | 1670 | sg_res = nr_pages + 1; |
| 1598 | return -ENOMEM; | 1671 | pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; |
| 1672 | } | ||
| 1673 | |||
| 1674 | while (nr_pages--) { | ||
| 1675 | uint64_t tmp; | ||
| 1676 | |||
| 1677 | if (!sg_res) { | ||
| 1678 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; | ||
| 1679 | sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; | ||
| 1680 | sg->dma_length = sg->length; | ||
| 1681 | pteval = page_to_phys(sg_page(sg)) | prot; | ||
| 1682 | } | ||
| 1683 | if (!pte) { | ||
| 1684 | first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); | ||
| 1685 | if (!pte) | ||
| 1686 | return -ENOMEM; | ||
| 1687 | } | ||
| 1599 | /* We don't need lock here, nobody else | 1688 | /* We don't need lock here, nobody else |
| 1600 | * touches the iova range | 1689 | * touches the iova range |
| 1601 | */ | 1690 | */ |
| 1602 | BUG_ON(dma_pte_addr(pte)); | 1691 | tmp = cmpxchg64_local(&pte->val, 0ULL, pteval); |
| 1603 | dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT); | 1692 | if (tmp) { |
| 1604 | dma_set_pte_prot(pte, prot); | 1693 | static int dumps = 5; |
| 1605 | if (prot & DMA_PTE_SNP) | 1694 | printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", |
| 1606 | dma_set_pte_snp(pte); | 1695 | iov_pfn, tmp, (unsigned long long)pteval); |
| 1607 | domain_flush_cache(domain, pte, sizeof(*pte)); | 1696 | if (dumps) { |
| 1608 | start_pfn++; | 1697 | dumps--; |
| 1609 | index++; | 1698 | debug_dma_dump_mappings(NULL); |
| 1699 | } | ||
| 1700 | WARN_ON(1); | ||
| 1701 | } | ||
| 1702 | pte++; | ||
| 1703 | if (!nr_pages || first_pte_in_page(pte)) { | ||
| 1704 | domain_flush_cache(domain, first_pte, | ||
| 1705 | (void *)pte - (void *)first_pte); | ||
| 1706 | pte = NULL; | ||
| 1707 | } | ||
| 1708 | iov_pfn++; | ||
| 1709 | pteval += VTD_PAGE_SIZE; | ||
| 1710 | sg_res--; | ||
| 1711 | if (!sg_res) | ||
| 1712 | sg = sg_next(sg); | ||
| 1610 | } | 1713 | } |
| 1611 | return 0; | 1714 | return 0; |
| 1612 | } | 1715 | } |
| 1613 | 1716 | ||
| 1717 | static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
| 1718 | struct scatterlist *sg, unsigned long nr_pages, | ||
| 1719 | int prot) | ||
| 1720 | { | ||
| 1721 | return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
| 1725 | unsigned long phys_pfn, unsigned long nr_pages, | ||
| 1726 | int prot) | ||
| 1727 | { | ||
| 1728 | return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); | ||
| 1729 | } | ||
| 1730 | |||
| 1614 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) | 1731 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) |
| 1615 | { | 1732 | { |
| 1616 | if (!iommu) | 1733 | if (!iommu) |
| @@ -1675,6 +1792,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
| 1675 | unsigned long flags; | 1792 | unsigned long flags; |
| 1676 | int bus = 0, devfn = 0; | 1793 | int bus = 0, devfn = 0; |
| 1677 | int segment; | 1794 | int segment; |
| 1795 | int ret; | ||
| 1678 | 1796 | ||
| 1679 | domain = find_domain(pdev); | 1797 | domain = find_domain(pdev); |
| 1680 | if (domain) | 1798 | if (domain) |
| @@ -1707,6 +1825,10 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
| 1707 | } | 1825 | } |
| 1708 | } | 1826 | } |
| 1709 | 1827 | ||
| 1828 | domain = alloc_domain(); | ||
| 1829 | if (!domain) | ||
| 1830 | goto error; | ||
| 1831 | |||
| 1710 | /* Allocate new domain for the device */ | 1832 | /* Allocate new domain for the device */ |
| 1711 | drhd = dmar_find_matched_drhd_unit(pdev); | 1833 | drhd = dmar_find_matched_drhd_unit(pdev); |
| 1712 | if (!drhd) { | 1834 | if (!drhd) { |
| @@ -1716,9 +1838,11 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
| 1716 | } | 1838 | } |
| 1717 | iommu = drhd->iommu; | 1839 | iommu = drhd->iommu; |
| 1718 | 1840 | ||
| 1719 | domain = iommu_alloc_domain(iommu); | 1841 | ret = iommu_attach_domain(domain, iommu); |
| 1720 | if (!domain) | 1842 | if (ret) { |
| 1843 | domain_exit(domain); | ||
| 1721 | goto error; | 1844 | goto error; |
| 1845 | } | ||
| 1722 | 1846 | ||
| 1723 | if (domain_init(domain, gaw)) { | 1847 | if (domain_init(domain, gaw)) { |
| 1724 | domain_exit(domain); | 1848 | domain_exit(domain); |
| @@ -1792,55 +1916,63 @@ error: | |||
| 1792 | return find_domain(pdev); | 1916 | return find_domain(pdev); |
| 1793 | } | 1917 | } |
| 1794 | 1918 | ||
| 1919 | static int iommu_identity_mapping; | ||
| 1920 | |||
| 1921 | static int iommu_domain_identity_map(struct dmar_domain *domain, | ||
| 1922 | unsigned long long start, | ||
| 1923 | unsigned long long end) | ||
| 1924 | { | ||
| 1925 | unsigned long first_vpfn = start >> VTD_PAGE_SHIFT; | ||
| 1926 | unsigned long last_vpfn = end >> VTD_PAGE_SHIFT; | ||
| 1927 | |||
| 1928 | if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn), | ||
| 1929 | dma_to_mm_pfn(last_vpfn))) { | ||
| 1930 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
| 1931 | return -ENOMEM; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | pr_debug("Mapping reserved region %llx-%llx for domain %d\n", | ||
| 1935 | start, end, domain->id); | ||
| 1936 | /* | ||
| 1937 | * RMRR range might have overlap with physical memory range, | ||
| 1938 | * clear it first | ||
| 1939 | */ | ||
| 1940 | dma_pte_clear_range(domain, first_vpfn, last_vpfn); | ||
| 1941 | |||
| 1942 | return domain_pfn_mapping(domain, first_vpfn, first_vpfn, | ||
| 1943 | last_vpfn - first_vpfn + 1, | ||
| 1944 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
| 1945 | } | ||
| 1946 | |||
| 1795 | static int iommu_prepare_identity_map(struct pci_dev *pdev, | 1947 | static int iommu_prepare_identity_map(struct pci_dev *pdev, |
| 1796 | unsigned long long start, | 1948 | unsigned long long start, |
| 1797 | unsigned long long end) | 1949 | unsigned long long end) |
| 1798 | { | 1950 | { |
| 1799 | struct dmar_domain *domain; | 1951 | struct dmar_domain *domain; |
| 1800 | unsigned long size; | ||
| 1801 | unsigned long long base; | ||
| 1802 | int ret; | 1952 | int ret; |
| 1803 | 1953 | ||
| 1804 | printk(KERN_INFO | 1954 | printk(KERN_INFO |
| 1805 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 1955 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
| 1806 | pci_name(pdev), start, end); | 1956 | pci_name(pdev), start, end); |
| 1807 | /* page table init */ | 1957 | |
| 1808 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | 1958 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
| 1809 | if (!domain) | 1959 | if (!domain) |
| 1810 | return -ENOMEM; | 1960 | return -ENOMEM; |
| 1811 | 1961 | ||
| 1812 | /* The address might not be aligned */ | 1962 | ret = iommu_domain_identity_map(domain, start, end); |
| 1813 | base = start & PAGE_MASK; | ||
| 1814 | size = end - base; | ||
| 1815 | size = PAGE_ALIGN(size); | ||
| 1816 | if (!reserve_iova(&domain->iovad, IOVA_PFN(base), | ||
| 1817 | IOVA_PFN(base + size) - 1)) { | ||
| 1818 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
| 1819 | ret = -ENOMEM; | ||
| 1820 | goto error; | ||
| 1821 | } | ||
| 1822 | |||
| 1823 | pr_debug("Mapping reserved region %lx@%llx for %s\n", | ||
| 1824 | size, base, pci_name(pdev)); | ||
| 1825 | /* | ||
| 1826 | * RMRR range might have overlap with physical memory range, | ||
| 1827 | * clear it first | ||
| 1828 | */ | ||
| 1829 | dma_pte_clear_range(domain, base, base + size); | ||
| 1830 | |||
| 1831 | ret = domain_page_mapping(domain, base, base, size, | ||
| 1832 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
| 1833 | if (ret) | 1963 | if (ret) |
| 1834 | goto error; | 1964 | goto error; |
| 1835 | 1965 | ||
| 1836 | /* context entry init */ | 1966 | /* context entry init */ |
| 1837 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 1967 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
| 1838 | if (!ret) | 1968 | if (ret) |
| 1839 | return 0; | 1969 | goto error; |
| 1840 | error: | 1970 | |
| 1971 | return 0; | ||
| 1972 | |||
| 1973 | error: | ||
| 1841 | domain_exit(domain); | 1974 | domain_exit(domain); |
| 1842 | return ret; | 1975 | return ret; |
| 1843 | |||
| 1844 | } | 1976 | } |
| 1845 | 1977 | ||
| 1846 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 1978 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
| @@ -1852,64 +1984,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
| 1852 | rmrr->end_address + 1); | 1984 | rmrr->end_address + 1); |
| 1853 | } | 1985 | } |
| 1854 | 1986 | ||
| 1855 | #ifdef CONFIG_DMAR_GFX_WA | ||
| 1856 | struct iommu_prepare_data { | ||
| 1857 | struct pci_dev *pdev; | ||
| 1858 | int ret; | ||
| 1859 | }; | ||
| 1860 | |||
| 1861 | static int __init iommu_prepare_work_fn(unsigned long start_pfn, | ||
| 1862 | unsigned long end_pfn, void *datax) | ||
| 1863 | { | ||
| 1864 | struct iommu_prepare_data *data; | ||
| 1865 | |||
| 1866 | data = (struct iommu_prepare_data *)datax; | ||
| 1867 | |||
| 1868 | data->ret = iommu_prepare_identity_map(data->pdev, | ||
| 1869 | start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
| 1870 | return data->ret; | ||
| 1871 | |||
| 1872 | } | ||
| 1873 | |||
| 1874 | static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | ||
| 1875 | { | ||
| 1876 | int nid; | ||
| 1877 | struct iommu_prepare_data data; | ||
| 1878 | |||
| 1879 | data.pdev = pdev; | ||
| 1880 | data.ret = 0; | ||
| 1881 | |||
| 1882 | for_each_online_node(nid) { | ||
| 1883 | work_with_active_regions(nid, iommu_prepare_work_fn, &data); | ||
| 1884 | if (data.ret) | ||
| 1885 | return data.ret; | ||
| 1886 | } | ||
| 1887 | return data.ret; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | static void __init iommu_prepare_gfx_mapping(void) | ||
| 1891 | { | ||
| 1892 | struct pci_dev *pdev = NULL; | ||
| 1893 | int ret; | ||
| 1894 | |||
| 1895 | for_each_pci_dev(pdev) { | ||
| 1896 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | ||
| 1897 | !IS_GFX_DEVICE(pdev)) | ||
| 1898 | continue; | ||
| 1899 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
| 1900 | pci_name(pdev)); | ||
| 1901 | ret = iommu_prepare_with_active_regions(pdev); | ||
| 1902 | if (ret) | ||
| 1903 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
| 1904 | } | ||
| 1905 | } | ||
| 1906 | #else /* !CONFIG_DMAR_GFX_WA */ | ||
| 1907 | static inline void iommu_prepare_gfx_mapping(void) | ||
| 1908 | { | ||
| 1909 | return; | ||
| 1910 | } | ||
| 1911 | #endif | ||
| 1912 | |||
| 1913 | #ifdef CONFIG_DMAR_FLOPPY_WA | 1987 | #ifdef CONFIG_DMAR_FLOPPY_WA |
| 1914 | static inline void iommu_prepare_isa(void) | 1988 | static inline void iommu_prepare_isa(void) |
| 1915 | { | 1989 | { |
| @@ -1920,12 +1994,12 @@ static inline void iommu_prepare_isa(void) | |||
| 1920 | if (!pdev) | 1994 | if (!pdev) |
| 1921 | return; | 1995 | return; |
| 1922 | 1996 | ||
| 1923 | printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | 1997 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
| 1924 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1998 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
| 1925 | 1999 | ||
| 1926 | if (ret) | 2000 | if (ret) |
| 1927 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | 2001 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
| 1928 | "floppy might not work\n"); | 2002 | "floppy might not work\n"); |
| 1929 | 2003 | ||
| 1930 | } | 2004 | } |
| 1931 | #else | 2005 | #else |
| @@ -1952,7 +2026,166 @@ static int __init init_context_pass_through(void) | |||
| 1952 | return 0; | 2026 | return 0; |
| 1953 | } | 2027 | } |
| 1954 | 2028 | ||
| 1955 | static int __init init_dmars(void) | 2029 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
| 2030 | |||
| 2031 | static int __init si_domain_work_fn(unsigned long start_pfn, | ||
| 2032 | unsigned long end_pfn, void *datax) | ||
| 2033 | { | ||
| 2034 | int *ret = datax; | ||
| 2035 | |||
| 2036 | *ret = iommu_domain_identity_map(si_domain, | ||
| 2037 | (uint64_t)start_pfn << PAGE_SHIFT, | ||
| 2038 | (uint64_t)end_pfn << PAGE_SHIFT); | ||
| 2039 | return *ret; | ||
| 2040 | |||
| 2041 | } | ||
| 2042 | |||
| 2043 | static int si_domain_init(void) | ||
| 2044 | { | ||
| 2045 | struct dmar_drhd_unit *drhd; | ||
| 2046 | struct intel_iommu *iommu; | ||
| 2047 | int nid, ret = 0; | ||
| 2048 | |||
| 2049 | si_domain = alloc_domain(); | ||
| 2050 | if (!si_domain) | ||
| 2051 | return -EFAULT; | ||
| 2052 | |||
| 2053 | pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | ||
| 2054 | |||
| 2055 | for_each_active_iommu(iommu, drhd) { | ||
| 2056 | ret = iommu_attach_domain(si_domain, iommu); | ||
| 2057 | if (ret) { | ||
| 2058 | domain_exit(si_domain); | ||
| 2059 | return -EFAULT; | ||
| 2060 | } | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { | ||
| 2064 | domain_exit(si_domain); | ||
| 2065 | return -EFAULT; | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | ||
| 2069 | |||
| 2070 | for_each_online_node(nid) { | ||
| 2071 | work_with_active_regions(nid, si_domain_work_fn, &ret); | ||
| 2072 | if (ret) | ||
| 2073 | return ret; | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | return 0; | ||
| 2077 | } | ||
| 2078 | |||
| 2079 | static void domain_remove_one_dev_info(struct dmar_domain *domain, | ||
| 2080 | struct pci_dev *pdev); | ||
| 2081 | static int identity_mapping(struct pci_dev *pdev) | ||
| 2082 | { | ||
| 2083 | struct device_domain_info *info; | ||
| 2084 | |||
| 2085 | if (likely(!iommu_identity_mapping)) | ||
| 2086 | return 0; | ||
| 2087 | |||
| 2088 | |||
| 2089 | list_for_each_entry(info, &si_domain->devices, link) | ||
| 2090 | if (info->dev == pdev) | ||
| 2091 | return 1; | ||
| 2092 | return 0; | ||
| 2093 | } | ||
| 2094 | |||
| 2095 | static int domain_add_dev_info(struct dmar_domain *domain, | ||
| 2096 | struct pci_dev *pdev) | ||
| 2097 | { | ||
| 2098 | struct device_domain_info *info; | ||
| 2099 | unsigned long flags; | ||
| 2100 | |||
| 2101 | info = alloc_devinfo_mem(); | ||
| 2102 | if (!info) | ||
| 2103 | return -ENOMEM; | ||
| 2104 | |||
| 2105 | info->segment = pci_domain_nr(pdev->bus); | ||
| 2106 | info->bus = pdev->bus->number; | ||
| 2107 | info->devfn = pdev->devfn; | ||
| 2108 | info->dev = pdev; | ||
| 2109 | info->domain = domain; | ||
| 2110 | |||
| 2111 | spin_lock_irqsave(&device_domain_lock, flags); | ||
| 2112 | list_add(&info->link, &domain->devices); | ||
| 2113 | list_add(&info->global, &device_domain_list); | ||
| 2114 | pdev->dev.archdata.iommu = info; | ||
| 2115 | spin_unlock_irqrestore(&device_domain_lock, flags); | ||
| 2116 | |||
| 2117 | return 0; | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | ||
| 2121 | { | ||
| 2122 | if (iommu_identity_mapping == 2) | ||
| 2123 | return IS_GFX_DEVICE(pdev); | ||
| 2124 | |||
| 2125 | /* | ||
| 2126 | * We want to start off with all devices in the 1:1 domain, and | ||
| 2127 | * take them out later if we find they can't access all of memory. | ||
| 2128 | * | ||
| 2129 | * However, we can't do this for PCI devices behind bridges, | ||
| 2130 | * because all PCI devices behind the same bridge will end up | ||
| 2131 | * with the same source-id on their transactions. | ||
| 2132 | * | ||
| 2133 | * Practically speaking, we can't change things around for these | ||
| 2134 | * devices at run-time, because we can't be sure there'll be no | ||
| 2135 | * DMA transactions in flight for any of their siblings. | ||
| 2136 | * | ||
| 2137 | * So PCI devices (unless they're on the root bus) as well as | ||
| 2138 | * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of | ||
| 2139 | * the 1:1 domain, just in _case_ one of their siblings turns out | ||
| 2140 | * not to be able to map all of memory. | ||
| 2141 | */ | ||
| 2142 | if (!pdev->is_pcie) { | ||
| 2143 | if (!pci_is_root_bus(pdev->bus)) | ||
| 2144 | return 0; | ||
| 2145 | if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) | ||
| 2146 | return 0; | ||
| 2147 | } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | ||
| 2148 | return 0; | ||
| 2149 | |||
| 2150 | /* | ||
| 2151 | * At boot time, we don't yet know if devices will be 64-bit capable. | ||
| 2152 | * Assume that they will -- if they turn out not to be, then we can | ||
| 2153 | * take them out of the 1:1 domain later. | ||
| 2154 | */ | ||
| 2155 | if (!startup) | ||
| 2156 | return pdev->dma_mask > DMA_BIT_MASK(32); | ||
| 2157 | |||
| 2158 | return 1; | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | static int iommu_prepare_static_identity_mapping(void) | ||
| 2162 | { | ||
| 2163 | struct pci_dev *pdev = NULL; | ||
| 2164 | int ret; | ||
| 2165 | |||
| 2166 | ret = si_domain_init(); | ||
| 2167 | if (ret) | ||
| 2168 | return -EFAULT; | ||
| 2169 | |||
| 2170 | for_each_pci_dev(pdev) { | ||
| 2171 | if (iommu_should_identity_map(pdev, 1)) { | ||
| 2172 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", | ||
| 2173 | pci_name(pdev)); | ||
| 2174 | |||
| 2175 | ret = domain_context_mapping(si_domain, pdev, | ||
| 2176 | CONTEXT_TT_MULTI_LEVEL); | ||
| 2177 | if (ret) | ||
| 2178 | return ret; | ||
| 2179 | ret = domain_add_dev_info(si_domain, pdev); | ||
| 2180 | if (ret) | ||
| 2181 | return ret; | ||
| 2182 | } | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | return 0; | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | int __init init_dmars(void) | ||
| 1956 | { | 2189 | { |
| 1957 | struct dmar_drhd_unit *drhd; | 2190 | struct dmar_drhd_unit *drhd; |
| 1958 | struct dmar_rmrr_unit *rmrr; | 2191 | struct dmar_rmrr_unit *rmrr; |
| @@ -1962,6 +2195,13 @@ static int __init init_dmars(void) | |||
| 1962 | int pass_through = 1; | 2195 | int pass_through = 1; |
| 1963 | 2196 | ||
| 1964 | /* | 2197 | /* |
| 2198 | * In case pass through can not be enabled, iommu tries to use identity | ||
| 2199 | * mapping. | ||
| 2200 | */ | ||
| 2201 | if (iommu_pass_through) | ||
| 2202 | iommu_identity_mapping = 1; | ||
| 2203 | |||
| 2204 | /* | ||
| 1965 | * for each drhd | 2205 | * for each drhd |
| 1966 | * allocate root | 2206 | * allocate root |
| 1967 | * initialize and program root entry to not present | 2207 | * initialize and program root entry to not present |
| @@ -2090,9 +2330,16 @@ static int __init init_dmars(void) | |||
| 2090 | 2330 | ||
| 2091 | /* | 2331 | /* |
| 2092 | * If pass through is not set or not enabled, setup context entries for | 2332 | * If pass through is not set or not enabled, setup context entries for |
| 2093 | * identity mappings for rmrr, gfx, and isa. | 2333 | * identity mappings for rmrr, gfx, and isa and may fall back to static |
| 2334 | * identity mapping if iommu_identity_mapping is set. | ||
| 2094 | */ | 2335 | */ |
| 2095 | if (!iommu_pass_through) { | 2336 | if (!iommu_pass_through) { |
| 2337 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA | ||
| 2338 | if (!iommu_identity_mapping) | ||
| 2339 | iommu_identity_mapping = 2; | ||
| 2340 | #endif | ||
| 2341 | if (iommu_identity_mapping) | ||
| 2342 | iommu_prepare_static_identity_mapping(); | ||
| 2096 | /* | 2343 | /* |
| 2097 | * For each rmrr | 2344 | * For each rmrr |
| 2098 | * for each dev attached to rmrr | 2345 | * for each dev attached to rmrr |
| @@ -2107,6 +2354,7 @@ static int __init init_dmars(void) | |||
| 2107 | * endfor | 2354 | * endfor |
| 2108 | * endfor | 2355 | * endfor |
| 2109 | */ | 2356 | */ |
| 2357 | printk(KERN_INFO "IOMMU: Setting RMRR:\n"); | ||
| 2110 | for_each_rmrr_units(rmrr) { | 2358 | for_each_rmrr_units(rmrr) { |
| 2111 | for (i = 0; i < rmrr->devices_cnt; i++) { | 2359 | for (i = 0; i < rmrr->devices_cnt; i++) { |
| 2112 | pdev = rmrr->devices[i]; | 2360 | pdev = rmrr->devices[i]; |
| @@ -2123,8 +2371,6 @@ static int __init init_dmars(void) | |||
| 2123 | } | 2371 | } |
| 2124 | } | 2372 | } |
| 2125 | 2373 | ||
| 2126 | iommu_prepare_gfx_mapping(); | ||
| 2127 | |||
| 2128 | iommu_prepare_isa(); | 2374 | iommu_prepare_isa(); |
| 2129 | } | 2375 | } |
| 2130 | 2376 | ||
| @@ -2169,50 +2415,40 @@ error: | |||
| 2169 | return ret; | 2415 | return ret; |
| 2170 | } | 2416 | } |
| 2171 | 2417 | ||
| 2172 | static inline u64 aligned_size(u64 host_addr, size_t size) | 2418 | /* Returns a number of VTD pages, but aligned to MM page size */ |
| 2419 | static inline unsigned long aligned_nrpages(unsigned long host_addr, | ||
| 2420 | size_t size) | ||
| 2173 | { | 2421 | { |
| 2174 | u64 addr; | 2422 | host_addr &= ~PAGE_MASK; |
| 2175 | addr = (host_addr & (~PAGE_MASK)) + size; | 2423 | return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT; |
| 2176 | return PAGE_ALIGN(addr); | ||
| 2177 | } | 2424 | } |
| 2178 | 2425 | ||
| 2179 | struct iova * | 2426 | /* This takes a number of _MM_ pages, not VTD pages */ |
| 2180 | iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) | 2427 | static struct iova *intel_alloc_iova(struct device *dev, |
| 2181 | { | 2428 | struct dmar_domain *domain, |
| 2182 | struct iova *piova; | 2429 | unsigned long nrpages, uint64_t dma_mask) |
| 2183 | |||
| 2184 | /* Make sure it's in range */ | ||
| 2185 | end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); | ||
| 2186 | if (!size || (IOVA_START_ADDR + size > end)) | ||
| 2187 | return NULL; | ||
| 2188 | |||
| 2189 | piova = alloc_iova(&domain->iovad, | ||
| 2190 | size >> PAGE_SHIFT, IOVA_PFN(end), 1); | ||
| 2191 | return piova; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | static struct iova * | ||
| 2195 | __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, | ||
| 2196 | size_t size, u64 dma_mask) | ||
| 2197 | { | 2430 | { |
| 2198 | struct pci_dev *pdev = to_pci_dev(dev); | 2431 | struct pci_dev *pdev = to_pci_dev(dev); |
| 2199 | struct iova *iova = NULL; | 2432 | struct iova *iova = NULL; |
| 2200 | 2433 | ||
| 2201 | if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) | 2434 | /* Restrict dma_mask to the width that the iommu can handle */ |
| 2202 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2435 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
| 2203 | else { | 2436 | |
| 2437 | if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { | ||
| 2204 | /* | 2438 | /* |
| 2205 | * First try to allocate an io virtual address in | 2439 | * First try to allocate an io virtual address in |
| 2206 | * DMA_BIT_MASK(32) and if that fails then try allocating | 2440 | * DMA_BIT_MASK(32) and if that fails then try allocating |
| 2207 | * from higher range | 2441 | * from higher range |
| 2208 | */ | 2442 | */ |
| 2209 | iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); | 2443 | iova = alloc_iova(&domain->iovad, nrpages, |
| 2210 | if (!iova) | 2444 | IOVA_PFN(DMA_BIT_MASK(32)), 1); |
| 2211 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2445 | if (iova) |
| 2212 | } | 2446 | return iova; |
| 2213 | 2447 | } | |
| 2214 | if (!iova) { | 2448 | iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); |
| 2215 | printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); | 2449 | if (unlikely(!iova)) { |
| 2450 | printk(KERN_ERR "Allocating %ld-page iova for %s failed", | ||
| 2451 | nrpages, pci_name(pdev)); | ||
| 2216 | return NULL; | 2452 | return NULL; |
| 2217 | } | 2453 | } |
| 2218 | 2454 | ||
| @@ -2248,6 +2484,63 @@ get_valid_domain_for_dev(struct pci_dev *pdev) | |||
| 2248 | return domain; | 2484 | return domain; |
| 2249 | } | 2485 | } |
| 2250 | 2486 | ||
| 2487 | static int iommu_dummy(struct pci_dev *pdev) | ||
| 2488 | { | ||
| 2489 | return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | /* Check if the pdev needs to go through non-identity map and unmap process.*/ | ||
| 2493 | static int iommu_no_mapping(struct device *dev) | ||
| 2494 | { | ||
| 2495 | struct pci_dev *pdev; | ||
| 2496 | int found; | ||
| 2497 | |||
| 2498 | if (unlikely(dev->bus != &pci_bus_type)) | ||
| 2499 | return 1; | ||
| 2500 | |||
| 2501 | pdev = to_pci_dev(dev); | ||
| 2502 | if (iommu_dummy(pdev)) | ||
| 2503 | return 1; | ||
| 2504 | |||
| 2505 | if (!iommu_identity_mapping) | ||
| 2506 | return 0; | ||
| 2507 | |||
| 2508 | found = identity_mapping(pdev); | ||
| 2509 | if (found) { | ||
| 2510 | if (iommu_should_identity_map(pdev, 0)) | ||
| 2511 | return 1; | ||
| 2512 | else { | ||
| 2513 | /* | ||
| 2514 | * 32 bit DMA is removed from si_domain and fall back | ||
| 2515 | * to non-identity mapping. | ||
| 2516 | */ | ||
| 2517 | domain_remove_one_dev_info(si_domain, pdev); | ||
| 2518 | printk(KERN_INFO "32bit %s uses non-identity mapping\n", | ||
| 2519 | pci_name(pdev)); | ||
| 2520 | return 0; | ||
| 2521 | } | ||
| 2522 | } else { | ||
| 2523 | /* | ||
| 2524 | * In case of a detached 64 bit DMA device from vm, the device | ||
| 2525 | * is put into si_domain for identity mapping. | ||
| 2526 | */ | ||
| 2527 | if (iommu_should_identity_map(pdev, 0)) { | ||
| 2528 | int ret; | ||
| 2529 | ret = domain_add_dev_info(si_domain, pdev); | ||
| 2530 | if (ret) | ||
| 2531 | return 0; | ||
| 2532 | ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); | ||
| 2533 | if (!ret) { | ||
| 2534 | printk(KERN_INFO "64bit %s uses identity mapping\n", | ||
| 2535 | pci_name(pdev)); | ||
| 2536 | return 1; | ||
| 2537 | } | ||
| 2538 | } | ||
| 2539 | } | ||
| 2540 | |||
| 2541 | return 0; | ||
| 2542 | } | ||
| 2543 | |||
| 2251 | static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | 2544 | static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, |
| 2252 | size_t size, int dir, u64 dma_mask) | 2545 | size_t size, int dir, u64 dma_mask) |
| 2253 | { | 2546 | { |
| @@ -2260,7 +2553,8 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
| 2260 | struct intel_iommu *iommu; | 2553 | struct intel_iommu *iommu; |
| 2261 | 2554 | ||
| 2262 | BUG_ON(dir == DMA_NONE); | 2555 | BUG_ON(dir == DMA_NONE); |
| 2263 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) | 2556 | |
| 2557 | if (iommu_no_mapping(hwdev)) | ||
| 2264 | return paddr; | 2558 | return paddr; |
| 2265 | 2559 | ||
| 2266 | domain = get_valid_domain_for_dev(pdev); | 2560 | domain = get_valid_domain_for_dev(pdev); |
| @@ -2268,14 +2562,13 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
| 2268 | return 0; | 2562 | return 0; |
| 2269 | 2563 | ||
| 2270 | iommu = domain_get_iommu(domain); | 2564 | iommu = domain_get_iommu(domain); |
| 2271 | size = aligned_size((u64)paddr, size); | 2565 | size = aligned_nrpages(paddr, size); |
| 2272 | 2566 | ||
| 2273 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2567 | iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), |
| 2568 | pdev->dma_mask); | ||
| 2274 | if (!iova) | 2569 | if (!iova) |
| 2275 | goto error; | 2570 | goto error; |
| 2276 | 2571 | ||
| 2277 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; | ||
| 2278 | |||
| 2279 | /* | 2572 | /* |
| 2280 | * Check if DMAR supports zero-length reads on write only | 2573 | * Check if DMAR supports zero-length reads on write only |
| 2281 | * mappings.. | 2574 | * mappings.. |
| @@ -2291,20 +2584,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
| 2291 | * might have two guest_addr mapping to the same host paddr, but this | 2584 | * might have two guest_addr mapping to the same host paddr, but this |
| 2292 | * is not a big problem | 2585 | * is not a big problem |
| 2293 | */ | 2586 | */ |
| 2294 | ret = domain_page_mapping(domain, start_paddr, | 2587 | ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), |
| 2295 | ((u64)paddr) & PHYSICAL_PAGE_MASK, | 2588 | paddr >> VTD_PAGE_SHIFT, size, prot); |
| 2296 | size, prot); | ||
| 2297 | if (ret) | 2589 | if (ret) |
| 2298 | goto error; | 2590 | goto error; |
| 2299 | 2591 | ||
| 2300 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2592 | /* it's a non-present to present mapping. Only flush if caching mode */ |
| 2301 | if (cap_caching_mode(iommu->cap)) | 2593 | if (cap_caching_mode(iommu->cap)) |
| 2302 | iommu_flush_iotlb_psi(iommu, 0, start_paddr, | 2594 | iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); |
| 2303 | size >> VTD_PAGE_SHIFT); | ||
| 2304 | else | 2595 | else |
| 2305 | iommu_flush_write_buffer(iommu); | 2596 | iommu_flush_write_buffer(iommu); |
| 2306 | 2597 | ||
| 2307 | return start_paddr + ((u64)paddr & (~PAGE_MASK)); | 2598 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; |
| 2599 | start_paddr += paddr & ~PAGE_MASK; | ||
| 2600 | return start_paddr; | ||
| 2308 | 2601 | ||
| 2309 | error: | 2602 | error: |
| 2310 | if (iova) | 2603 | if (iova) |
| @@ -2397,34 +2690,38 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
| 2397 | { | 2690 | { |
| 2398 | struct pci_dev *pdev = to_pci_dev(dev); | 2691 | struct pci_dev *pdev = to_pci_dev(dev); |
| 2399 | struct dmar_domain *domain; | 2692 | struct dmar_domain *domain; |
| 2400 | unsigned long start_addr; | 2693 | unsigned long start_pfn, last_pfn; |
| 2401 | struct iova *iova; | 2694 | struct iova *iova; |
| 2402 | struct intel_iommu *iommu; | 2695 | struct intel_iommu *iommu; |
| 2403 | 2696 | ||
| 2404 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) | 2697 | if (iommu_no_mapping(dev)) |
| 2405 | return; | 2698 | return; |
| 2699 | |||
| 2406 | domain = find_domain(pdev); | 2700 | domain = find_domain(pdev); |
| 2407 | BUG_ON(!domain); | 2701 | BUG_ON(!domain); |
| 2408 | 2702 | ||
| 2409 | iommu = domain_get_iommu(domain); | 2703 | iommu = domain_get_iommu(domain); |
| 2410 | 2704 | ||
| 2411 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); | 2705 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); |
| 2412 | if (!iova) | 2706 | if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", |
| 2707 | (unsigned long long)dev_addr)) | ||
| 2413 | return; | 2708 | return; |
| 2414 | 2709 | ||
| 2415 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2710 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2416 | size = aligned_size((u64)dev_addr, size); | 2711 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; |
| 2417 | 2712 | ||
| 2418 | pr_debug("Device %s unmapping: %zx@%llx\n", | 2713 | pr_debug("Device %s unmapping: pfn %lx-%lx\n", |
| 2419 | pci_name(pdev), size, (unsigned long long)start_addr); | 2714 | pci_name(pdev), start_pfn, last_pfn); |
| 2420 | 2715 | ||
| 2421 | /* clear the whole page */ | 2716 | /* clear the whole page */ |
| 2422 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2717 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
| 2718 | |||
| 2423 | /* free page tables */ | 2719 | /* free page tables */ |
| 2424 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2720 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
| 2721 | |||
| 2425 | if (intel_iommu_strict) { | 2722 | if (intel_iommu_strict) { |
| 2426 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2723 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
| 2427 | size >> VTD_PAGE_SHIFT); | 2724 | last_pfn - start_pfn + 1); |
| 2428 | /* free iova */ | 2725 | /* free iova */ |
| 2429 | __free_iova(&domain->iovad, iova); | 2726 | __free_iova(&domain->iovad, iova); |
| 2430 | } else { | 2727 | } else { |
| @@ -2482,17 +2779,13 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
| 2482 | int nelems, enum dma_data_direction dir, | 2779 | int nelems, enum dma_data_direction dir, |
| 2483 | struct dma_attrs *attrs) | 2780 | struct dma_attrs *attrs) |
| 2484 | { | 2781 | { |
| 2485 | int i; | ||
| 2486 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2782 | struct pci_dev *pdev = to_pci_dev(hwdev); |
| 2487 | struct dmar_domain *domain; | 2783 | struct dmar_domain *domain; |
| 2488 | unsigned long start_addr; | 2784 | unsigned long start_pfn, last_pfn; |
| 2489 | struct iova *iova; | 2785 | struct iova *iova; |
| 2490 | size_t size = 0; | ||
| 2491 | phys_addr_t addr; | ||
| 2492 | struct scatterlist *sg; | ||
| 2493 | struct intel_iommu *iommu; | 2786 | struct intel_iommu *iommu; |
| 2494 | 2787 | ||
| 2495 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) | 2788 | if (iommu_no_mapping(hwdev)) |
| 2496 | return; | 2789 | return; |
| 2497 | 2790 | ||
| 2498 | domain = find_domain(pdev); | 2791 | domain = find_domain(pdev); |
| @@ -2501,22 +2794,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
| 2501 | iommu = domain_get_iommu(domain); | 2794 | iommu = domain_get_iommu(domain); |
| 2502 | 2795 | ||
| 2503 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); | 2796 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); |
| 2504 | if (!iova) | 2797 | if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n", |
| 2798 | (unsigned long long)sglist[0].dma_address)) | ||
| 2505 | return; | 2799 | return; |
| 2506 | for_each_sg(sglist, sg, nelems, i) { | ||
| 2507 | addr = page_to_phys(sg_page(sg)) + sg->offset; | ||
| 2508 | size += aligned_size((u64)addr, sg->length); | ||
| 2509 | } | ||
| 2510 | 2800 | ||
| 2511 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2801 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2802 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; | ||
| 2512 | 2803 | ||
| 2513 | /* clear the whole page */ | 2804 | /* clear the whole page */ |
| 2514 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2805 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
| 2806 | |||
| 2515 | /* free page tables */ | 2807 | /* free page tables */ |
| 2516 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2808 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
| 2517 | 2809 | ||
| 2518 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2810 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
| 2519 | size >> VTD_PAGE_SHIFT); | 2811 | (last_pfn - start_pfn + 1)); |
| 2520 | 2812 | ||
| 2521 | /* free iova */ | 2813 | /* free iova */ |
| 2522 | __free_iova(&domain->iovad, iova); | 2814 | __free_iova(&domain->iovad, iova); |
| @@ -2539,21 +2831,20 @@ static int intel_nontranslate_map_sg(struct device *hddev, | |||
| 2539 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, | 2831 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, |
| 2540 | enum dma_data_direction dir, struct dma_attrs *attrs) | 2832 | enum dma_data_direction dir, struct dma_attrs *attrs) |
| 2541 | { | 2833 | { |
| 2542 | phys_addr_t addr; | ||
| 2543 | int i; | 2834 | int i; |
| 2544 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2835 | struct pci_dev *pdev = to_pci_dev(hwdev); |
| 2545 | struct dmar_domain *domain; | 2836 | struct dmar_domain *domain; |
| 2546 | size_t size = 0; | 2837 | size_t size = 0; |
| 2547 | int prot = 0; | 2838 | int prot = 0; |
| 2548 | size_t offset = 0; | 2839 | size_t offset_pfn = 0; |
| 2549 | struct iova *iova = NULL; | 2840 | struct iova *iova = NULL; |
| 2550 | int ret; | 2841 | int ret; |
| 2551 | struct scatterlist *sg; | 2842 | struct scatterlist *sg; |
| 2552 | unsigned long start_addr; | 2843 | unsigned long start_vpfn; |
| 2553 | struct intel_iommu *iommu; | 2844 | struct intel_iommu *iommu; |
| 2554 | 2845 | ||
| 2555 | BUG_ON(dir == DMA_NONE); | 2846 | BUG_ON(dir == DMA_NONE); |
| 2556 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) | 2847 | if (iommu_no_mapping(hwdev)) |
| 2557 | return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); | 2848 | return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); |
| 2558 | 2849 | ||
| 2559 | domain = get_valid_domain_for_dev(pdev); | 2850 | domain = get_valid_domain_for_dev(pdev); |
| @@ -2562,12 +2853,11 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
| 2562 | 2853 | ||
| 2563 | iommu = domain_get_iommu(domain); | 2854 | iommu = domain_get_iommu(domain); |
| 2564 | 2855 | ||
| 2565 | for_each_sg(sglist, sg, nelems, i) { | 2856 | for_each_sg(sglist, sg, nelems, i) |
| 2566 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2857 | size += aligned_nrpages(sg->offset, sg->length); |
| 2567 | size += aligned_size((u64)addr, sg->length); | ||
| 2568 | } | ||
| 2569 | 2858 | ||
| 2570 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2859 | iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), |
| 2860 | pdev->dma_mask); | ||
| 2571 | if (!iova) { | 2861 | if (!iova) { |
| 2572 | sglist->dma_length = 0; | 2862 | sglist->dma_length = 0; |
| 2573 | return 0; | 2863 | return 0; |
| @@ -2583,35 +2873,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
| 2583 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) | 2873 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) |
| 2584 | prot |= DMA_PTE_WRITE; | 2874 | prot |= DMA_PTE_WRITE; |
| 2585 | 2875 | ||
| 2586 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2876 | start_vpfn = mm_to_dma_pfn(iova->pfn_lo); |
| 2587 | offset = 0; | 2877 | |
| 2588 | for_each_sg(sglist, sg, nelems, i) { | 2878 | ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot); |
| 2589 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2879 | if (unlikely(ret)) { |
| 2590 | size = aligned_size((u64)addr, sg->length); | 2880 | /* clear the page */ |
| 2591 | ret = domain_page_mapping(domain, start_addr + offset, | 2881 | dma_pte_clear_range(domain, start_vpfn, |
| 2592 | ((u64)addr) & PHYSICAL_PAGE_MASK, | 2882 | start_vpfn + size - 1); |
| 2593 | size, prot); | 2883 | /* free page tables */ |
| 2594 | if (ret) { | 2884 | dma_pte_free_pagetable(domain, start_vpfn, |
| 2595 | /* clear the page */ | 2885 | start_vpfn + size - 1); |
| 2596 | dma_pte_clear_range(domain, start_addr, | 2886 | /* free iova */ |
| 2597 | start_addr + offset); | 2887 | __free_iova(&domain->iovad, iova); |
| 2598 | /* free page tables */ | 2888 | return 0; |
| 2599 | dma_pte_free_pagetable(domain, start_addr, | ||
| 2600 | start_addr + offset); | ||
| 2601 | /* free iova */ | ||
| 2602 | __free_iova(&domain->iovad, iova); | ||
| 2603 | return 0; | ||
| 2604 | } | ||
| 2605 | sg->dma_address = start_addr + offset + | ||
| 2606 | ((u64)addr & (~PAGE_MASK)); | ||
| 2607 | sg->dma_length = sg->length; | ||
| 2608 | offset += size; | ||
| 2609 | } | 2889 | } |
| 2610 | 2890 | ||
| 2611 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2891 | /* it's a non-present to present mapping. Only flush if caching mode */ |
| 2612 | if (cap_caching_mode(iommu->cap)) | 2892 | if (cap_caching_mode(iommu->cap)) |
| 2613 | iommu_flush_iotlb_psi(iommu, 0, start_addr, | 2893 | iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); |
| 2614 | offset >> VTD_PAGE_SHIFT); | ||
| 2615 | else | 2894 | else |
| 2616 | iommu_flush_write_buffer(iommu); | 2895 | iommu_flush_write_buffer(iommu); |
| 2617 | 2896 | ||
| @@ -2951,31 +3230,6 @@ int __init intel_iommu_init(void) | |||
| 2951 | return 0; | 3230 | return 0; |
| 2952 | } | 3231 | } |
| 2953 | 3232 | ||
| 2954 | static int vm_domain_add_dev_info(struct dmar_domain *domain, | ||
| 2955 | struct pci_dev *pdev) | ||
| 2956 | { | ||
| 2957 | struct device_domain_info *info; | ||
| 2958 | unsigned long flags; | ||
| 2959 | |||
| 2960 | info = alloc_devinfo_mem(); | ||
| 2961 | if (!info) | ||
| 2962 | return -ENOMEM; | ||
| 2963 | |||
| 2964 | info->segment = pci_domain_nr(pdev->bus); | ||
| 2965 | info->bus = pdev->bus->number; | ||
| 2966 | info->devfn = pdev->devfn; | ||
| 2967 | info->dev = pdev; | ||
| 2968 | info->domain = domain; | ||
| 2969 | |||
| 2970 | spin_lock_irqsave(&device_domain_lock, flags); | ||
| 2971 | list_add(&info->link, &domain->devices); | ||
| 2972 | list_add(&info->global, &device_domain_list); | ||
| 2973 | pdev->dev.archdata.iommu = info; | ||
| 2974 | spin_unlock_irqrestore(&device_domain_lock, flags); | ||
| 2975 | |||
| 2976 | return 0; | ||
| 2977 | } | ||
| 2978 | |||
| 2979 | static void iommu_detach_dependent_devices(struct intel_iommu *iommu, | 3233 | static void iommu_detach_dependent_devices(struct intel_iommu *iommu, |
| 2980 | struct pci_dev *pdev) | 3234 | struct pci_dev *pdev) |
| 2981 | { | 3235 | { |
| @@ -3003,7 +3257,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, | |||
| 3003 | } | 3257 | } |
| 3004 | } | 3258 | } |
| 3005 | 3259 | ||
| 3006 | static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, | 3260 | static void domain_remove_one_dev_info(struct dmar_domain *domain, |
| 3007 | struct pci_dev *pdev) | 3261 | struct pci_dev *pdev) |
| 3008 | { | 3262 | { |
| 3009 | struct device_domain_info *info; | 3263 | struct device_domain_info *info; |
| @@ -3136,12 +3390,11 @@ static struct dmar_domain *iommu_alloc_vm_domain(void) | |||
| 3136 | return domain; | 3390 | return domain; |
| 3137 | } | 3391 | } |
| 3138 | 3392 | ||
| 3139 | static int vm_domain_init(struct dmar_domain *domain, int guest_width) | 3393 | static int md_domain_init(struct dmar_domain *domain, int guest_width) |
| 3140 | { | 3394 | { |
| 3141 | int adjust_width; | 3395 | int adjust_width; |
| 3142 | 3396 | ||
| 3143 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 3397 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
| 3144 | spin_lock_init(&domain->mapping_lock); | ||
| 3145 | spin_lock_init(&domain->iommu_lock); | 3398 | spin_lock_init(&domain->iommu_lock); |
| 3146 | 3399 | ||
| 3147 | domain_reserve_special_ranges(domain); | 3400 | domain_reserve_special_ranges(domain); |
| @@ -3195,8 +3448,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
| 3195 | 3448 | ||
| 3196 | static void vm_domain_exit(struct dmar_domain *domain) | 3449 | static void vm_domain_exit(struct dmar_domain *domain) |
| 3197 | { | 3450 | { |
| 3198 | u64 end; | ||
| 3199 | |||
| 3200 | /* Domain 0 is reserved, so dont process it */ | 3451 | /* Domain 0 is reserved, so dont process it */ |
| 3201 | if (!domain) | 3452 | if (!domain) |
| 3202 | return; | 3453 | return; |
| @@ -3204,14 +3455,12 @@ static void vm_domain_exit(struct dmar_domain *domain) | |||
| 3204 | vm_domain_remove_all_dev_info(domain); | 3455 | vm_domain_remove_all_dev_info(domain); |
| 3205 | /* destroy iovas */ | 3456 | /* destroy iovas */ |
| 3206 | put_iova_domain(&domain->iovad); | 3457 | put_iova_domain(&domain->iovad); |
| 3207 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
| 3208 | end = end & (~VTD_PAGE_MASK); | ||
| 3209 | 3458 | ||
| 3210 | /* clear ptes */ | 3459 | /* clear ptes */ |
| 3211 | dma_pte_clear_range(domain, 0, end); | 3460 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 3212 | 3461 | ||
| 3213 | /* free page tables */ | 3462 | /* free page tables */ |
| 3214 | dma_pte_free_pagetable(domain, 0, end); | 3463 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
| 3215 | 3464 | ||
| 3216 | iommu_free_vm_domain(domain); | 3465 | iommu_free_vm_domain(domain); |
| 3217 | free_domain_mem(domain); | 3466 | free_domain_mem(domain); |
| @@ -3227,7 +3476,7 @@ static int intel_iommu_domain_init(struct iommu_domain *domain) | |||
| 3227 | "intel_iommu_domain_init: dmar_domain == NULL\n"); | 3476 | "intel_iommu_domain_init: dmar_domain == NULL\n"); |
| 3228 | return -ENOMEM; | 3477 | return -ENOMEM; |
| 3229 | } | 3478 | } |
| 3230 | if (vm_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { | 3479 | if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { |
| 3231 | printk(KERN_ERR | 3480 | printk(KERN_ERR |
| 3232 | "intel_iommu_domain_init() failed\n"); | 3481 | "intel_iommu_domain_init() failed\n"); |
| 3233 | vm_domain_exit(dmar_domain); | 3482 | vm_domain_exit(dmar_domain); |
| @@ -3262,8 +3511,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
| 3262 | 3511 | ||
| 3263 | old_domain = find_domain(pdev); | 3512 | old_domain = find_domain(pdev); |
| 3264 | if (old_domain) { | 3513 | if (old_domain) { |
| 3265 | if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) | 3514 | if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE || |
| 3266 | vm_domain_remove_one_dev_info(old_domain, pdev); | 3515 | dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) |
| 3516 | domain_remove_one_dev_info(old_domain, pdev); | ||
| 3267 | else | 3517 | else |
| 3268 | domain_remove_dev_info(old_domain); | 3518 | domain_remove_dev_info(old_domain); |
| 3269 | } | 3519 | } |
| @@ -3285,7 +3535,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
| 3285 | return -EFAULT; | 3535 | return -EFAULT; |
| 3286 | } | 3536 | } |
| 3287 | 3537 | ||
| 3288 | ret = vm_domain_add_dev_info(dmar_domain, pdev); | 3538 | ret = domain_add_dev_info(dmar_domain, pdev); |
| 3289 | if (ret) | 3539 | if (ret) |
| 3290 | return ret; | 3540 | return ret; |
| 3291 | 3541 | ||
| @@ -3299,7 +3549,7 @@ static void intel_iommu_detach_device(struct iommu_domain *domain, | |||
| 3299 | struct dmar_domain *dmar_domain = domain->priv; | 3549 | struct dmar_domain *dmar_domain = domain->priv; |
| 3300 | struct pci_dev *pdev = to_pci_dev(dev); | 3550 | struct pci_dev *pdev = to_pci_dev(dev); |
| 3301 | 3551 | ||
| 3302 | vm_domain_remove_one_dev_info(dmar_domain, pdev); | 3552 | domain_remove_one_dev_info(dmar_domain, pdev); |
| 3303 | } | 3553 | } |
| 3304 | 3554 | ||
| 3305 | static int intel_iommu_map_range(struct iommu_domain *domain, | 3555 | static int intel_iommu_map_range(struct iommu_domain *domain, |
| @@ -3319,7 +3569,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3319 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3569 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
| 3320 | prot |= DMA_PTE_SNP; | 3570 | prot |= DMA_PTE_SNP; |
| 3321 | 3571 | ||
| 3322 | max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size); | 3572 | max_addr = iova + size; |
| 3323 | if (dmar_domain->max_addr < max_addr) { | 3573 | if (dmar_domain->max_addr < max_addr) { |
| 3324 | int min_agaw; | 3574 | int min_agaw; |
| 3325 | u64 end; | 3575 | u64 end; |
| @@ -3337,8 +3587,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3337 | } | 3587 | } |
| 3338 | dmar_domain->max_addr = max_addr; | 3588 | dmar_domain->max_addr = max_addr; |
| 3339 | } | 3589 | } |
| 3340 | 3590 | /* Round up size to next multiple of PAGE_SIZE, if it and | |
| 3341 | ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot); | 3591 | the low bits of hpa would take us onto the next page */ |
| 3592 | size = aligned_nrpages(hpa, size); | ||
| 3593 | ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, | ||
| 3594 | hpa >> VTD_PAGE_SHIFT, size, prot); | ||
| 3342 | return ret; | 3595 | return ret; |
| 3343 | } | 3596 | } |
| 3344 | 3597 | ||
| @@ -3346,15 +3599,15 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, | |||
| 3346 | unsigned long iova, size_t size) | 3599 | unsigned long iova, size_t size) |
| 3347 | { | 3600 | { |
| 3348 | struct dmar_domain *dmar_domain = domain->priv; | 3601 | struct dmar_domain *dmar_domain = domain->priv; |
| 3349 | dma_addr_t base; | ||
| 3350 | 3602 | ||
| 3351 | /* The address might not be aligned */ | 3603 | if (!size) |
| 3352 | base = iova & VTD_PAGE_MASK; | 3604 | return; |
| 3353 | size = VTD_PAGE_ALIGN(size); | 3605 | |
| 3354 | dma_pte_clear_range(dmar_domain, base, base + size); | 3606 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
| 3607 | (iova + size - 1) >> VTD_PAGE_SHIFT); | ||
| 3355 | 3608 | ||
| 3356 | if (dmar_domain->max_addr == base + size) | 3609 | if (dmar_domain->max_addr == iova + size) |
| 3357 | dmar_domain->max_addr = base; | 3610 | dmar_domain->max_addr = iova; |
| 3358 | } | 3611 | } |
| 3359 | 3612 | ||
| 3360 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3613 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
| @@ -3364,7 +3617,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | |||
| 3364 | struct dma_pte *pte; | 3617 | struct dma_pte *pte; |
| 3365 | u64 phys = 0; | 3618 | u64 phys = 0; |
| 3366 | 3619 | ||
| 3367 | pte = addr_to_dma_pte(dmar_domain, iova); | 3620 | pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT); |
| 3368 | if (pte) | 3621 | if (pte) |
| 3369 | phys = dma_pte_addr(pte); | 3622 | phys = dma_pte_addr(pte); |
| 3370 | 3623 | ||
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 1e83c8c5f985..4f5b8712931f 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #include <linux/intel-iommu.h> | 10 | #include <linux/intel-iommu.h> |
| 11 | #include "intr_remapping.h" | 11 | #include "intr_remapping.h" |
| 12 | #include <acpi/acpi.h> | 12 | #include <acpi/acpi.h> |
| 13 | #include <asm/pci-direct.h> | ||
| 14 | #include "pci.h" | ||
| 13 | 15 | ||
| 14 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | 16 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; |
| 15 | static int ir_ioapic_num; | 17 | static int ir_ioapic_num; |
| @@ -314,7 +316,8 @@ int modify_irte(int irq, struct irte *irte_modified) | |||
| 314 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | 316 | index = irq_iommu->irte_index + irq_iommu->sub_handle; |
| 315 | irte = &iommu->ir_table->base[index]; | 317 | irte = &iommu->ir_table->base[index]; |
| 316 | 318 | ||
| 317 | set_64bit((unsigned long *)irte, irte_modified->low); | 319 | set_64bit((unsigned long *)&irte->low, irte_modified->low); |
| 320 | set_64bit((unsigned long *)&irte->high, irte_modified->high); | ||
| 318 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); | 321 | __iommu_flush_cache(iommu, irte, sizeof(*irte)); |
| 319 | 322 | ||
| 320 | rc = qi_flush_iec(iommu, index, 0); | 323 | rc = qi_flush_iec(iommu, index, 0); |
| @@ -369,12 +372,32 @@ struct intel_iommu *map_dev_to_ir(struct pci_dev *dev) | |||
| 369 | return drhd->iommu; | 372 | return drhd->iommu; |
| 370 | } | 373 | } |
| 371 | 374 | ||
| 375 | static int clear_entries(struct irq_2_iommu *irq_iommu) | ||
| 376 | { | ||
| 377 | struct irte *start, *entry, *end; | ||
| 378 | struct intel_iommu *iommu; | ||
| 379 | int index; | ||
| 380 | |||
| 381 | if (irq_iommu->sub_handle) | ||
| 382 | return 0; | ||
| 383 | |||
| 384 | iommu = irq_iommu->iommu; | ||
| 385 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | ||
| 386 | |||
| 387 | start = iommu->ir_table->base + index; | ||
| 388 | end = start + (1 << irq_iommu->irte_mask); | ||
| 389 | |||
| 390 | for (entry = start; entry < end; entry++) { | ||
| 391 | set_64bit((unsigned long *)&entry->low, 0); | ||
| 392 | set_64bit((unsigned long *)&entry->high, 0); | ||
| 393 | } | ||
| 394 | |||
| 395 | return qi_flush_iec(iommu, index, irq_iommu->irte_mask); | ||
| 396 | } | ||
| 397 | |||
| 372 | int free_irte(int irq) | 398 | int free_irte(int irq) |
| 373 | { | 399 | { |
| 374 | int rc = 0; | 400 | int rc = 0; |
| 375 | int index, i; | ||
| 376 | struct irte *irte; | ||
| 377 | struct intel_iommu *iommu; | ||
| 378 | struct irq_2_iommu *irq_iommu; | 401 | struct irq_2_iommu *irq_iommu; |
| 379 | unsigned long flags; | 402 | unsigned long flags; |
| 380 | 403 | ||
| @@ -385,16 +408,7 @@ int free_irte(int irq) | |||
| 385 | return -1; | 408 | return -1; |
| 386 | } | 409 | } |
| 387 | 410 | ||
| 388 | iommu = irq_iommu->iommu; | 411 | rc = clear_entries(irq_iommu); |
| 389 | |||
| 390 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | ||
| 391 | irte = &iommu->ir_table->base[index]; | ||
| 392 | |||
| 393 | if (!irq_iommu->sub_handle) { | ||
| 394 | for (i = 0; i < (1 << irq_iommu->irte_mask); i++) | ||
| 395 | set_64bit((unsigned long *)(irte + i), 0); | ||
| 396 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); | ||
| 397 | } | ||
| 398 | 412 | ||
| 399 | irq_iommu->iommu = NULL; | 413 | irq_iommu->iommu = NULL; |
| 400 | irq_iommu->irte_index = 0; | 414 | irq_iommu->irte_index = 0; |
| @@ -406,6 +420,91 @@ int free_irte(int irq) | |||
| 406 | return rc; | 420 | return rc; |
| 407 | } | 421 | } |
| 408 | 422 | ||
| 423 | /* | ||
| 424 | * source validation type | ||
| 425 | */ | ||
| 426 | #define SVT_NO_VERIFY 0x0 /* no verification is required */ | ||
| 427 | #define SVT_VERIFY_SID_SQ 0x1 /* verify using SID and SQ fiels */ | ||
| 428 | #define SVT_VERIFY_BUS 0x2 /* verify bus of request-id */ | ||
| 429 | |||
| 430 | /* | ||
| 431 | * source-id qualifier | ||
| 432 | */ | ||
| 433 | #define SQ_ALL_16 0x0 /* verify all 16 bits of request-id */ | ||
| 434 | #define SQ_13_IGNORE_1 0x1 /* verify most significant 13 bits, ignore | ||
| 435 | * the third least significant bit | ||
| 436 | */ | ||
| 437 | #define SQ_13_IGNORE_2 0x2 /* verify most significant 13 bits, ignore | ||
| 438 | * the second and third least significant bits | ||
| 439 | */ | ||
| 440 | #define SQ_13_IGNORE_3 0x3 /* verify most significant 13 bits, ignore | ||
| 441 | * the least three significant bits | ||
| 442 | */ | ||
| 443 | |||
| 444 | /* | ||
| 445 | * set SVT, SQ and SID fields of irte to verify | ||
| 446 | * source ids of interrupt requests | ||
| 447 | */ | ||
| 448 | static void set_irte_sid(struct irte *irte, unsigned int svt, | ||
| 449 | unsigned int sq, unsigned int sid) | ||
| 450 | { | ||
| 451 | irte->svt = svt; | ||
| 452 | irte->sq = sq; | ||
| 453 | irte->sid = sid; | ||
| 454 | } | ||
| 455 | |||
| 456 | int set_ioapic_sid(struct irte *irte, int apic) | ||
| 457 | { | ||
| 458 | int i; | ||
| 459 | u16 sid = 0; | ||
| 460 | |||
| 461 | if (!irte) | ||
| 462 | return -1; | ||
| 463 | |||
| 464 | for (i = 0; i < MAX_IO_APICS; i++) { | ||
| 465 | if (ir_ioapic[i].id == apic) { | ||
| 466 | sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn; | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | if (sid == 0) { | ||
| 472 | pr_warning("Failed to set source-id of IOAPIC (%d)\n", apic); | ||
| 473 | return -1; | ||
| 474 | } | ||
| 475 | |||
| 476 | set_irte_sid(irte, 1, 0, sid); | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | int set_msi_sid(struct irte *irte, struct pci_dev *dev) | ||
| 482 | { | ||
| 483 | struct pci_dev *bridge; | ||
| 484 | |||
| 485 | if (!irte || !dev) | ||
| 486 | return -1; | ||
| 487 | |||
| 488 | /* PCIe device or Root Complex integrated PCI device */ | ||
| 489 | if (dev->is_pcie || !dev->bus->parent) { | ||
| 490 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, | ||
| 491 | (dev->bus->number << 8) | dev->devfn); | ||
| 492 | return 0; | ||
| 493 | } | ||
| 494 | |||
| 495 | bridge = pci_find_upstream_pcie_bridge(dev); | ||
| 496 | if (bridge) { | ||
| 497 | if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */ | ||
| 498 | set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, | ||
| 499 | (bridge->bus->number << 8) | dev->bus->number); | ||
| 500 | else /* this is a legacy PCI bridge */ | ||
| 501 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, | ||
| 502 | (bridge->bus->number << 8) | bridge->devfn); | ||
| 503 | } | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 409 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | 508 | static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) |
| 410 | { | 509 | { |
| 411 | u64 addr; | 510 | u64 addr; |
| @@ -612,6 +711,35 @@ error: | |||
| 612 | return -1; | 711 | return -1; |
| 613 | } | 712 | } |
| 614 | 713 | ||
| 714 | static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope, | ||
| 715 | struct intel_iommu *iommu) | ||
| 716 | { | ||
| 717 | struct acpi_dmar_pci_path *path; | ||
| 718 | u8 bus; | ||
| 719 | int count; | ||
| 720 | |||
| 721 | bus = scope->bus; | ||
| 722 | path = (struct acpi_dmar_pci_path *)(scope + 1); | ||
| 723 | count = (scope->length - sizeof(struct acpi_dmar_device_scope)) | ||
| 724 | / sizeof(struct acpi_dmar_pci_path); | ||
| 725 | |||
| 726 | while (--count > 0) { | ||
| 727 | /* | ||
| 728 | * Access PCI directly due to the PCI | ||
| 729 | * subsystem isn't initialized yet. | ||
| 730 | */ | ||
| 731 | bus = read_pci_config_byte(bus, path->dev, path->fn, | ||
| 732 | PCI_SECONDARY_BUS); | ||
| 733 | path++; | ||
| 734 | } | ||
| 735 | |||
| 736 | ir_ioapic[ir_ioapic_num].bus = bus; | ||
| 737 | ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn); | ||
| 738 | ir_ioapic[ir_ioapic_num].iommu = iommu; | ||
| 739 | ir_ioapic[ir_ioapic_num].id = scope->enumeration_id; | ||
| 740 | ir_ioapic_num++; | ||
| 741 | } | ||
| 742 | |||
| 615 | static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, | 743 | static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, |
| 616 | struct intel_iommu *iommu) | 744 | struct intel_iommu *iommu) |
| 617 | { | 745 | { |
| @@ -636,9 +764,7 @@ static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, | |||
| 636 | " 0x%Lx\n", scope->enumeration_id, | 764 | " 0x%Lx\n", scope->enumeration_id, |
| 637 | drhd->address); | 765 | drhd->address); |
| 638 | 766 | ||
| 639 | ir_ioapic[ir_ioapic_num].iommu = iommu; | 767 | ir_parse_one_ioapic_scope(scope, iommu); |
| 640 | ir_ioapic[ir_ioapic_num].id = scope->enumeration_id; | ||
| 641 | ir_ioapic_num++; | ||
| 642 | } | 768 | } |
| 643 | start += scope->length; | 769 | start += scope->length; |
| 644 | } | 770 | } |
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h index ca48f0df8ac9..63a263c18415 100644 --- a/drivers/pci/intr_remapping.h +++ b/drivers/pci/intr_remapping.h | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | struct ioapic_scope { | 3 | struct ioapic_scope { |
| 4 | struct intel_iommu *iommu; | 4 | struct intel_iommu *iommu; |
| 5 | unsigned int id; | 5 | unsigned int id; |
| 6 | unsigned int bus; /* PCI bus number */ | ||
| 7 | unsigned int devfn; /* PCI devfn number */ | ||
| 6 | }; | 8 | }; |
| 7 | 9 | ||
| 8 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) | 10 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) |
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index 2287116e9822..46dd440e2315 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c | |||
| @@ -1,9 +1,19 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2006, Intel Corporation. | 2 | * Copyright © 2006-2009, Intel Corporation. |
| 3 | * | 3 | * |
| 4 | * This file is released under the GPLv2. | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License along with | ||
| 14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
| 15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
| 5 | * | 16 | * |
| 6 | * Copyright (C) 2006-2008 Intel Corporation | ||
| 7 | * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | 17 | * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> |
| 8 | */ | 18 | */ |
| 9 | 19 | ||
| @@ -123,7 +133,15 @@ move_left: | |||
| 123 | /* Insert the new_iova into domain rbtree by holding writer lock */ | 133 | /* Insert the new_iova into domain rbtree by holding writer lock */ |
| 124 | /* Add new node and rebalance tree. */ | 134 | /* Add new node and rebalance tree. */ |
| 125 | { | 135 | { |
| 126 | struct rb_node **entry = &((prev)), *parent = NULL; | 136 | struct rb_node **entry, *parent = NULL; |
| 137 | |||
| 138 | /* If we have 'prev', it's a valid place to start the | ||
| 139 | insertion. Otherwise, start from the root. */ | ||
| 140 | if (prev) | ||
| 141 | entry = &prev; | ||
| 142 | else | ||
| 143 | entry = &iovad->rbroot.rb_node; | ||
| 144 | |||
| 127 | /* Figure out where to put new node */ | 145 | /* Figure out where to put new node */ |
| 128 | while (*entry) { | 146 | while (*entry) { |
| 129 | struct iova *this = container_of(*entry, | 147 | struct iova *this = container_of(*entry, |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d9f06fbfa0bf..d986afb7032b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control) | |||
| 127 | * reliably as devices without an INTx disable bit will then generate a | 127 | * reliably as devices without an INTx disable bit will then generate a |
| 128 | * level IRQ which will never be cleared. | 128 | * level IRQ which will never be cleared. |
| 129 | */ | 129 | */ |
| 130 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | 130 | static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) |
| 131 | { | 131 | { |
| 132 | u32 mask_bits = desc->masked; | 132 | u32 mask_bits = desc->masked; |
| 133 | 133 | ||
| 134 | if (!desc->msi_attrib.maskbit) | 134 | if (!desc->msi_attrib.maskbit) |
| 135 | return; | 135 | return 0; |
| 136 | 136 | ||
| 137 | mask_bits &= ~mask; | 137 | mask_bits &= ~mask; |
| 138 | mask_bits |= flag; | 138 | mask_bits |= flag; |
| 139 | pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); | 139 | pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); |
| 140 | desc->masked = mask_bits; | 140 | |
| 141 | return mask_bits; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | ||
| 145 | { | ||
| 146 | desc->masked = __msi_mask_irq(desc, mask, flag); | ||
| 141 | } | 147 | } |
| 142 | 148 | ||
| 143 | /* | 149 | /* |
| @@ -147,15 +153,21 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |||
| 147 | * file. This saves a few milliseconds when initialising devices with lots | 153 | * file. This saves a few milliseconds when initialising devices with lots |
| 148 | * of MSI-X interrupts. | 154 | * of MSI-X interrupts. |
| 149 | */ | 155 | */ |
| 150 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) | 156 | static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) |
| 151 | { | 157 | { |
| 152 | u32 mask_bits = desc->masked; | 158 | u32 mask_bits = desc->masked; |
| 153 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 159 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
| 154 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | 160 | PCI_MSIX_ENTRY_VECTOR_CTRL; |
| 155 | mask_bits &= ~1; | 161 | mask_bits &= ~1; |
| 156 | mask_bits |= flag; | 162 | mask_bits |= flag; |
| 157 | writel(mask_bits, desc->mask_base + offset); | 163 | writel(mask_bits, desc->mask_base + offset); |
| 158 | desc->masked = mask_bits; | 164 | |
| 165 | return mask_bits; | ||
| 166 | } | ||
| 167 | |||
| 168 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
| 169 | { | ||
| 170 | desc->masked = __msix_mask_irq(desc, flag); | ||
| 159 | } | 171 | } |
| 160 | 172 | ||
| 161 | static void msi_set_mask_bit(unsigned irq, u32 flag) | 173 | static void msi_set_mask_bit(unsigned irq, u32 flag) |
| @@ -188,9 +200,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
| 188 | void __iomem *base = entry->mask_base + | 200 | void __iomem *base = entry->mask_base + |
| 189 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 201 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
| 190 | 202 | ||
| 191 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 203 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); |
| 192 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | 204 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); |
| 193 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | 205 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA); |
| 194 | } else { | 206 | } else { |
| 195 | struct pci_dev *dev = entry->dev; | 207 | struct pci_dev *dev = entry->dev; |
| 196 | int pos = entry->msi_attrib.pos; | 208 | int pos = entry->msi_attrib.pos; |
| @@ -225,11 +237,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
| 225 | base = entry->mask_base + | 237 | base = entry->mask_base + |
| 226 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 238 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
| 227 | 239 | ||
| 228 | writel(msg->address_lo, | 240 | writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); |
| 229 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 241 | writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); |
| 230 | writel(msg->address_hi, | 242 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA); |
| 231 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
| 232 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
| 233 | } else { | 243 | } else { |
| 234 | struct pci_dev *dev = entry->dev; | 244 | struct pci_dev *dev = entry->dev; |
| 235 | int pos = entry->msi_attrib.pos; | 245 | int pos = entry->msi_attrib.pos; |
| @@ -385,6 +395,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
| 385 | /* Configure MSI capability structure */ | 395 | /* Configure MSI capability structure */ |
| 386 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); | 396 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); |
| 387 | if (ret) { | 397 | if (ret) { |
| 398 | msi_mask_irq(entry, mask, ~mask); | ||
| 388 | msi_free_irqs(dev); | 399 | msi_free_irqs(dev); |
| 389 | return ret; | 400 | return ret; |
| 390 | } | 401 | } |
| @@ -439,8 +450,14 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 439 | 450 | ||
| 440 | for (i = 0; i < nvec; i++) { | 451 | for (i = 0; i < nvec; i++) { |
| 441 | entry = alloc_msi_entry(dev); | 452 | entry = alloc_msi_entry(dev); |
| 442 | if (!entry) | 453 | if (!entry) { |
| 443 | break; | 454 | if (!i) |
| 455 | iounmap(base); | ||
| 456 | else | ||
| 457 | msi_free_irqs(dev); | ||
| 458 | /* No enough memory. Don't try again */ | ||
| 459 | return -ENOMEM; | ||
| 460 | } | ||
| 444 | 461 | ||
| 445 | j = entries[i].entry; | 462 | j = entries[i].entry; |
| 446 | entry->msi_attrib.is_msix = 1; | 463 | entry->msi_attrib.is_msix = 1; |
| @@ -487,7 +504,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 487 | set_irq_msi(entry->irq, entry); | 504 | set_irq_msi(entry->irq, entry); |
| 488 | j = entries[i].entry; | 505 | j = entries[i].entry; |
| 489 | entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + | 506 | entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + |
| 490 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | 507 | PCI_MSIX_ENTRY_VECTOR_CTRL); |
| 491 | msix_mask_irq(entry, 1); | 508 | msix_mask_irq(entry, 1); |
| 492 | i++; | 509 | i++; |
| 493 | } | 510 | } |
| @@ -611,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev) | |||
| 611 | pci_intx_for_msi(dev, 1); | 628 | pci_intx_for_msi(dev, 1); |
| 612 | dev->msi_enabled = 0; | 629 | dev->msi_enabled = 0; |
| 613 | 630 | ||
| 631 | /* Return the device with MSI unmasked as initial states */ | ||
| 614 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); | 632 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); |
| 615 | mask = msi_capable_mask(ctrl); | 633 | mask = msi_capable_mask(ctrl); |
| 616 | msi_mask_irq(desc, mask, ~mask); | 634 | /* Keep cached state to be restored */ |
| 635 | __msi_mask_irq(desc, mask, ~mask); | ||
| 617 | 636 | ||
| 618 | /* Restore dev->irq to its default pin-assertion irq */ | 637 | /* Restore dev->irq to its default pin-assertion irq */ |
| 619 | dev->irq = desc->msi_attrib.default_irq; | 638 | dev->irq = desc->msi_attrib.default_irq; |
| @@ -653,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
| 653 | 672 | ||
| 654 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | 673 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { |
| 655 | if (entry->msi_attrib.is_msix) { | 674 | if (entry->msi_attrib.is_msix) { |
| 656 | msix_mask_irq(entry, 1); | ||
| 657 | if (list_is_last(&entry->list, &dev->msi_list)) | 675 | if (list_is_last(&entry->list, &dev->msi_list)) |
| 658 | iounmap(entry->mask_base); | 676 | iounmap(entry->mask_base); |
| 659 | } | 677 | } |
| @@ -741,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev) | |||
| 741 | 759 | ||
| 742 | void pci_msix_shutdown(struct pci_dev* dev) | 760 | void pci_msix_shutdown(struct pci_dev* dev) |
| 743 | { | 761 | { |
| 762 | struct msi_desc *entry; | ||
| 763 | |||
| 744 | if (!pci_msi_enable || !dev || !dev->msix_enabled) | 764 | if (!pci_msi_enable || !dev || !dev->msix_enabled) |
| 745 | return; | 765 | return; |
| 746 | 766 | ||
| 767 | /* Return the device with MSI-X masked as initial states */ | ||
| 768 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
| 769 | /* Keep cached states to be restored */ | ||
| 770 | __msix_mask_irq(entry, 1); | ||
| 771 | } | ||
| 772 | |||
| 747 | msix_set_enable(dev, 0); | 773 | msix_set_enable(dev, 0); |
| 748 | pci_intx_for_msi(dev, 1); | 774 | pci_intx_for_msi(dev, 1); |
| 749 | dev->msix_enabled = 0; | 775 | dev->msix_enabled = 0; |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index a0662842550b..de27c1cb5a2b 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
| @@ -6,11 +6,11 @@ | |||
| 6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
| 7 | #define MSI_H | 7 | #define MSI_H |
| 8 | 8 | ||
| 9 | #define PCI_MSIX_ENTRY_SIZE 16 | 9 | #define PCI_MSIX_ENTRY_SIZE 16 |
| 10 | #define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 | 10 | #define PCI_MSIX_ENTRY_LOWER_ADDR 0 |
| 11 | #define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 | 11 | #define PCI_MSIX_ENTRY_UPPER_ADDR 4 |
| 12 | #define PCI_MSIX_ENTRY_DATA_OFFSET 8 | 12 | #define PCI_MSIX_ENTRY_DATA 8 |
| 13 | #define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 | 13 | #define PCI_MSIX_ENTRY_VECTOR_CTRL 12 |
| 14 | 14 | ||
| 15 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) | 15 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) |
| 16 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) | 16 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6c93af5ced18..dbd0f947f497 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev) | |||
| 1517 | * | 1517 | * |
| 1518 | * Perform INTx swizzling for a device behind one level of bridge. This is | 1518 | * Perform INTx swizzling for a device behind one level of bridge. This is |
| 1519 | * required by section 9.1 of the PCI-to-PCI bridge specification for devices | 1519 | * required by section 9.1 of the PCI-to-PCI bridge specification for devices |
| 1520 | * behind bridges on add-in cards. | 1520 | * behind bridges on add-in cards. For devices with ARI enabled, the slot |
| 1521 | * number is always 0 (see the Implementation Note in section 2.2.8.1 of | ||
| 1522 | * the PCI Express Base Specification, Revision 2.1) | ||
| 1521 | */ | 1523 | */ |
| 1522 | u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) | 1524 | u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) |
| 1523 | { | 1525 | { |
| 1524 | return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; | 1526 | int slot; |
| 1527 | |||
| 1528 | if (pci_ari_enabled(dev->bus)) | ||
| 1529 | slot = 0; | ||
| 1530 | else | ||
| 1531 | slot = PCI_SLOT(dev->devfn); | ||
| 1532 | |||
| 1533 | return (((pin - 1) + slot) % 4) + 1; | ||
| 1525 | } | 1534 | } |
| 1526 | 1535 | ||
| 1527 | int | 1536 | int |
| @@ -2171,7 +2180,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | |||
| 2171 | u16 ctrl; | 2180 | u16 ctrl; |
| 2172 | struct pci_dev *pdev; | 2181 | struct pci_dev *pdev; |
| 2173 | 2182 | ||
| 2174 | if (dev->subordinate) | 2183 | if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) |
| 2175 | return -ENOTTY; | 2184 | return -ENOTTY; |
| 2176 | 2185 | ||
| 2177 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 2186 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c index ece97df4df6d..a928d8ab6bda 100644 --- a/drivers/pci/pcie/aer/ecrc.c +++ b/drivers/pci/pcie/aer/ecrc.c | |||
| @@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev) | |||
| 106 | disable_ecrc_checking(dev); | 106 | disable_ecrc_checking(dev); |
| 107 | break; | 107 | break; |
| 108 | case ECRC_POLICY_ON: | 108 | case ECRC_POLICY_ON: |
| 109 | enable_ecrc_checking(dev);; | 109 | enable_ecrc_checking(dev); |
| 110 | break; | 110 | break; |
| 111 | default: | 111 | default: |
| 112 | return; | 112 | return; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 56552d74abea..06b965623962 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) | |||
| 1058 | } | 1058 | } |
| 1059 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); | 1059 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); |
| 1060 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); | 1060 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); |
| 1061 | /* ALi loses some register settings that we cannot then restore */ | ||
| 1062 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3); | ||
| 1063 | /* VIA comes back fine but we need to keep it alive or ACPI GTM failures | ||
| 1064 | occur when mode detecting */ | ||
| 1065 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3); | ||
| 1061 | 1066 | ||
| 1062 | /* This was originally an Alpha specific thing, but it really fits here. | 1067 | /* This was originally an Alpha specific thing, but it really fits here. |
| 1063 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. | 1068 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index eddb0748b0ea..8c02b6c53bdb 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
| @@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot); | |||
| 311 | #include <linux/pci_hotplug.h> | 311 | #include <linux/pci_hotplug.h> |
| 312 | /** | 312 | /** |
| 313 | * pci_hp_create_link - create symbolic link to the hotplug driver module. | 313 | * pci_hp_create_link - create symbolic link to the hotplug driver module. |
| 314 | * @slot: struct pci_slot | 314 | * @pci_slot: struct pci_slot |
| 315 | * | 315 | * |
| 316 | * Helper function for pci_hotplug_core.c to create symbolic link to | 316 | * Helper function for pci_hotplug_core.c to create symbolic link to |
| 317 | * the hotplug driver module. | 317 | * the hotplug driver module. |
| @@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link); | |||
| 334 | 334 | ||
| 335 | /** | 335 | /** |
| 336 | * pci_hp_remove_link - remove symbolic link to the hotplug driver module. | 336 | * pci_hp_remove_link - remove symbolic link to the hotplug driver module. |
| 337 | * @slot: struct pci_slot | 337 | * @pci_slot: struct pci_slot |
| 338 | * | 338 | * |
| 339 | * Helper function for pci_hotplug_core.c to remove symbolic link to | 339 | * Helper function for pci_hotplug_core.c to remove symbolic link to |
| 340 | * the hotplug driver module. | 340 | * the hotplug driver module. |
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index ec22284eed30..e1c1ec540893 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
| 12 | #include <linux/smp_lock.h> | ||
| 13 | #include <linux/syscalls.h> | 12 | #include <linux/syscalls.h> |
| 14 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
| 15 | #include "pci.h" | 14 | #include "pci.h" |
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 9ad97ea836e8..8eb04230fec7 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c | |||
| @@ -472,7 +472,8 @@ static int __init init_tcic(void) | |||
| 472 | init_timer(&poll_timer); | 472 | init_timer(&poll_timer); |
| 473 | 473 | ||
| 474 | /* Build interrupt mask */ | 474 | /* Build interrupt mask */ |
| 475 | printk(", %d sockets\n" KERN_INFO " irq list (", sockets); | 475 | printk(KERN_CONT ", %d sockets\n", sockets); |
| 476 | printk(KERN_INFO " irq list ("); | ||
| 476 | if (irq_list_count == 0) | 477 | if (irq_list_count == 0) |
| 477 | mask = irq_mask; | 478 | mask = irq_mask; |
| 478 | else | 479 | else |
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 659421d0ca46..d4ad50d737b0 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. | 2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -32,7 +32,7 @@ | |||
| 32 | #include "i82365.h" | 32 | #include "i82365.h" |
| 33 | 33 | ||
| 34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); | 34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); |
| 35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
| 36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
| 37 | 37 | ||
| 38 | #define CARD_MAX_SLOTS 2 | 38 | #define CARD_MAX_SLOTS 2 |
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 812f038e9bda..9b3c15827e5c 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * NEC VRC4173 CARDU driver for Socket Services | 6 | * NEC VRC4173 CARDU driver for Socket Services |
| 7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) | 7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) |
| 8 | * | 8 | * |
| 9 | * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 9 | * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> |
| 10 | * | 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
| 12 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
| @@ -41,7 +41,7 @@ | |||
| 41 | #include "vrc4173_cardu.h" | 41 | #include "vrc4173_cardu.h" |
| 42 | 42 | ||
| 43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); | 43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); |
| 44 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 44 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
| 45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
| 46 | 46 | ||
| 47 | static int vrc4173_cardu_slots; | 47 | static int vrc4173_cardu_slots; |
diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h index 7d77c74120c1..a7d96018ed8d 100644 --- a/drivers/pcmcia/vrc4173_cardu.h +++ b/drivers/pcmcia/vrc4173_cardu.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * BRIEF MODULE DESCRIPTION | 5 | * BRIEF MODULE DESCRIPTION |
| 6 | * Include file for NEC VRC4173 CARDU. | 6 | * Include file for NEC VRC4173 CARDU. |
| 7 | * | 7 | * |
| 8 | * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 8 | * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org> |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
| 11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c682ac536415..46dad12f952f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -34,10 +34,27 @@ config ACER_WMI | |||
| 34 | If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M | 34 | If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M |
| 35 | here. | 35 | here. |
| 36 | 36 | ||
| 37 | config ACERHDF | ||
| 38 | tristate "Acer Aspire One temperature and fan driver" | ||
| 39 | depends on THERMAL && THERMAL_HWMON && ACPI | ||
| 40 | ---help--- | ||
| 41 | This is a driver for Acer Aspire One netbooks. It allows to access | ||
| 42 | the temperature sensor and to control the fan. | ||
| 43 | |||
| 44 | After loading this driver the BIOS is still in control of the fan. | ||
| 45 | To let the kernel handle the fan, do: | ||
| 46 | echo -n enabled > /sys/class/thermal/thermal_zone0/mode | ||
| 47 | |||
| 48 | For more information about this driver see | ||
| 49 | <http://piie.net/files/acerhdf_README.txt> | ||
| 50 | |||
| 51 | If you have an Acer Aspire One netbook, say Y or M | ||
| 52 | here. | ||
| 53 | |||
| 37 | config ASUS_LAPTOP | 54 | config ASUS_LAPTOP |
| 38 | tristate "Asus Laptop Extras (EXPERIMENTAL)" | 55 | tristate "Asus Laptop Extras" |
| 39 | depends on ACPI | 56 | depends on ACPI |
| 40 | depends on EXPERIMENTAL && !ACPI_ASUS | 57 | depends on !ACPI_ASUS |
| 41 | select LEDS_CLASS | 58 | select LEDS_CLASS |
| 42 | select NEW_LEDS | 59 | select NEW_LEDS |
| 43 | select BACKLIGHT_CLASS_DEVICE | 60 | select BACKLIGHT_CLASS_DEVICE |
| @@ -45,12 +62,12 @@ config ASUS_LAPTOP | |||
| 45 | ---help--- | 62 | ---help--- |
| 46 | This is the new Linux driver for Asus laptops. It may also support some | 63 | This is the new Linux driver for Asus laptops. It may also support some |
| 47 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate | 64 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate |
| 48 | standard ACPI events that go through /proc/acpi/events. It also adds | 65 | standard ACPI events and input events. It also adds |
| 49 | support for video output switching, LCD backlight control, Bluetooth and | 66 | support for video output switching, LCD backlight control, Bluetooth and |
| 50 | Wlan control, and most importantly, allows you to blink those fancy LEDs. | 67 | Wlan control, and most importantly, allows you to blink those fancy LEDs. |
| 51 | 68 | ||
| 52 | For more information and a userspace daemon for handling the extra | 69 | For more information and a userspace daemon for handling the extra |
| 53 | buttons see <http://acpi4asus.sf.net/>. | 70 | buttons see <http://acpi4asus.sf.net>. |
| 54 | 71 | ||
| 55 | If you have an ACPI-compatible ASUS laptop, say Y or M here. | 72 | If you have an ACPI-compatible ASUS laptop, say Y or M here. |
| 56 | 73 | ||
| @@ -338,11 +355,15 @@ config EEEPC_LAPTOP | |||
| 338 | depends on INPUT | 355 | depends on INPUT |
| 339 | depends on EXPERIMENTAL | 356 | depends on EXPERIMENTAL |
| 340 | depends on RFKILL || RFKILL = n | 357 | depends on RFKILL || RFKILL = n |
| 358 | depends on HOTPLUG_PCI | ||
| 341 | select BACKLIGHT_CLASS_DEVICE | 359 | select BACKLIGHT_CLASS_DEVICE |
| 342 | select HWMON | 360 | select HWMON |
| 343 | ---help--- | 361 | ---help--- |
| 344 | This driver supports the Fn-Fx keys on Eee PC laptops. | 362 | This driver supports the Fn-Fx keys on Eee PC laptops. |
| 345 | It also adds the ability to switch camera/wlan on/off. | 363 | |
| 364 | It also gives access to some extra laptop functionalities like | ||
| 365 | Bluetooth, backlight and allows powering on/off some other | ||
| 366 | devices. | ||
| 346 | 367 | ||
| 347 | If you have an Eee PC laptop, say Y or M here. | 368 | If you have an Eee PC laptop, say Y or M here. |
| 348 | 369 | ||
| @@ -369,7 +390,7 @@ config ACPI_WMI | |||
| 369 | any ACPI-WMI devices. | 390 | any ACPI-WMI devices. |
| 370 | 391 | ||
| 371 | config ACPI_ASUS | 392 | config ACPI_ASUS |
| 372 | tristate "ASUS/Medion Laptop Extras" | 393 | tristate "ASUS/Medion Laptop Extras (DEPRECATED)" |
| 373 | depends on ACPI | 394 | depends on ACPI |
| 374 | select BACKLIGHT_CLASS_DEVICE | 395 | select BACKLIGHT_CLASS_DEVICE |
| 375 | ---help--- | 396 | ---help--- |
| @@ -390,7 +411,7 @@ config ACPI_ASUS | |||
| 390 | parameters. | 411 | parameters. |
| 391 | 412 | ||
| 392 | More information and a userspace daemon for handling the extra buttons | 413 | More information and a userspace daemon for handling the extra buttons |
| 393 | at <http://sourceforge.net/projects/acpi4asus/>. | 414 | at <http://acpi4asus.sf.net>. |
| 394 | 415 | ||
| 395 | If you have an ACPI-compatible ASUS laptop, say Y or M here. This | 416 | If you have an ACPI-compatible ASUS laptop, say Y or M here. This |
| 396 | driver is still under development, so if your laptop is unsupported or | 417 | driver is still under development, so if your laptop is unsupported or |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e40c7bd1b87e..641b8bfa5538 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -9,6 +9,7 @@ obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o | |||
| 9 | obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o | 9 | obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o |
| 10 | obj-$(CONFIG_DELL_WMI) += dell-wmi.o | 10 | obj-$(CONFIG_DELL_WMI) += dell-wmi.o |
| 11 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o | 11 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o |
| 12 | obj-$(CONFIG_ACERHDF) += acerhdf.o | ||
| 12 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | 13 | obj-$(CONFIG_HP_WMI) += hp-wmi.o |
| 13 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 14 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
| 14 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o | 15 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o |
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c new file mode 100644 index 000000000000..bdfee177eefb --- /dev/null +++ b/drivers/platform/x86/acerhdf.c | |||
| @@ -0,0 +1,602 @@ | |||
| 1 | /* | ||
| 2 | * acerhdf - A driver which monitors the temperature | ||
| 3 | * of the aspire one netbook, turns on/off the fan | ||
| 4 | * as soon as the upper/lower threshold is reached. | ||
| 5 | * | ||
| 6 | * (C) 2009 - Peter Feuerer peter (a) piie.net | ||
| 7 | * http://piie.net | ||
| 8 | * 2009 Borislav Petkov <petkovbb@gmail.com> | ||
| 9 | * | ||
| 10 | * Inspired by and many thanks to: | ||
| 11 | * o acerfand - Rachel Greenham | ||
| 12 | * o acer_ec.pl - Michael Kurz michi.kurz (at) googlemail.com | ||
| 13 | * - Petr Tomasek tomasek (#) etf,cuni,cz | ||
| 14 | * - Carlos Corbacho cathectic (at) gmail.com | ||
| 15 | * o lkml - Matthew Garrett | ||
| 16 | * - Borislav Petkov | ||
| 17 | * - Andreas Mohr | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or modify | ||
| 20 | * it under the terms of the GNU General Public License as published by | ||
| 21 | * the Free Software Foundation; either version 2 of the License, or | ||
| 22 | * (at your option) any later version. | ||
| 23 | * | ||
| 24 | * This program is distributed in the hope that it will be useful, | ||
| 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 27 | * GNU General Public License for more details. | ||
| 28 | * | ||
| 29 | * You should have received a copy of the GNU General Public License | ||
| 30 | * along with this program; if not, write to the Free Software | ||
| 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define pr_fmt(fmt) "acerhdf: " fmt | ||
| 35 | |||
| 36 | #include <linux/kernel.h> | ||
| 37 | #include <linux/module.h> | ||
| 38 | #include <linux/fs.h> | ||
| 39 | #include <linux/dmi.h> | ||
| 40 | #include <acpi/acpi_drivers.h> | ||
| 41 | #include <linux/sched.h> | ||
| 42 | #include <linux/thermal.h> | ||
| 43 | #include <linux/platform_device.h> | ||
| 44 | |||
| 45 | /* | ||
| 46 | * The driver is started with "kernel mode off" by default. That means, the BIOS | ||
| 47 | * is still in control of the fan. In this mode the driver allows to read the | ||
| 48 | * temperature of the cpu and a userspace tool may take over control of the fan. | ||
| 49 | * If the driver is switched to "kernel mode" (e.g. via module parameter) the | ||
| 50 | * driver is in full control of the fan. If you want the module to be started in | ||
| 51 | * kernel mode by default, define the following: | ||
| 52 | */ | ||
| 53 | #undef START_IN_KERNEL_MODE | ||
| 54 | |||
| 55 | #define DRV_VER "0.5.13" | ||
| 56 | |||
| 57 | /* | ||
| 58 | * According to the Atom N270 datasheet, | ||
| 59 | * (http://download.intel.com/design/processor/datashts/320032.pdf) the | ||
| 60 | * CPU's optimal operating limits denoted in junction temperature as | ||
| 61 | * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, | ||
| 62 | * assume 89°C is critical temperature. | ||
| 63 | */ | ||
| 64 | #define ACERHDF_TEMP_CRIT 89 | ||
| 65 | #define ACERHDF_FAN_OFF 0 | ||
| 66 | #define ACERHDF_FAN_AUTO 1 | ||
| 67 | |||
| 68 | /* | ||
| 69 | * No matter what value the user puts into the fanon variable, turn on the fan | ||
| 70 | * at 80 degree Celsius to prevent hardware damage | ||
| 71 | */ | ||
| 72 | #define ACERHDF_MAX_FANON 80 | ||
| 73 | |||
| 74 | /* | ||
| 75 | * Maximum interval between two temperature checks is 15 seconds, as the die | ||
| 76 | * can get hot really fast under heavy load (plus we shouldn't forget about | ||
| 77 | * possible impact of _external_ aggressive sources such as heaters, sun etc.) | ||
| 78 | */ | ||
| 79 | #define ACERHDF_MAX_INTERVAL 15 | ||
| 80 | |||
| 81 | #ifdef START_IN_KERNEL_MODE | ||
| 82 | static int kernelmode = 1; | ||
| 83 | #else | ||
| 84 | static int kernelmode; | ||
| 85 | #endif | ||
| 86 | |||
| 87 | static unsigned int interval = 10; | ||
| 88 | static unsigned int fanon = 63; | ||
| 89 | static unsigned int fanoff = 58; | ||
| 90 | static unsigned int verbose; | ||
| 91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; | ||
| 92 | static char force_bios[16]; | ||
| 93 | static unsigned int prev_interval; | ||
| 94 | struct thermal_zone_device *thz_dev; | ||
| 95 | struct thermal_cooling_device *cl_dev; | ||
| 96 | struct platform_device *acerhdf_dev; | ||
| 97 | |||
| 98 | module_param(kernelmode, uint, 0); | ||
| 99 | MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); | ||
| 100 | module_param(interval, uint, 0600); | ||
| 101 | MODULE_PARM_DESC(interval, "Polling interval of temperature check"); | ||
| 102 | module_param(fanon, uint, 0600); | ||
| 103 | MODULE_PARM_DESC(fanon, "Turn the fan on above this temperature"); | ||
| 104 | module_param(fanoff, uint, 0600); | ||
| 105 | MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature"); | ||
| 106 | module_param(verbose, uint, 0600); | ||
| 107 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); | ||
| 108 | module_param_string(force_bios, force_bios, 16, 0); | ||
| 109 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); | ||
| 110 | |||
| 111 | /* BIOS settings */ | ||
| 112 | struct bios_settings_t { | ||
| 113 | const char *vendor; | ||
| 114 | const char *version; | ||
| 115 | unsigned char fanreg; | ||
| 116 | unsigned char tempreg; | ||
| 117 | unsigned char fancmd[2]; /* fan off and auto commands */ | ||
| 118 | }; | ||
| 119 | |||
| 120 | /* Register addresses and values for different BIOS versions */ | ||
| 121 | static const struct bios_settings_t bios_tbl[] = { | ||
| 122 | {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, | ||
| 123 | {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, | ||
| 124 | {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, | ||
| 125 | {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, | ||
| 126 | {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, | ||
| 127 | {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, | ||
| 128 | {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, | ||
| 129 | {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, | ||
| 130 | {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | ||
| 131 | {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | ||
| 132 | {"", "", 0, 0, {0, 0} } | ||
| 133 | }; | ||
| 134 | |||
| 135 | static const struct bios_settings_t *bios_cfg __read_mostly; | ||
| 136 | |||
| 137 | |||
| 138 | static int acerhdf_get_temp(int *temp) | ||
| 139 | { | ||
| 140 | u8 read_temp; | ||
| 141 | |||
| 142 | if (ec_read(bios_cfg->tempreg, &read_temp)) | ||
| 143 | return -EINVAL; | ||
| 144 | |||
| 145 | *temp = read_temp; | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static int acerhdf_get_fanstate(int *state) | ||
| 151 | { | ||
| 152 | u8 fan; | ||
| 153 | bool tmp; | ||
| 154 | |||
| 155 | if (ec_read(bios_cfg->fanreg, &fan)) | ||
| 156 | return -EINVAL; | ||
| 157 | |||
| 158 | tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]); | ||
| 159 | *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO; | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void acerhdf_change_fanstate(int state) | ||
| 165 | { | ||
| 166 | unsigned char cmd; | ||
| 167 | |||
| 168 | if (verbose) | ||
| 169 | pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ? | ||
| 170 | "OFF" : "ON"); | ||
| 171 | |||
| 172 | if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) { | ||
| 173 | pr_err("invalid fan state %d requested, setting to auto!\n", | ||
| 174 | state); | ||
| 175 | state = ACERHDF_FAN_AUTO; | ||
| 176 | } | ||
| 177 | |||
| 178 | cmd = bios_cfg->fancmd[state]; | ||
| 179 | fanstate = state; | ||
| 180 | |||
| 181 | ec_write(bios_cfg->fanreg, cmd); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void acerhdf_check_param(struct thermal_zone_device *thermal) | ||
| 185 | { | ||
| 186 | if (fanon > ACERHDF_MAX_FANON) { | ||
| 187 | pr_err("fanon temperature too high, set to %d\n", | ||
| 188 | ACERHDF_MAX_FANON); | ||
| 189 | fanon = ACERHDF_MAX_FANON; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (kernelmode && prev_interval != interval) { | ||
| 193 | if (interval > ACERHDF_MAX_INTERVAL) { | ||
| 194 | pr_err("interval too high, set to %d\n", | ||
| 195 | ACERHDF_MAX_INTERVAL); | ||
| 196 | interval = ACERHDF_MAX_INTERVAL; | ||
| 197 | } | ||
| 198 | if (verbose) | ||
| 199 | pr_notice("interval changed to: %d\n", | ||
| 200 | interval); | ||
| 201 | thermal->polling_delay = interval*1000; | ||
| 202 | prev_interval = interval; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | /* | ||
| 207 | * This is the thermal zone callback which does the delayed polling of the fan | ||
| 208 | * state. We do check /sysfs-originating settings here in acerhdf_check_param() | ||
| 209 | * as late as the polling interval is since we can't do that in the respective | ||
| 210 | * accessors of the module parameters. | ||
| 211 | */ | ||
| 212 | static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, | ||
| 213 | unsigned long *t) | ||
| 214 | { | ||
| 215 | int temp, err = 0; | ||
| 216 | |||
| 217 | acerhdf_check_param(thermal); | ||
| 218 | |||
| 219 | err = acerhdf_get_temp(&temp); | ||
| 220 | if (err) | ||
| 221 | return err; | ||
| 222 | |||
| 223 | if (verbose) | ||
| 224 | pr_notice("temp %d\n", temp); | ||
| 225 | |||
| 226 | *t = temp; | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int acerhdf_bind(struct thermal_zone_device *thermal, | ||
| 231 | struct thermal_cooling_device *cdev) | ||
| 232 | { | ||
| 233 | /* if the cooling device is the one from acerhdf bind it */ | ||
| 234 | if (cdev != cl_dev) | ||
| 235 | return 0; | ||
| 236 | |||
| 237 | if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) { | ||
| 238 | pr_err("error binding cooling dev\n"); | ||
| 239 | return -EINVAL; | ||
| 240 | } | ||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | static int acerhdf_unbind(struct thermal_zone_device *thermal, | ||
| 245 | struct thermal_cooling_device *cdev) | ||
| 246 | { | ||
| 247 | if (cdev != cl_dev) | ||
| 248 | return 0; | ||
| 249 | |||
| 250 | if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) { | ||
| 251 | pr_err("error unbinding cooling dev\n"); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | static inline void acerhdf_revert_to_bios_mode(void) | ||
| 258 | { | ||
| 259 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
| 260 | kernelmode = 0; | ||
| 261 | if (thz_dev) | ||
| 262 | thz_dev->polling_delay = 0; | ||
| 263 | pr_notice("kernel mode fan control OFF\n"); | ||
| 264 | } | ||
| 265 | static inline void acerhdf_enable_kernelmode(void) | ||
| 266 | { | ||
| 267 | kernelmode = 1; | ||
| 268 | |||
| 269 | thz_dev->polling_delay = interval*1000; | ||
| 270 | thermal_zone_device_update(thz_dev); | ||
| 271 | pr_notice("kernel mode fan control ON\n"); | ||
| 272 | } | ||
| 273 | |||
| 274 | static int acerhdf_get_mode(struct thermal_zone_device *thermal, | ||
| 275 | enum thermal_device_mode *mode) | ||
| 276 | { | ||
| 277 | if (verbose) | ||
| 278 | pr_notice("kernel mode fan control %d\n", kernelmode); | ||
| 279 | |||
| 280 | *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED | ||
| 281 | : THERMAL_DEVICE_DISABLED; | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* | ||
| 287 | * set operation mode; | ||
| 288 | * enabled: the thermal layer of the kernel takes care about | ||
| 289 | * the temperature and the fan. | ||
| 290 | * disabled: the BIOS takes control of the fan. | ||
| 291 | */ | ||
| 292 | static int acerhdf_set_mode(struct thermal_zone_device *thermal, | ||
| 293 | enum thermal_device_mode mode) | ||
| 294 | { | ||
| 295 | if (mode == THERMAL_DEVICE_DISABLED && kernelmode) | ||
| 296 | acerhdf_revert_to_bios_mode(); | ||
| 297 | else if (mode == THERMAL_DEVICE_ENABLED && !kernelmode) | ||
| 298 | acerhdf_enable_kernelmode(); | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip, | ||
| 304 | enum thermal_trip_type *type) | ||
| 305 | { | ||
| 306 | if (trip == 0) | ||
| 307 | *type = THERMAL_TRIP_ACTIVE; | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, | ||
| 313 | unsigned long *temp) | ||
| 314 | { | ||
| 315 | if (trip == 0) | ||
| 316 | *temp = fanon; | ||
| 317 | |||
| 318 | return 0; | ||
| 319 | } | ||
| 320 | |||
| 321 | static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, | ||
| 322 | unsigned long *temperature) | ||
| 323 | { | ||
| 324 | *temperature = ACERHDF_TEMP_CRIT; | ||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* bind callback functions to thermalzone */ | ||
| 329 | struct thermal_zone_device_ops acerhdf_dev_ops = { | ||
| 330 | .bind = acerhdf_bind, | ||
| 331 | .unbind = acerhdf_unbind, | ||
| 332 | .get_temp = acerhdf_get_ec_temp, | ||
| 333 | .get_mode = acerhdf_get_mode, | ||
| 334 | .set_mode = acerhdf_set_mode, | ||
| 335 | .get_trip_type = acerhdf_get_trip_type, | ||
| 336 | .get_trip_temp = acerhdf_get_trip_temp, | ||
| 337 | .get_crit_temp = acerhdf_get_crit_temp, | ||
| 338 | }; | ||
| 339 | |||
| 340 | |||
| 341 | /* | ||
| 342 | * cooling device callback functions | ||
| 343 | * get maximal fan cooling state | ||
| 344 | */ | ||
| 345 | static int acerhdf_get_max_state(struct thermal_cooling_device *cdev, | ||
| 346 | unsigned long *state) | ||
| 347 | { | ||
| 348 | *state = 1; | ||
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int acerhdf_get_cur_state(struct thermal_cooling_device *cdev, | ||
| 354 | unsigned long *state) | ||
| 355 | { | ||
| 356 | int err = 0, tmp; | ||
| 357 | |||
| 358 | err = acerhdf_get_fanstate(&tmp); | ||
| 359 | if (err) | ||
| 360 | return err; | ||
| 361 | |||
| 362 | *state = (tmp == ACERHDF_FAN_AUTO) ? 1 : 0; | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* change current fan state - is overwritten when running in kernel mode */ | ||
| 367 | static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev, | ||
| 368 | unsigned long state) | ||
| 369 | { | ||
| 370 | int cur_temp, cur_state, err = 0; | ||
| 371 | |||
| 372 | if (!kernelmode) | ||
| 373 | return 0; | ||
| 374 | |||
| 375 | err = acerhdf_get_temp(&cur_temp); | ||
| 376 | if (err) { | ||
| 377 | pr_err("error reading temperature, hand off control to BIOS\n"); | ||
| 378 | goto err_out; | ||
| 379 | } | ||
| 380 | |||
| 381 | err = acerhdf_get_fanstate(&cur_state); | ||
| 382 | if (err) { | ||
| 383 | pr_err("error reading fan state, hand off control to BIOS\n"); | ||
| 384 | goto err_out; | ||
| 385 | } | ||
| 386 | |||
| 387 | if (state == 0) { | ||
| 388 | /* turn fan off only if below fanoff temperature */ | ||
| 389 | if ((cur_state == ACERHDF_FAN_AUTO) && | ||
| 390 | (cur_temp < fanoff)) | ||
| 391 | acerhdf_change_fanstate(ACERHDF_FAN_OFF); | ||
| 392 | } else { | ||
| 393 | if (cur_state == ACERHDF_FAN_OFF) | ||
| 394 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
| 395 | } | ||
| 396 | return 0; | ||
| 397 | |||
| 398 | err_out: | ||
| 399 | acerhdf_revert_to_bios_mode(); | ||
| 400 | return -EINVAL; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* bind fan callbacks to fan device */ | ||
| 404 | struct thermal_cooling_device_ops acerhdf_cooling_ops = { | ||
| 405 | .get_max_state = acerhdf_get_max_state, | ||
| 406 | .get_cur_state = acerhdf_get_cur_state, | ||
| 407 | .set_cur_state = acerhdf_set_cur_state, | ||
| 408 | }; | ||
| 409 | |||
| 410 | /* suspend / resume functionality */ | ||
| 411 | static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | ||
| 412 | { | ||
| 413 | if (kernelmode) | ||
| 414 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
| 415 | |||
| 416 | if (verbose) | ||
| 417 | pr_notice("going suspend\n"); | ||
| 418 | |||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int acerhdf_resume(struct platform_device *device) | ||
| 423 | { | ||
| 424 | if (verbose) | ||
| 425 | pr_notice("resuming\n"); | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int __devinit acerhdf_probe(struct platform_device *device) | ||
| 431 | { | ||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | static int acerhdf_remove(struct platform_device *device) | ||
| 436 | { | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 440 | struct platform_driver acerhdf_drv = { | ||
| 441 | .driver = { | ||
| 442 | .name = "acerhdf", | ||
| 443 | .owner = THIS_MODULE, | ||
| 444 | }, | ||
| 445 | .probe = acerhdf_probe, | ||
| 446 | .remove = acerhdf_remove, | ||
| 447 | .suspend = acerhdf_suspend, | ||
| 448 | .resume = acerhdf_resume, | ||
| 449 | }; | ||
| 450 | |||
| 451 | |||
| 452 | /* check hardware */ | ||
| 453 | static int acerhdf_check_hardware(void) | ||
| 454 | { | ||
| 455 | char const *vendor, *version, *product; | ||
| 456 | int i; | ||
| 457 | |||
| 458 | /* get BIOS data */ | ||
| 459 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | ||
| 460 | version = dmi_get_system_info(DMI_BIOS_VERSION); | ||
| 461 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
| 462 | |||
| 463 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); | ||
| 464 | |||
| 465 | if (!force_bios[0]) { | ||
| 466 | if (strncmp(product, "AO", 2)) { | ||
| 467 | pr_err("no Aspire One hardware found\n"); | ||
| 468 | return -EINVAL; | ||
| 469 | } | ||
| 470 | } else { | ||
| 471 | pr_info("forcing BIOS version: %s\n", version); | ||
| 472 | version = force_bios; | ||
| 473 | kernelmode = 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | if (verbose) | ||
| 477 | pr_info("BIOS info: %s %s, product: %s\n", | ||
| 478 | vendor, version, product); | ||
| 479 | |||
| 480 | /* search BIOS version and vendor in BIOS settings table */ | ||
| 481 | for (i = 0; bios_tbl[i].version[0]; i++) { | ||
| 482 | if (!strcmp(bios_tbl[i].vendor, vendor) && | ||
| 483 | !strcmp(bios_tbl[i].version, version)) { | ||
| 484 | bios_cfg = &bios_tbl[i]; | ||
| 485 | break; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | if (!bios_cfg) { | ||
| 490 | pr_err("unknown (unsupported) BIOS version %s/%s, " | ||
| 491 | "please report, aborting!\n", vendor, version); | ||
| 492 | return -EINVAL; | ||
| 493 | } | ||
| 494 | |||
| 495 | /* | ||
| 496 | * if started with kernel mode off, prevent the kernel from switching | ||
| 497 | * off the fan | ||
| 498 | */ | ||
| 499 | if (!kernelmode) { | ||
| 500 | pr_notice("Fan control off, to enable do:\n"); | ||
| 501 | pr_notice("echo -n \"enabled\" > " | ||
| 502 | "/sys/class/thermal/thermal_zone0/mode\n"); | ||
| 503 | } | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static int acerhdf_register_platform(void) | ||
| 509 | { | ||
| 510 | int err = 0; | ||
| 511 | |||
| 512 | err = platform_driver_register(&acerhdf_drv); | ||
| 513 | if (err) | ||
| 514 | return err; | ||
| 515 | |||
| 516 | acerhdf_dev = platform_device_alloc("acerhdf", -1); | ||
| 517 | platform_device_add(acerhdf_dev); | ||
| 518 | |||
| 519 | return 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | static void acerhdf_unregister_platform(void) | ||
| 523 | { | ||
| 524 | if (!acerhdf_dev) | ||
| 525 | return; | ||
| 526 | |||
| 527 | platform_device_del(acerhdf_dev); | ||
| 528 | platform_driver_unregister(&acerhdf_drv); | ||
| 529 | } | ||
| 530 | |||
| 531 | static int acerhdf_register_thermal(void) | ||
| 532 | { | ||
| 533 | cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, | ||
| 534 | &acerhdf_cooling_ops); | ||
| 535 | |||
| 536 | if (IS_ERR(cl_dev)) | ||
| 537 | return -EINVAL; | ||
| 538 | |||
| 539 | thz_dev = thermal_zone_device_register("acerhdf", 1, NULL, | ||
| 540 | &acerhdf_dev_ops, 0, 0, 0, | ||
| 541 | (kernelmode) ? interval*1000 : 0); | ||
| 542 | if (IS_ERR(thz_dev)) | ||
| 543 | return -EINVAL; | ||
| 544 | |||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | |||
| 548 | static void acerhdf_unregister_thermal(void) | ||
| 549 | { | ||
| 550 | if (cl_dev) { | ||
| 551 | thermal_cooling_device_unregister(cl_dev); | ||
| 552 | cl_dev = NULL; | ||
| 553 | } | ||
| 554 | |||
| 555 | if (thz_dev) { | ||
| 556 | thermal_zone_device_unregister(thz_dev); | ||
| 557 | thz_dev = NULL; | ||
| 558 | } | ||
| 559 | } | ||
| 560 | |||
| 561 | static int __init acerhdf_init(void) | ||
| 562 | { | ||
| 563 | int err = 0; | ||
| 564 | |||
| 565 | err = acerhdf_check_hardware(); | ||
| 566 | if (err) | ||
| 567 | goto out_err; | ||
| 568 | |||
| 569 | err = acerhdf_register_platform(); | ||
| 570 | if (err) | ||
| 571 | goto err_unreg; | ||
| 572 | |||
| 573 | err = acerhdf_register_thermal(); | ||
| 574 | if (err) | ||
| 575 | goto err_unreg; | ||
| 576 | |||
| 577 | return 0; | ||
| 578 | |||
| 579 | err_unreg: | ||
| 580 | acerhdf_unregister_thermal(); | ||
| 581 | acerhdf_unregister_platform(); | ||
| 582 | |||
| 583 | out_err: | ||
| 584 | return -ENODEV; | ||
| 585 | } | ||
| 586 | |||
| 587 | static void __exit acerhdf_exit(void) | ||
| 588 | { | ||
| 589 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | ||
| 590 | acerhdf_unregister_thermal(); | ||
| 591 | acerhdf_unregister_platform(); | ||
| 592 | } | ||
| 593 | |||
| 594 | MODULE_LICENSE("GPL"); | ||
| 595 | MODULE_AUTHOR("Peter Feuerer"); | ||
| 596 | MODULE_DESCRIPTION("Aspire One temperature and fan driver"); | ||
| 597 | MODULE_ALIAS("dmi:*:*Acer*:*:"); | ||
| 598 | MODULE_ALIAS("dmi:*:*Gateway*:*:"); | ||
| 599 | MODULE_ALIAS("dmi:*:*Packard Bell*:*:"); | ||
| 600 | |||
| 601 | module_init(acerhdf_init); | ||
| 602 | module_exit(acerhdf_exit); | ||
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index bfc1a8892a32..db657bbeec90 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | * Sam Lin - GPS support | 33 | * Sam Lin - GPS support |
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 37 | |||
| 36 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
| 37 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 38 | #include <linux/init.h> | 40 | #include <linux/init.h> |
| @@ -53,9 +55,10 @@ | |||
| 53 | #define ASUS_HOTK_NAME "Asus Laptop Support" | 55 | #define ASUS_HOTK_NAME "Asus Laptop Support" |
| 54 | #define ASUS_HOTK_CLASS "hotkey" | 56 | #define ASUS_HOTK_CLASS "hotkey" |
| 55 | #define ASUS_HOTK_DEVICE_NAME "Hotkey" | 57 | #define ASUS_HOTK_DEVICE_NAME "Hotkey" |
| 56 | #define ASUS_HOTK_FILE "asus-laptop" | 58 | #define ASUS_HOTK_FILE KBUILD_MODNAME |
| 57 | #define ASUS_HOTK_PREFIX "\\_SB.ATKD." | 59 | #define ASUS_HOTK_PREFIX "\\_SB.ATKD." |
| 58 | 60 | ||
| 61 | |||
| 59 | /* | 62 | /* |
| 60 | * Some events we use, same for all Asus | 63 | * Some events we use, same for all Asus |
| 61 | */ | 64 | */ |
| @@ -207,13 +210,17 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids); | |||
| 207 | 210 | ||
| 208 | static int asus_hotk_add(struct acpi_device *device); | 211 | static int asus_hotk_add(struct acpi_device *device); |
| 209 | static int asus_hotk_remove(struct acpi_device *device, int type); | 212 | static int asus_hotk_remove(struct acpi_device *device, int type); |
| 213 | static void asus_hotk_notify(struct acpi_device *device, u32 event); | ||
| 214 | |||
| 210 | static struct acpi_driver asus_hotk_driver = { | 215 | static struct acpi_driver asus_hotk_driver = { |
| 211 | .name = ASUS_HOTK_NAME, | 216 | .name = ASUS_HOTK_NAME, |
| 212 | .class = ASUS_HOTK_CLASS, | 217 | .class = ASUS_HOTK_CLASS, |
| 213 | .ids = asus_device_ids, | 218 | .ids = asus_device_ids, |
| 219 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 214 | .ops = { | 220 | .ops = { |
| 215 | .add = asus_hotk_add, | 221 | .add = asus_hotk_add, |
| 216 | .remove = asus_hotk_remove, | 222 | .remove = asus_hotk_remove, |
| 223 | .notify = asus_hotk_notify, | ||
| 217 | }, | 224 | }, |
| 218 | }; | 225 | }; |
| 219 | 226 | ||
| @@ -323,7 +330,7 @@ static int read_wireless_status(int mask) | |||
| 323 | 330 | ||
| 324 | rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); | 331 | rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); |
| 325 | if (ACPI_FAILURE(rv)) | 332 | if (ACPI_FAILURE(rv)) |
| 326 | printk(ASUS_WARNING "Error reading Wireless status\n"); | 333 | pr_warning("Error reading Wireless status\n"); |
| 327 | else | 334 | else |
| 328 | return (status & mask) ? 1 : 0; | 335 | return (status & mask) ? 1 : 0; |
| 329 | 336 | ||
| @@ -337,7 +344,7 @@ static int read_gps_status(void) | |||
| 337 | 344 | ||
| 338 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); | 345 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); |
| 339 | if (ACPI_FAILURE(rv)) | 346 | if (ACPI_FAILURE(rv)) |
| 340 | printk(ASUS_WARNING "Error reading GPS status\n"); | 347 | pr_warning("Error reading GPS status\n"); |
| 341 | else | 348 | else |
| 342 | return status ? 1 : 0; | 349 | return status ? 1 : 0; |
| 343 | 350 | ||
| @@ -377,7 +384,7 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
| 377 | } | 384 | } |
| 378 | 385 | ||
| 379 | if (write_acpi_int(handle, NULL, out, NULL)) | 386 | if (write_acpi_int(handle, NULL, out, NULL)) |
| 380 | printk(ASUS_WARNING " write failed %x\n", mask); | 387 | pr_warning(" write failed %x\n", mask); |
| 381 | } | 388 | } |
| 382 | 389 | ||
| 383 | /* /sys/class/led handlers */ | 390 | /* /sys/class/led handlers */ |
| @@ -420,7 +427,7 @@ static int set_lcd_state(int value) | |||
| 420 | NULL, NULL, NULL); | 427 | NULL, NULL, NULL); |
| 421 | 428 | ||
| 422 | if (ACPI_FAILURE(status)) | 429 | if (ACPI_FAILURE(status)) |
| 423 | printk(ASUS_WARNING "Error switching LCD\n"); | 430 | pr_warning("Error switching LCD\n"); |
| 424 | } | 431 | } |
| 425 | 432 | ||
| 426 | write_status(NULL, lcd, LCD_ON); | 433 | write_status(NULL, lcd, LCD_ON); |
| @@ -444,7 +451,7 @@ static int read_brightness(struct backlight_device *bd) | |||
| 444 | 451 | ||
| 445 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); | 452 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); |
| 446 | if (ACPI_FAILURE(rv)) | 453 | if (ACPI_FAILURE(rv)) |
| 447 | printk(ASUS_WARNING "Error reading brightness\n"); | 454 | pr_warning("Error reading brightness\n"); |
| 448 | 455 | ||
| 449 | return value; | 456 | return value; |
| 450 | } | 457 | } |
| @@ -457,7 +464,7 @@ static int set_brightness(struct backlight_device *bd, int value) | |||
| 457 | /* 0 <= value <= 15 */ | 464 | /* 0 <= value <= 15 */ |
| 458 | 465 | ||
| 459 | if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { | 466 | if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { |
| 460 | printk(ASUS_WARNING "Error changing brightness\n"); | 467 | pr_warning("Error changing brightness\n"); |
| 461 | ret = -EIO; | 468 | ret = -EIO; |
| 462 | } | 469 | } |
| 463 | 470 | ||
| @@ -587,7 +594,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, | |||
| 587 | rv = parse_arg(buf, count, &value); | 594 | rv = parse_arg(buf, count, &value); |
| 588 | if (rv > 0) { | 595 | if (rv > 0) { |
| 589 | if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) | 596 | if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) |
| 590 | printk(ASUS_WARNING "LED display write failed\n"); | 597 | pr_warning("LED display write failed\n"); |
| 591 | else | 598 | else |
| 592 | hotk->ledd_status = (u32) value; | 599 | hotk->ledd_status = (u32) value; |
| 593 | } | 600 | } |
| @@ -632,7 +639,7 @@ static void set_display(int value) | |||
| 632 | { | 639 | { |
| 633 | /* no sanity check needed for now */ | 640 | /* no sanity check needed for now */ |
| 634 | if (write_acpi_int(display_set_handle, NULL, value, NULL)) | 641 | if (write_acpi_int(display_set_handle, NULL, value, NULL)) |
| 635 | printk(ASUS_WARNING "Error setting display\n"); | 642 | pr_warning("Error setting display\n"); |
| 636 | return; | 643 | return; |
| 637 | } | 644 | } |
| 638 | 645 | ||
| @@ -647,7 +654,7 @@ static int read_display(void) | |||
| 647 | rv = acpi_evaluate_integer(display_get_handle, NULL, | 654 | rv = acpi_evaluate_integer(display_get_handle, NULL, |
| 648 | NULL, &value); | 655 | NULL, &value); |
| 649 | if (ACPI_FAILURE(rv)) | 656 | if (ACPI_FAILURE(rv)) |
| 650 | printk(ASUS_WARNING "Error reading display status\n"); | 657 | pr_warning("Error reading display status\n"); |
| 651 | } | 658 | } |
| 652 | 659 | ||
| 653 | value &= 0x0F; /* needed for some models, shouldn't hurt others */ | 660 | value &= 0x0F; /* needed for some models, shouldn't hurt others */ |
| @@ -689,7 +696,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, | |||
| 689 | static void set_light_sens_switch(int value) | 696 | static void set_light_sens_switch(int value) |
| 690 | { | 697 | { |
| 691 | if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) | 698 | if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) |
| 692 | printk(ASUS_WARNING "Error setting light sensor switch\n"); | 699 | pr_warning("Error setting light sensor switch\n"); |
| 693 | hotk->light_switch = value; | 700 | hotk->light_switch = value; |
| 694 | } | 701 | } |
| 695 | 702 | ||
| @@ -714,7 +721,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, | |||
| 714 | static void set_light_sens_level(int value) | 721 | static void set_light_sens_level(int value) |
| 715 | { | 722 | { |
| 716 | if (write_acpi_int(ls_level_handle, NULL, value, NULL)) | 723 | if (write_acpi_int(ls_level_handle, NULL, value, NULL)) |
| 717 | printk(ASUS_WARNING "Error setting light sensor level\n"); | 724 | pr_warning("Error setting light sensor level\n"); |
| 718 | hotk->light_level = value; | 725 | hotk->light_level = value; |
| 719 | } | 726 | } |
| 720 | 727 | ||
| @@ -812,7 +819,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
| 812 | return -EINVAL; | 819 | return -EINVAL; |
| 813 | } | 820 | } |
| 814 | 821 | ||
| 815 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 822 | static void asus_hotk_notify(struct acpi_device *device, u32 event) |
| 816 | { | 823 | { |
| 817 | static struct key_entry *key; | 824 | static struct key_entry *key; |
| 818 | u16 count; | 825 | u16 count; |
| @@ -975,11 +982,11 @@ static int asus_hotk_get_info(void) | |||
| 975 | */ | 982 | */ |
| 976 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); | 983 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); |
| 977 | if (ACPI_FAILURE(status)) | 984 | if (ACPI_FAILURE(status)) |
| 978 | printk(ASUS_WARNING "Couldn't get the DSDT table header\n"); | 985 | pr_warning("Couldn't get the DSDT table header\n"); |
| 979 | 986 | ||
| 980 | /* We have to write 0 on init this far for all ASUS models */ | 987 | /* We have to write 0 on init this far for all ASUS models */ |
| 981 | if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { | 988 | if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { |
| 982 | printk(ASUS_ERR "Hotkey initialization failed\n"); | 989 | pr_err("Hotkey initialization failed\n"); |
| 983 | return -ENODEV; | 990 | return -ENODEV; |
| 984 | } | 991 | } |
| 985 | 992 | ||
| @@ -987,9 +994,9 @@ static int asus_hotk_get_info(void) | |||
| 987 | status = | 994 | status = |
| 988 | acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); | 995 | acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); |
| 989 | if (ACPI_FAILURE(status)) | 996 | if (ACPI_FAILURE(status)) |
| 990 | printk(ASUS_WARNING "Error calling BSTS\n"); | 997 | pr_warning("Error calling BSTS\n"); |
| 991 | else if (bsts_result) | 998 | else if (bsts_result) |
| 992 | printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n", | 999 | pr_notice("BSTS called, 0x%02x returned\n", |
| 993 | (uint) bsts_result); | 1000 | (uint) bsts_result); |
| 994 | 1001 | ||
| 995 | /* This too ... */ | 1002 | /* This too ... */ |
| @@ -1020,7 +1027,7 @@ static int asus_hotk_get_info(void) | |||
| 1020 | return -ENOMEM; | 1027 | return -ENOMEM; |
| 1021 | 1028 | ||
| 1022 | if (*string) | 1029 | if (*string) |
| 1023 | printk(ASUS_NOTICE " %s model detected\n", string); | 1030 | pr_notice(" %s model detected\n", string); |
| 1024 | 1031 | ||
| 1025 | ASUS_HANDLE_INIT(mled_set); | 1032 | ASUS_HANDLE_INIT(mled_set); |
| 1026 | ASUS_HANDLE_INIT(tled_set); | 1033 | ASUS_HANDLE_INIT(tled_set); |
| @@ -1077,7 +1084,7 @@ static int asus_input_init(void) | |||
| 1077 | 1084 | ||
| 1078 | hotk->inputdev = input_allocate_device(); | 1085 | hotk->inputdev = input_allocate_device(); |
| 1079 | if (!hotk->inputdev) { | 1086 | if (!hotk->inputdev) { |
| 1080 | printk(ASUS_INFO "Unable to allocate input device\n"); | 1087 | pr_info("Unable to allocate input device\n"); |
| 1081 | return 0; | 1088 | return 0; |
| 1082 | } | 1089 | } |
| 1083 | hotk->inputdev->name = "Asus Laptop extra buttons"; | 1090 | hotk->inputdev->name = "Asus Laptop extra buttons"; |
| @@ -1096,7 +1103,7 @@ static int asus_input_init(void) | |||
| 1096 | } | 1103 | } |
| 1097 | result = input_register_device(hotk->inputdev); | 1104 | result = input_register_device(hotk->inputdev); |
| 1098 | if (result) { | 1105 | if (result) { |
| 1099 | printk(ASUS_INFO "Unable to register input device\n"); | 1106 | pr_info("Unable to register input device\n"); |
| 1100 | input_free_device(hotk->inputdev); | 1107 | input_free_device(hotk->inputdev); |
| 1101 | } | 1108 | } |
| 1102 | return result; | 1109 | return result; |
| @@ -1113,7 +1120,7 @@ static int asus_hotk_check(void) | |||
| 1113 | if (hotk->device->status.present) { | 1120 | if (hotk->device->status.present) { |
| 1114 | result = asus_hotk_get_info(); | 1121 | result = asus_hotk_get_info(); |
| 1115 | } else { | 1122 | } else { |
| 1116 | printk(ASUS_ERR "Hotkey device not present, aborting\n"); | 1123 | pr_err("Hotkey device not present, aborting\n"); |
| 1117 | return -EINVAL; | 1124 | return -EINVAL; |
| 1118 | } | 1125 | } |
| 1119 | 1126 | ||
| @@ -1124,13 +1131,12 @@ static int asus_hotk_found; | |||
| 1124 | 1131 | ||
| 1125 | static int asus_hotk_add(struct acpi_device *device) | 1132 | static int asus_hotk_add(struct acpi_device *device) |
| 1126 | { | 1133 | { |
| 1127 | acpi_status status = AE_OK; | ||
| 1128 | int result; | 1134 | int result; |
| 1129 | 1135 | ||
| 1130 | if (!device) | 1136 | if (!device) |
| 1131 | return -EINVAL; | 1137 | return -EINVAL; |
| 1132 | 1138 | ||
| 1133 | printk(ASUS_NOTICE "Asus Laptop Support version %s\n", | 1139 | pr_notice("Asus Laptop Support version %s\n", |
| 1134 | ASUS_LAPTOP_VERSION); | 1140 | ASUS_LAPTOP_VERSION); |
| 1135 | 1141 | ||
| 1136 | hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); | 1142 | hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); |
| @@ -1149,15 +1155,6 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 1149 | 1155 | ||
| 1150 | asus_hotk_add_fs(); | 1156 | asus_hotk_add_fs(); |
| 1151 | 1157 | ||
| 1152 | /* | ||
| 1153 | * We install the handler, it will receive the hotk in parameter, so, we | ||
| 1154 | * could add other data to the hotk struct | ||
| 1155 | */ | ||
| 1156 | status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, | ||
| 1157 | asus_hotk_notify, hotk); | ||
| 1158 | if (ACPI_FAILURE(status)) | ||
| 1159 | printk(ASUS_ERR "Error installing notify handler\n"); | ||
| 1160 | |||
| 1161 | asus_hotk_found = 1; | 1158 | asus_hotk_found = 1; |
| 1162 | 1159 | ||
| 1163 | /* WLED and BLED are on by default */ | 1160 | /* WLED and BLED are on by default */ |
| @@ -1198,16 +1195,9 @@ end: | |||
| 1198 | 1195 | ||
| 1199 | static int asus_hotk_remove(struct acpi_device *device, int type) | 1196 | static int asus_hotk_remove(struct acpi_device *device, int type) |
| 1200 | { | 1197 | { |
| 1201 | acpi_status status = 0; | ||
| 1202 | |||
| 1203 | if (!device || !acpi_driver_data(device)) | 1198 | if (!device || !acpi_driver_data(device)) |
| 1204 | return -EINVAL; | 1199 | return -EINVAL; |
| 1205 | 1200 | ||
| 1206 | status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, | ||
| 1207 | asus_hotk_notify); | ||
| 1208 | if (ACPI_FAILURE(status)) | ||
| 1209 | printk(ASUS_ERR "Error removing notify handler\n"); | ||
| 1210 | |||
| 1211 | kfree(hotk->name); | 1201 | kfree(hotk->name); |
| 1212 | kfree(hotk); | 1202 | kfree(hotk); |
| 1213 | 1203 | ||
| @@ -1260,8 +1250,7 @@ static int asus_backlight_init(struct device *dev) | |||
| 1260 | bd = backlight_device_register(ASUS_HOTK_FILE, dev, | 1250 | bd = backlight_device_register(ASUS_HOTK_FILE, dev, |
| 1261 | NULL, &asusbl_ops); | 1251 | NULL, &asusbl_ops); |
| 1262 | if (IS_ERR(bd)) { | 1252 | if (IS_ERR(bd)) { |
| 1263 | printk(ASUS_ERR | 1253 | pr_err("Could not register asus backlight device\n"); |
| 1264 | "Could not register asus backlight device\n"); | ||
| 1265 | asus_backlight_device = NULL; | 1254 | asus_backlight_device = NULL; |
| 1266 | return PTR_ERR(bd); | 1255 | return PTR_ERR(bd); |
| 1267 | } | 1256 | } |
| @@ -1334,7 +1323,6 @@ out: | |||
| 1334 | 1323 | ||
| 1335 | static int __init asus_laptop_init(void) | 1324 | static int __init asus_laptop_init(void) |
| 1336 | { | 1325 | { |
| 1337 | struct device *dev; | ||
| 1338 | int result; | 1326 | int result; |
| 1339 | 1327 | ||
| 1340 | if (acpi_disabled) | 1328 | if (acpi_disabled) |
| @@ -1356,24 +1344,10 @@ static int __init asus_laptop_init(void) | |||
| 1356 | return -ENODEV; | 1344 | return -ENODEV; |
| 1357 | } | 1345 | } |
| 1358 | 1346 | ||
| 1359 | dev = acpi_get_physical_device(hotk->device->handle); | ||
| 1360 | |||
| 1361 | if (!acpi_video_backlight_support()) { | ||
| 1362 | result = asus_backlight_init(dev); | ||
| 1363 | if (result) | ||
| 1364 | goto fail_backlight; | ||
| 1365 | } else | ||
| 1366 | printk(ASUS_INFO "Brightness ignored, must be controlled by " | ||
| 1367 | "ACPI video driver\n"); | ||
| 1368 | |||
| 1369 | result = asus_input_init(); | 1347 | result = asus_input_init(); |
| 1370 | if (result) | 1348 | if (result) |
| 1371 | goto fail_input; | 1349 | goto fail_input; |
| 1372 | 1350 | ||
| 1373 | result = asus_led_init(dev); | ||
| 1374 | if (result) | ||
| 1375 | goto fail_led; | ||
| 1376 | |||
| 1377 | /* Register platform stuff */ | 1351 | /* Register platform stuff */ |
| 1378 | result = platform_driver_register(&asuspf_driver); | 1352 | result = platform_driver_register(&asuspf_driver); |
| 1379 | if (result) | 1353 | if (result) |
| @@ -1394,8 +1368,27 @@ static int __init asus_laptop_init(void) | |||
| 1394 | if (result) | 1368 | if (result) |
| 1395 | goto fail_sysfs; | 1369 | goto fail_sysfs; |
| 1396 | 1370 | ||
| 1371 | result = asus_led_init(&asuspf_device->dev); | ||
| 1372 | if (result) | ||
| 1373 | goto fail_led; | ||
| 1374 | |||
| 1375 | if (!acpi_video_backlight_support()) { | ||
| 1376 | result = asus_backlight_init(&asuspf_device->dev); | ||
| 1377 | if (result) | ||
| 1378 | goto fail_backlight; | ||
| 1379 | } else | ||
| 1380 | pr_info("Brightness ignored, must be controlled by " | ||
| 1381 | "ACPI video driver\n"); | ||
| 1382 | |||
| 1397 | return 0; | 1383 | return 0; |
| 1398 | 1384 | ||
| 1385 | fail_backlight: | ||
| 1386 | asus_led_exit(); | ||
| 1387 | |||
| 1388 | fail_led: | ||
| 1389 | sysfs_remove_group(&asuspf_device->dev.kobj, | ||
| 1390 | &asuspf_attribute_group); | ||
| 1391 | |||
| 1399 | fail_sysfs: | 1392 | fail_sysfs: |
| 1400 | platform_device_del(asuspf_device); | 1393 | platform_device_del(asuspf_device); |
| 1401 | 1394 | ||
| @@ -1406,15 +1399,9 @@ fail_platform_device1: | |||
| 1406 | platform_driver_unregister(&asuspf_driver); | 1399 | platform_driver_unregister(&asuspf_driver); |
| 1407 | 1400 | ||
| 1408 | fail_platform_driver: | 1401 | fail_platform_driver: |
| 1409 | asus_led_exit(); | ||
| 1410 | |||
| 1411 | fail_led: | ||
| 1412 | asus_input_exit(); | 1402 | asus_input_exit(); |
| 1413 | 1403 | ||
| 1414 | fail_input: | 1404 | fail_input: |
| 1415 | asus_backlight_exit(); | ||
| 1416 | |||
| 1417 | fail_backlight: | ||
| 1418 | 1405 | ||
| 1419 | return result; | 1406 | return result; |
| 1420 | } | 1407 | } |
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index ba1f7497e4b9..ddf5240ade8c 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c | |||
| @@ -455,6 +455,8 @@ static struct asus_hotk *hotk; | |||
| 455 | */ | 455 | */ |
| 456 | static int asus_hotk_add(struct acpi_device *device); | 456 | static int asus_hotk_add(struct acpi_device *device); |
| 457 | static int asus_hotk_remove(struct acpi_device *device, int type); | 457 | static int asus_hotk_remove(struct acpi_device *device, int type); |
| 458 | static void asus_hotk_notify(struct acpi_device *device, u32 event); | ||
| 459 | |||
| 458 | static const struct acpi_device_id asus_device_ids[] = { | 460 | static const struct acpi_device_id asus_device_ids[] = { |
| 459 | {"ATK0100", 0}, | 461 | {"ATK0100", 0}, |
| 460 | {"", 0}, | 462 | {"", 0}, |
| @@ -465,9 +467,11 @@ static struct acpi_driver asus_hotk_driver = { | |||
| 465 | .name = "asus_acpi", | 467 | .name = "asus_acpi", |
| 466 | .class = ACPI_HOTK_CLASS, | 468 | .class = ACPI_HOTK_CLASS, |
| 467 | .ids = asus_device_ids, | 469 | .ids = asus_device_ids, |
| 470 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 468 | .ops = { | 471 | .ops = { |
| 469 | .add = asus_hotk_add, | 472 | .add = asus_hotk_add, |
| 470 | .remove = asus_hotk_remove, | 473 | .remove = asus_hotk_remove, |
| 474 | .notify = asus_hotk_notify, | ||
| 471 | }, | 475 | }, |
| 472 | }; | 476 | }; |
| 473 | 477 | ||
| @@ -1101,12 +1105,20 @@ static int asus_hotk_remove_fs(struct acpi_device *device) | |||
| 1101 | return 0; | 1105 | return 0; |
| 1102 | } | 1106 | } |
| 1103 | 1107 | ||
| 1104 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 1108 | static void asus_hotk_notify(struct acpi_device *device, u32 event) |
| 1105 | { | 1109 | { |
| 1106 | /* TODO Find a better way to handle events count. */ | 1110 | /* TODO Find a better way to handle events count. */ |
| 1107 | if (!hotk) | 1111 | if (!hotk) |
| 1108 | return; | 1112 | return; |
| 1109 | 1113 | ||
| 1114 | /* | ||
| 1115 | * The BIOS *should* be sending us device events, but apparently | ||
| 1116 | * Asus uses system events instead, so just ignore any device | ||
| 1117 | * events we get. | ||
| 1118 | */ | ||
| 1119 | if (event > ACPI_MAX_SYS_NOTIFY) | ||
| 1120 | return; | ||
| 1121 | |||
| 1110 | if ((event & ~((u32) BR_UP)) < 16) | 1122 | if ((event & ~((u32) BR_UP)) < 16) |
| 1111 | hotk->brightness = (event & ~((u32) BR_UP)); | 1123 | hotk->brightness = (event & ~((u32) BR_UP)); |
| 1112 | else if ((event & ~((u32) BR_DOWN)) < 16) | 1124 | else if ((event & ~((u32) BR_DOWN)) < 16) |
| @@ -1346,15 +1358,6 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 1346 | if (result) | 1358 | if (result) |
| 1347 | goto end; | 1359 | goto end; |
| 1348 | 1360 | ||
| 1349 | /* | ||
| 1350 | * We install the handler, it will receive the hotk in parameter, so, we | ||
| 1351 | * could add other data to the hotk struct | ||
| 1352 | */ | ||
| 1353 | status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | ||
| 1354 | asus_hotk_notify, hotk); | ||
| 1355 | if (ACPI_FAILURE(status)) | ||
| 1356 | printk(KERN_ERR " Error installing notify handler\n"); | ||
| 1357 | |||
| 1358 | /* For laptops without GPLV: init the hotk->brightness value */ | 1361 | /* For laptops without GPLV: init the hotk->brightness value */ |
| 1359 | if ((!hotk->methods->brightness_get) | 1362 | if ((!hotk->methods->brightness_get) |
| 1360 | && (!hotk->methods->brightness_status) | 1363 | && (!hotk->methods->brightness_status) |
| @@ -1389,16 +1392,9 @@ end: | |||
| 1389 | 1392 | ||
| 1390 | static int asus_hotk_remove(struct acpi_device *device, int type) | 1393 | static int asus_hotk_remove(struct acpi_device *device, int type) |
| 1391 | { | 1394 | { |
| 1392 | acpi_status status = 0; | ||
| 1393 | |||
| 1394 | if (!device || !acpi_driver_data(device)) | 1395 | if (!device || !acpi_driver_data(device)) |
| 1395 | return -EINVAL; | 1396 | return -EINVAL; |
| 1396 | 1397 | ||
| 1397 | status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | ||
| 1398 | asus_hotk_notify); | ||
| 1399 | if (ACPI_FAILURE(status)) | ||
| 1400 | printk(KERN_ERR "Asus ACPI: Error removing notify handler\n"); | ||
| 1401 | |||
| 1402 | asus_hotk_remove_fs(device); | 1398 | asus_hotk_remove_fs(device); |
| 1403 | 1399 | ||
| 1404 | kfree(hotk); | 1400 | kfree(hotk); |
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 2fab94162147..0f900cc9fa7a 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c | |||
| @@ -46,10 +46,53 @@ struct key_entry { | |||
| 46 | u16 keycode; | 46 | u16 keycode; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | enum { KE_KEY, KE_SW, KE_END }; | 49 | enum { KE_KEY, KE_SW, KE_IGNORE, KE_END }; |
| 50 | |||
| 51 | /* | ||
| 52 | * Certain keys are flagged as KE_IGNORE. All of these are either | ||
| 53 | * notifications (rather than requests for change) or are also sent | ||
| 54 | * via the keyboard controller so should not be sent again. | ||
| 55 | */ | ||
| 50 | 56 | ||
| 51 | static struct key_entry dell_wmi_keymap[] = { | 57 | static struct key_entry dell_wmi_keymap[] = { |
| 52 | {KE_KEY, 0xe045, KEY_PROG1}, | 58 | {KE_KEY, 0xe045, KEY_PROG1}, |
| 59 | {KE_KEY, 0xe009, KEY_EJECTCD}, | ||
| 60 | |||
| 61 | /* These also contain the brightness level at offset 6 */ | ||
| 62 | {KE_KEY, 0xe006, KEY_BRIGHTNESSUP}, | ||
| 63 | {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN}, | ||
| 64 | |||
| 65 | /* Battery health status button */ | ||
| 66 | {KE_KEY, 0xe007, KEY_BATTERY}, | ||
| 67 | |||
| 68 | /* This is actually for all radios. Although physically a | ||
| 69 | * switch, the notification does not provide an indication of | ||
| 70 | * state and so it should be reported as a key */ | ||
| 71 | {KE_KEY, 0xe008, KEY_WLAN}, | ||
| 72 | |||
| 73 | /* The next device is at offset 6, the active devices are at | ||
| 74 | offset 8 and the attached devices at offset 10 */ | ||
| 75 | {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE}, | ||
| 76 | |||
| 77 | {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, | ||
| 78 | |||
| 79 | /* BIOS error detected */ | ||
| 80 | {KE_IGNORE, 0xe00d, KEY_RESERVED}, | ||
| 81 | |||
| 82 | /* Wifi Catcher */ | ||
| 83 | {KE_KEY, 0xe011, KEY_PROG2}, | ||
| 84 | |||
| 85 | /* Ambient light sensor toggle */ | ||
| 86 | {KE_IGNORE, 0xe013, KEY_RESERVED}, | ||
| 87 | |||
| 88 | {KE_IGNORE, 0xe020, KEY_MUTE}, | ||
| 89 | {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN}, | ||
| 90 | {KE_IGNORE, 0xe030, KEY_VOLUMEUP}, | ||
| 91 | {KE_IGNORE, 0xe033, KEY_KBDILLUMUP}, | ||
| 92 | {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN}, | ||
| 93 | {KE_IGNORE, 0xe03a, KEY_CAPSLOCK}, | ||
| 94 | {KE_IGNORE, 0xe045, KEY_NUMLOCK}, | ||
| 95 | {KE_IGNORE, 0xe046, KEY_SCROLLLOCK}, | ||
| 53 | {KE_END, 0} | 96 | {KE_END, 0} |
| 54 | }; | 97 | }; |
| 55 | 98 | ||
| @@ -122,15 +165,20 @@ static void dell_wmi_notify(u32 value, void *context) | |||
| 122 | 165 | ||
| 123 | if (obj && obj->type == ACPI_TYPE_BUFFER) { | 166 | if (obj && obj->type == ACPI_TYPE_BUFFER) { |
| 124 | int *buffer = (int *)obj->buffer.pointer; | 167 | int *buffer = (int *)obj->buffer.pointer; |
| 125 | key = dell_wmi_get_entry_by_scancode(buffer[1]); | 168 | /* |
| 169 | * The upper bytes of the event may contain | ||
| 170 | * additional information, so mask them off for the | ||
| 171 | * scancode lookup | ||
| 172 | */ | ||
| 173 | key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF); | ||
| 126 | if (key) { | 174 | if (key) { |
| 127 | input_report_key(dell_wmi_input_dev, key->keycode, 1); | 175 | input_report_key(dell_wmi_input_dev, key->keycode, 1); |
| 128 | input_sync(dell_wmi_input_dev); | 176 | input_sync(dell_wmi_input_dev); |
| 129 | input_report_key(dell_wmi_input_dev, key->keycode, 0); | 177 | input_report_key(dell_wmi_input_dev, key->keycode, 0); |
| 130 | input_sync(dell_wmi_input_dev); | 178 | input_sync(dell_wmi_input_dev); |
| 131 | } else | 179 | } else if (buffer[1] & 0xFFFF) |
| 132 | printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", | 180 | printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", |
| 133 | buffer[1]); | 181 | buffer[1] & 0xFFFF); |
| 134 | } | 182 | } |
| 135 | } | 183 | } |
| 136 | 184 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 8153b3e59189..ec560f16d720 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 20 | |||
| 19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| @@ -31,6 +33,7 @@ | |||
| 31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
| 32 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
| 33 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 34 | 37 | ||
| 35 | #define EEEPC_LAPTOP_VERSION "0.1" | 38 | #define EEEPC_LAPTOP_VERSION "0.1" |
| 36 | 39 | ||
| @@ -40,11 +43,6 @@ | |||
| 40 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | 43 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" |
| 41 | #define EEEPC_HOTK_HID "ASUS010" | 44 | #define EEEPC_HOTK_HID "ASUS010" |
| 42 | 45 | ||
| 43 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
| 44 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
| 45 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
| 46 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
| 47 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
| 48 | 46 | ||
| 49 | /* | 47 | /* |
| 50 | * Definitions for Asus EeePC | 48 | * Definitions for Asus EeePC |
| @@ -62,7 +60,10 @@ enum { | |||
| 62 | DISABLE_ASL_GPS = 0x0020, | 60 | DISABLE_ASL_GPS = 0x0020, |
| 63 | DISABLE_ASL_DISPLAYSWITCH = 0x0040, | 61 | DISABLE_ASL_DISPLAYSWITCH = 0x0040, |
| 64 | DISABLE_ASL_MODEM = 0x0080, | 62 | DISABLE_ASL_MODEM = 0x0080, |
| 65 | DISABLE_ASL_CARDREADER = 0x0100 | 63 | DISABLE_ASL_CARDREADER = 0x0100, |
| 64 | DISABLE_ASL_3G = 0x0200, | ||
| 65 | DISABLE_ASL_WIMAX = 0x0400, | ||
| 66 | DISABLE_ASL_HWCF = 0x0800 | ||
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | enum { | 69 | enum { |
| @@ -87,7 +88,13 @@ enum { | |||
| 87 | CM_ASL_USBPORT3, | 88 | CM_ASL_USBPORT3, |
| 88 | CM_ASL_MODEM, | 89 | CM_ASL_MODEM, |
| 89 | CM_ASL_CARDREADER, | 90 | CM_ASL_CARDREADER, |
| 90 | CM_ASL_LID | 91 | CM_ASL_3G, |
| 92 | CM_ASL_WIMAX, | ||
| 93 | CM_ASL_HWCF, | ||
| 94 | CM_ASL_LID, | ||
| 95 | CM_ASL_TYPE, | ||
| 96 | CM_ASL_PANELPOWER, /*P901*/ | ||
| 97 | CM_ASL_TPD | ||
| 91 | }; | 98 | }; |
| 92 | 99 | ||
| 93 | static const char *cm_getv[] = { | 100 | static const char *cm_getv[] = { |
| @@ -96,7 +103,8 @@ static const char *cm_getv[] = { | |||
| 96 | NULL, "PBLG", NULL, NULL, | 103 | NULL, "PBLG", NULL, NULL, |
| 97 | "CFVG", NULL, NULL, NULL, | 104 | "CFVG", NULL, NULL, NULL, |
| 98 | "USBG", NULL, NULL, "MODG", | 105 | "USBG", NULL, NULL, "MODG", |
| 99 | "CRDG", "LIDG" | 106 | "CRDG", "M3GG", "WIMG", "HWCF", |
| 107 | "LIDG", "TYPE", "PBPG", "TPDG" | ||
| 100 | }; | 108 | }; |
| 101 | 109 | ||
| 102 | static const char *cm_setv[] = { | 110 | static const char *cm_setv[] = { |
| @@ -105,7 +113,8 @@ static const char *cm_setv[] = { | |||
| 105 | "SDSP", "PBLS", "HDPS", NULL, | 113 | "SDSP", "PBLS", "HDPS", NULL, |
| 106 | "CFVS", NULL, NULL, NULL, | 114 | "CFVS", NULL, NULL, NULL, |
| 107 | "USBG", NULL, NULL, "MODS", | 115 | "USBG", NULL, NULL, "MODS", |
| 108 | "CRDS", NULL | 116 | "CRDS", "M3GS", "WIMS", NULL, |
| 117 | NULL, NULL, "PBPS", "TPDS" | ||
| 109 | }; | 118 | }; |
| 110 | 119 | ||
| 111 | #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." | 120 | #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." |
| @@ -130,8 +139,10 @@ struct eeepc_hotk { | |||
| 130 | u16 event_count[128]; /* count for each event */ | 139 | u16 event_count[128]; /* count for each event */ |
| 131 | struct input_dev *inputdev; | 140 | struct input_dev *inputdev; |
| 132 | u16 *keycode_map; | 141 | u16 *keycode_map; |
| 133 | struct rfkill *eeepc_wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
| 134 | struct rfkill *eeepc_bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
| 144 | struct rfkill *wwan3g_rfkill; | ||
| 145 | struct hotplug_slot *hotplug_slot; | ||
| 135 | }; | 146 | }; |
| 136 | 147 | ||
| 137 | /* The actual device the driver binds to */ | 148 | /* The actual device the driver binds to */ |
| @@ -181,6 +192,7 @@ static struct key_entry eeepc_keymap[] = { | |||
| 181 | static int eeepc_hotk_add(struct acpi_device *device); | 192 | static int eeepc_hotk_add(struct acpi_device *device); |
| 182 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 193 | static int eeepc_hotk_remove(struct acpi_device *device, int type); |
| 183 | static int eeepc_hotk_resume(struct acpi_device *device); | 194 | static int eeepc_hotk_resume(struct acpi_device *device); |
| 195 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); | ||
| 184 | 196 | ||
| 185 | static const struct acpi_device_id eeepc_device_ids[] = { | 197 | static const struct acpi_device_id eeepc_device_ids[] = { |
| 186 | {EEEPC_HOTK_HID, 0}, | 198 | {EEEPC_HOTK_HID, 0}, |
| @@ -192,13 +204,24 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
| 192 | .name = EEEPC_HOTK_NAME, | 204 | .name = EEEPC_HOTK_NAME, |
| 193 | .class = EEEPC_HOTK_CLASS, | 205 | .class = EEEPC_HOTK_CLASS, |
| 194 | .ids = eeepc_device_ids, | 206 | .ids = eeepc_device_ids, |
| 207 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 195 | .ops = { | 208 | .ops = { |
| 196 | .add = eeepc_hotk_add, | 209 | .add = eeepc_hotk_add, |
| 197 | .remove = eeepc_hotk_remove, | 210 | .remove = eeepc_hotk_remove, |
| 198 | .resume = eeepc_hotk_resume, | 211 | .resume = eeepc_hotk_resume, |
| 212 | .notify = eeepc_hotk_notify, | ||
| 199 | }, | 213 | }, |
| 200 | }; | 214 | }; |
| 201 | 215 | ||
| 216 | /* PCI hotplug ops */ | ||
| 217 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | ||
| 218 | |||
| 219 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | ||
| 220 | .owner = THIS_MODULE, | ||
| 221 | .get_adapter_status = eeepc_get_adapter_status, | ||
| 222 | .get_power_status = eeepc_get_adapter_status, | ||
| 223 | }; | ||
| 224 | |||
| 202 | /* The backlight device /sys/class/backlight */ | 225 | /* The backlight device /sys/class/backlight */ |
| 203 | static struct backlight_device *eeepc_backlight_device; | 226 | static struct backlight_device *eeepc_backlight_device; |
| 204 | 227 | ||
| @@ -260,20 +283,20 @@ static int set_acpi(int cm, int value) | |||
| 260 | if (method == NULL) | 283 | if (method == NULL) |
| 261 | return -ENODEV; | 284 | return -ENODEV; |
| 262 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | 285 | if (write_acpi_int(ehotk->handle, method, value, NULL)) |
| 263 | printk(EEEPC_WARNING "Error writing %s\n", method); | 286 | pr_warning("Error writing %s\n", method); |
| 264 | } | 287 | } |
| 265 | return 0; | 288 | return 0; |
| 266 | } | 289 | } |
| 267 | 290 | ||
| 268 | static int get_acpi(int cm) | 291 | static int get_acpi(int cm) |
| 269 | { | 292 | { |
| 270 | int value = -1; | 293 | int value = -ENODEV; |
| 271 | if ((ehotk->cm_supported & (0x1 << cm))) { | 294 | if ((ehotk->cm_supported & (0x1 << cm))) { |
| 272 | const char *method = cm_getv[cm]; | 295 | const char *method = cm_getv[cm]; |
| 273 | if (method == NULL) | 296 | if (method == NULL) |
| 274 | return -ENODEV; | 297 | return -ENODEV; |
| 275 | if (read_acpi_int(ehotk->handle, method, &value)) | 298 | if (read_acpi_int(ehotk->handle, method, &value)) |
| 276 | printk(EEEPC_WARNING "Error reading %s\n", method); | 299 | pr_warning("Error reading %s\n", method); |
| 277 | } | 300 | } |
| 278 | return value; | 301 | return value; |
| 279 | } | 302 | } |
| @@ -318,6 +341,15 @@ static const struct rfkill_ops eeepc_rfkill_ops = { | |||
| 318 | .set_block = eeepc_rfkill_set, | 341 | .set_block = eeepc_rfkill_set, |
| 319 | }; | 342 | }; |
| 320 | 343 | ||
| 344 | static void __init eeepc_enable_camera(void) | ||
| 345 | { | ||
| 346 | /* | ||
| 347 | * If the following call to set_acpi() fails, it's because there's no | ||
| 348 | * camera so we can ignore the error. | ||
| 349 | */ | ||
| 350 | set_acpi(CM_ASL_CAMERA, 1); | ||
| 351 | } | ||
| 352 | |||
| 321 | /* | 353 | /* |
| 322 | * Sys helpers | 354 | * Sys helpers |
| 323 | */ | 355 | */ |
| @@ -336,13 +368,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | |||
| 336 | 368 | ||
| 337 | rv = parse_arg(buf, count, &value); | 369 | rv = parse_arg(buf, count, &value); |
| 338 | if (rv > 0) | 370 | if (rv > 0) |
| 339 | set_acpi(cm, value); | 371 | value = set_acpi(cm, value); |
| 372 | if (value < 0) | ||
| 373 | return value; | ||
| 340 | return rv; | 374 | return rv; |
| 341 | } | 375 | } |
| 342 | 376 | ||
| 343 | static ssize_t show_sys_acpi(int cm, char *buf) | 377 | static ssize_t show_sys_acpi(int cm, char *buf) |
| 344 | { | 378 | { |
| 345 | return sprintf(buf, "%d\n", get_acpi(cm)); | 379 | int value = get_acpi(cm); |
| 380 | |||
| 381 | if (value < 0) | ||
| 382 | return value; | ||
| 383 | return sprintf(buf, "%d\n", value); | ||
| 346 | } | 384 | } |
| 347 | 385 | ||
| 348 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | 386 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ |
| @@ -369,13 +407,88 @@ static ssize_t show_sys_acpi(int cm, char *buf) | |||
| 369 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); | 407 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); |
| 370 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); | 408 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); |
| 371 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); | 409 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); |
| 372 | EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV); | 410 | |
| 411 | struct eeepc_cpufv { | ||
| 412 | int num; | ||
| 413 | int cur; | ||
| 414 | }; | ||
| 415 | |||
| 416 | static int get_cpufv(struct eeepc_cpufv *c) | ||
| 417 | { | ||
| 418 | c->cur = get_acpi(CM_ASL_CPUFV); | ||
| 419 | c->num = (c->cur >> 8) & 0xff; | ||
| 420 | c->cur &= 0xff; | ||
| 421 | if (c->cur < 0 || c->num <= 0 || c->num > 12) | ||
| 422 | return -ENODEV; | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static ssize_t show_available_cpufv(struct device *dev, | ||
| 427 | struct device_attribute *attr, | ||
| 428 | char *buf) | ||
| 429 | { | ||
| 430 | struct eeepc_cpufv c; | ||
| 431 | int i; | ||
| 432 | ssize_t len = 0; | ||
| 433 | |||
| 434 | if (get_cpufv(&c)) | ||
| 435 | return -ENODEV; | ||
| 436 | for (i = 0; i < c.num; i++) | ||
| 437 | len += sprintf(buf + len, "%d ", i); | ||
| 438 | len += sprintf(buf + len, "\n"); | ||
| 439 | return len; | ||
| 440 | } | ||
| 441 | |||
| 442 | static ssize_t show_cpufv(struct device *dev, | ||
| 443 | struct device_attribute *attr, | ||
| 444 | char *buf) | ||
| 445 | { | ||
| 446 | struct eeepc_cpufv c; | ||
| 447 | |||
| 448 | if (get_cpufv(&c)) | ||
| 449 | return -ENODEV; | ||
| 450 | return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); | ||
| 451 | } | ||
| 452 | |||
| 453 | static ssize_t store_cpufv(struct device *dev, | ||
| 454 | struct device_attribute *attr, | ||
| 455 | const char *buf, size_t count) | ||
| 456 | { | ||
| 457 | struct eeepc_cpufv c; | ||
| 458 | int rv, value; | ||
| 459 | |||
| 460 | if (get_cpufv(&c)) | ||
| 461 | return -ENODEV; | ||
| 462 | rv = parse_arg(buf, count, &value); | ||
| 463 | if (rv < 0) | ||
| 464 | return rv; | ||
| 465 | if (!rv || value < 0 || value >= c.num) | ||
| 466 | return -EINVAL; | ||
| 467 | set_acpi(CM_ASL_CPUFV, value); | ||
| 468 | return rv; | ||
| 469 | } | ||
| 470 | |||
| 471 | static struct device_attribute dev_attr_cpufv = { | ||
| 472 | .attr = { | ||
| 473 | .name = "cpufv", | ||
| 474 | .mode = 0644 }, | ||
| 475 | .show = show_cpufv, | ||
| 476 | .store = store_cpufv | ||
| 477 | }; | ||
| 478 | |||
| 479 | static struct device_attribute dev_attr_available_cpufv = { | ||
| 480 | .attr = { | ||
| 481 | .name = "available_cpufv", | ||
| 482 | .mode = 0444 }, | ||
| 483 | .show = show_available_cpufv | ||
| 484 | }; | ||
| 373 | 485 | ||
| 374 | static struct attribute *platform_attributes[] = { | 486 | static struct attribute *platform_attributes[] = { |
| 375 | &dev_attr_camera.attr, | 487 | &dev_attr_camera.attr, |
| 376 | &dev_attr_cardr.attr, | 488 | &dev_attr_cardr.attr, |
| 377 | &dev_attr_disp.attr, | 489 | &dev_attr_disp.attr, |
| 378 | &dev_attr_cpufv.attr, | 490 | &dev_attr_cpufv.attr, |
| 491 | &dev_attr_available_cpufv.attr, | ||
| 379 | NULL | 492 | NULL |
| 380 | }; | 493 | }; |
| 381 | 494 | ||
| @@ -441,6 +554,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
| 441 | return -EINVAL; | 554 | return -EINVAL; |
| 442 | } | 555 | } |
| 443 | 556 | ||
| 557 | static void cmsg_quirk(int cm, const char *name) | ||
| 558 | { | ||
| 559 | int dummy; | ||
| 560 | |||
| 561 | /* Some BIOSes do not report cm although it is avaliable. | ||
| 562 | Check if cm_getv[cm] works and, if yes, assume cm should be set. */ | ||
| 563 | if (!(ehotk->cm_supported & (1 << cm)) | ||
| 564 | && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { | ||
| 565 | pr_info("%s (%x) not reported by BIOS," | ||
| 566 | " enabling anyway\n", name, 1 << cm); | ||
| 567 | ehotk->cm_supported |= 1 << cm; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static void cmsg_quirks(void) | ||
| 572 | { | ||
| 573 | cmsg_quirk(CM_ASL_LID, "LID"); | ||
| 574 | cmsg_quirk(CM_ASL_TYPE, "TYPE"); | ||
| 575 | cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); | ||
| 576 | cmsg_quirk(CM_ASL_TPD, "TPD"); | ||
| 577 | } | ||
| 578 | |||
| 444 | static int eeepc_hotk_check(void) | 579 | static int eeepc_hotk_check(void) |
| 445 | { | 580 | { |
| 446 | const struct key_entry *key; | 581 | const struct key_entry *key; |
| @@ -453,26 +588,24 @@ static int eeepc_hotk_check(void) | |||
| 453 | if (ehotk->device->status.present) { | 588 | if (ehotk->device->status.present) { |
| 454 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | 589 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, |
| 455 | &buffer)) { | 590 | &buffer)) { |
| 456 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | 591 | pr_err("Hotkey initialization failed\n"); |
| 457 | return -ENODEV; | 592 | return -ENODEV; |
| 458 | } else { | 593 | } else { |
| 459 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | 594 | pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); |
| 460 | ehotk->init_flag); | ||
| 461 | } | 595 | } |
| 462 | /* get control methods supported */ | 596 | /* get control methods supported */ |
| 463 | if (read_acpi_int(ehotk->handle, "CMSG" | 597 | if (read_acpi_int(ehotk->handle, "CMSG" |
| 464 | , &ehotk->cm_supported)) { | 598 | , &ehotk->cm_supported)) { |
| 465 | printk(EEEPC_ERR | 599 | pr_err("Get control methods supported failed\n"); |
| 466 | "Get control methods supported failed\n"); | ||
| 467 | return -ENODEV; | 600 | return -ENODEV; |
| 468 | } else { | 601 | } else { |
| 469 | printk(EEEPC_INFO | 602 | cmsg_quirks(); |
| 470 | "Get control methods supported: 0x%x\n", | 603 | pr_info("Get control methods supported: 0x%x\n", |
| 471 | ehotk->cm_supported); | 604 | ehotk->cm_supported); |
| 472 | } | 605 | } |
| 473 | ehotk->inputdev = input_allocate_device(); | 606 | ehotk->inputdev = input_allocate_device(); |
| 474 | if (!ehotk->inputdev) { | 607 | if (!ehotk->inputdev) { |
| 475 | printk(EEEPC_INFO "Unable to allocate input device\n"); | 608 | pr_info("Unable to allocate input device\n"); |
| 476 | return 0; | 609 | return 0; |
| 477 | } | 610 | } |
| 478 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | 611 | ehotk->inputdev->name = "Asus EeePC extra buttons"; |
| @@ -491,12 +624,12 @@ static int eeepc_hotk_check(void) | |||
| 491 | } | 624 | } |
| 492 | result = input_register_device(ehotk->inputdev); | 625 | result = input_register_device(ehotk->inputdev); |
| 493 | if (result) { | 626 | if (result) { |
| 494 | printk(EEEPC_INFO "Unable to register input device\n"); | 627 | pr_info("Unable to register input device\n"); |
| 495 | input_free_device(ehotk->inputdev); | 628 | input_free_device(ehotk->inputdev); |
| 496 | return 0; | 629 | return 0; |
| 497 | } | 630 | } |
| 498 | } else { | 631 | } else { |
| 499 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 632 | pr_err("Hotkey device not present, aborting\n"); |
| 500 | return -EINVAL; | 633 | return -EINVAL; |
| 501 | } | 634 | } |
| 502 | return 0; | 635 | return 0; |
| @@ -514,6 +647,19 @@ static int notify_brn(void) | |||
| 514 | return -1; | 647 | return -1; |
| 515 | } | 648 | } |
| 516 | 649 | ||
| 650 | static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | ||
| 651 | u8 *value) | ||
| 652 | { | ||
| 653 | int val = get_acpi(CM_ASL_WLAN); | ||
| 654 | |||
| 655 | if (val == 1 || val == 0) | ||
| 656 | *value = val; | ||
| 657 | else | ||
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 517 | static void eeepc_rfkill_hotplug(void) | 663 | static void eeepc_rfkill_hotplug(void) |
| 518 | { | 664 | { |
| 519 | struct pci_dev *dev; | 665 | struct pci_dev *dev; |
| @@ -521,7 +667,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 521 | bool blocked; | 667 | bool blocked; |
| 522 | 668 | ||
| 523 | if (!bus) { | 669 | if (!bus) { |
| 524 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 670 | pr_warning("Unable to find PCI bus 1?\n"); |
| 525 | return; | 671 | return; |
| 526 | } | 672 | } |
| 527 | 673 | ||
| @@ -537,7 +683,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 537 | if (dev) { | 683 | if (dev) { |
| 538 | pci_bus_assign_resources(bus); | 684 | pci_bus_assign_resources(bus); |
| 539 | if (pci_bus_add_device(dev)) | 685 | if (pci_bus_add_device(dev)) |
| 540 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | 686 | pr_err("Unable to hotplug wifi\n"); |
| 541 | } | 687 | } |
| 542 | } else { | 688 | } else { |
| 543 | dev = pci_get_slot(bus, 0); | 689 | dev = pci_get_slot(bus, 0); |
| @@ -547,7 +693,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 547 | } | 693 | } |
| 548 | } | 694 | } |
| 549 | 695 | ||
| 550 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 696 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
| 551 | } | 697 | } |
| 552 | 698 | ||
| 553 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 699 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
| @@ -558,7 +704,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
| 558 | eeepc_rfkill_hotplug(); | 704 | eeepc_rfkill_hotplug(); |
| 559 | } | 705 | } |
| 560 | 706 | ||
| 561 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 707 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
| 562 | { | 708 | { |
| 563 | static struct key_entry *key; | 709 | static struct key_entry *key; |
| 564 | u16 count; | 710 | u16 count; |
| @@ -566,6 +712,8 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
| 566 | 712 | ||
| 567 | if (!ehotk) | 713 | if (!ehotk) |
| 568 | return; | 714 | return; |
| 715 | if (event > ACPI_MAX_SYS_NOTIFY) | ||
| 716 | return; | ||
| 569 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 717 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
| 570 | brn = notify_brn(); | 718 | brn = notify_brn(); |
| 571 | count = ehotk->event_count[event % 128]++; | 719 | count = ehotk->event_count[event % 128]++; |
| @@ -618,8 +766,7 @@ static int eeepc_register_rfkill_notifier(char *node) | |||
| 618 | eeepc_rfkill_notify, | 766 | eeepc_rfkill_notify, |
| 619 | NULL); | 767 | NULL); |
| 620 | if (ACPI_FAILURE(status)) | 768 | if (ACPI_FAILURE(status)) |
| 621 | printk(EEEPC_WARNING | 769 | pr_warning("Failed to register notify on %s\n", node); |
| 622 | "Failed to register notify on %s\n", node); | ||
| 623 | } else | 770 | } else |
| 624 | return -ENODEV; | 771 | return -ENODEV; |
| 625 | 772 | ||
| @@ -638,20 +785,66 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
| 638 | ACPI_SYSTEM_NOTIFY, | 785 | ACPI_SYSTEM_NOTIFY, |
| 639 | eeepc_rfkill_notify); | 786 | eeepc_rfkill_notify); |
| 640 | if (ACPI_FAILURE(status)) | 787 | if (ACPI_FAILURE(status)) |
| 641 | printk(EEEPC_ERR | 788 | pr_err("Error removing rfkill notify handler %s\n", |
| 642 | "Error removing rfkill notify handler %s\n", | ||
| 643 | node); | 789 | node); |
| 644 | } | 790 | } |
| 645 | } | 791 | } |
| 646 | 792 | ||
| 793 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | ||
| 794 | { | ||
| 795 | kfree(hotplug_slot->info); | ||
| 796 | kfree(hotplug_slot); | ||
| 797 | } | ||
| 798 | |||
| 799 | static int eeepc_setup_pci_hotplug(void) | ||
| 800 | { | ||
| 801 | int ret = -ENOMEM; | ||
| 802 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
| 803 | |||
| 804 | if (!bus) { | ||
| 805 | pr_err("Unable to find wifi PCI bus\n"); | ||
| 806 | return -ENODEV; | ||
| 807 | } | ||
| 808 | |||
| 809 | ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
| 810 | if (!ehotk->hotplug_slot) | ||
| 811 | goto error_slot; | ||
| 812 | |||
| 813 | ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), | ||
| 814 | GFP_KERNEL); | ||
| 815 | if (!ehotk->hotplug_slot->info) | ||
| 816 | goto error_info; | ||
| 817 | |||
| 818 | ehotk->hotplug_slot->private = ehotk; | ||
| 819 | ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; | ||
| 820 | ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; | ||
| 821 | eeepc_get_adapter_status(ehotk->hotplug_slot, | ||
| 822 | &ehotk->hotplug_slot->info->adapter_status); | ||
| 823 | |||
| 824 | ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); | ||
| 825 | if (ret) { | ||
| 826 | pr_err("Unable to register hotplug slot - %d\n", ret); | ||
| 827 | goto error_register; | ||
| 828 | } | ||
| 829 | |||
| 830 | return 0; | ||
| 831 | |||
| 832 | error_register: | ||
| 833 | kfree(ehotk->hotplug_slot->info); | ||
| 834 | error_info: | ||
| 835 | kfree(ehotk->hotplug_slot); | ||
| 836 | ehotk->hotplug_slot = NULL; | ||
| 837 | error_slot: | ||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | |||
| 647 | static int eeepc_hotk_add(struct acpi_device *device) | 841 | static int eeepc_hotk_add(struct acpi_device *device) |
| 648 | { | 842 | { |
| 649 | acpi_status status = AE_OK; | ||
| 650 | int result; | 843 | int result; |
| 651 | 844 | ||
| 652 | if (!device) | 845 | if (!device) |
| 653 | return -EINVAL; | 846 | return -EINVAL; |
| 654 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | 847 | pr_notice(EEEPC_HOTK_NAME "\n"); |
| 655 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | 848 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
| 656 | if (!ehotk) | 849 | if (!ehotk) |
| 657 | return -ENOMEM; | 850 | return -ENOMEM; |
| @@ -664,58 +857,9 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 664 | result = eeepc_hotk_check(); | 857 | result = eeepc_hotk_check(); |
| 665 | if (result) | 858 | if (result) |
| 666 | goto ehotk_fail; | 859 | goto ehotk_fail; |
| 667 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
| 668 | eeepc_hotk_notify, ehotk); | ||
| 669 | if (ACPI_FAILURE(status)) | ||
| 670 | printk(EEEPC_ERR "Error installing notify handler\n"); | ||
| 671 | |||
| 672 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 673 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 674 | |||
| 675 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
| 676 | ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", | ||
| 677 | &device->dev, | ||
| 678 | RFKILL_TYPE_WLAN, | ||
| 679 | &eeepc_rfkill_ops, | ||
| 680 | (void *)CM_ASL_WLAN); | ||
| 681 | |||
| 682 | if (!ehotk->eeepc_wlan_rfkill) | ||
| 683 | goto wlan_fail; | ||
| 684 | |||
| 685 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, | ||
| 686 | get_acpi(CM_ASL_WLAN) != 1); | ||
| 687 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
| 688 | if (result) | ||
| 689 | goto wlan_fail; | ||
| 690 | } | ||
| 691 | |||
| 692 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
| 693 | ehotk->eeepc_bluetooth_rfkill = | ||
| 694 | rfkill_alloc("eeepc-bluetooth", | ||
| 695 | &device->dev, | ||
| 696 | RFKILL_TYPE_BLUETOOTH, | ||
| 697 | &eeepc_rfkill_ops, | ||
| 698 | (void *)CM_ASL_BLUETOOTH); | ||
| 699 | |||
| 700 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
| 701 | goto bluetooth_fail; | ||
| 702 | |||
| 703 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
| 704 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
| 705 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
| 706 | if (result) | ||
| 707 | goto bluetooth_fail; | ||
| 708 | } | ||
| 709 | 860 | ||
| 710 | return 0; | 861 | return 0; |
| 711 | 862 | ||
| 712 | bluetooth_fail: | ||
| 713 | rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); | ||
| 714 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
| 715 | wlan_fail: | ||
| 716 | rfkill_destroy(ehotk->eeepc_wlan_rfkill); | ||
| 717 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 718 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 719 | ehotk_fail: | 863 | ehotk_fail: |
| 720 | kfree(ehotk); | 864 | kfree(ehotk); |
| 721 | ehotk = NULL; | 865 | ehotk = NULL; |
| @@ -725,17 +869,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 725 | 869 | ||
| 726 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | 870 | static int eeepc_hotk_remove(struct acpi_device *device, int type) |
| 727 | { | 871 | { |
| 728 | acpi_status status = 0; | ||
| 729 | |||
| 730 | if (!device || !acpi_driver_data(device)) | 872 | if (!device || !acpi_driver_data(device)) |
| 731 | return -EINVAL; | 873 | return -EINVAL; |
| 732 | status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
| 733 | eeepc_hotk_notify); | ||
| 734 | if (ACPI_FAILURE(status)) | ||
| 735 | printk(EEEPC_ERR "Error removing notify handler\n"); | ||
| 736 | |||
| 737 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 738 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 739 | 874 | ||
| 740 | kfree(ehotk); | 875 | kfree(ehotk); |
| 741 | return 0; | 876 | return 0; |
| @@ -743,7 +878,7 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
| 743 | 878 | ||
| 744 | static int eeepc_hotk_resume(struct acpi_device *device) | 879 | static int eeepc_hotk_resume(struct acpi_device *device) |
| 745 | { | 880 | { |
| 746 | if (ehotk->eeepc_wlan_rfkill) { | 881 | if (ehotk->wlan_rfkill) { |
| 747 | bool wlan; | 882 | bool wlan; |
| 748 | 883 | ||
| 749 | /* Workaround - it seems that _PTS disables the wireless | 884 | /* Workaround - it seems that _PTS disables the wireless |
| @@ -755,14 +890,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
| 755 | wlan = get_acpi(CM_ASL_WLAN); | 890 | wlan = get_acpi(CM_ASL_WLAN); |
| 756 | set_acpi(CM_ASL_WLAN, wlan); | 891 | set_acpi(CM_ASL_WLAN, wlan); |
| 757 | 892 | ||
| 758 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 893 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
| 759 | wlan != 1); | ||
| 760 | 894 | ||
| 761 | eeepc_rfkill_hotplug(); | 895 | eeepc_rfkill_hotplug(); |
| 762 | } | 896 | } |
| 763 | 897 | ||
| 764 | if (ehotk->eeepc_bluetooth_rfkill) | 898 | if (ehotk->bluetooth_rfkill) |
| 765 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 899 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
| 766 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 900 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
| 767 | 901 | ||
| 768 | return 0; | 902 | return 0; |
| @@ -884,10 +1018,16 @@ static void eeepc_backlight_exit(void) | |||
| 884 | 1018 | ||
| 885 | static void eeepc_rfkill_exit(void) | 1019 | static void eeepc_rfkill_exit(void) |
| 886 | { | 1020 | { |
| 887 | if (ehotk->eeepc_wlan_rfkill) | 1021 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
| 888 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
| 889 | if (ehotk->eeepc_bluetooth_rfkill) | 1023 | if (ehotk->wlan_rfkill) |
| 890 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 1024 | rfkill_unregister(ehotk->wlan_rfkill); |
| 1025 | if (ehotk->bluetooth_rfkill) | ||
| 1026 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
| 1027 | if (ehotk->wwan3g_rfkill) | ||
| 1028 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
| 1029 | if (ehotk->hotplug_slot) | ||
| 1030 | pci_hp_deregister(ehotk->hotplug_slot); | ||
| 891 | } | 1031 | } |
| 892 | 1032 | ||
| 893 | static void eeepc_input_exit(void) | 1033 | static void eeepc_input_exit(void) |
| @@ -922,6 +1062,75 @@ static void __exit eeepc_laptop_exit(void) | |||
| 922 | platform_driver_unregister(&platform_driver); | 1062 | platform_driver_unregister(&platform_driver); |
| 923 | } | 1063 | } |
| 924 | 1064 | ||
| 1065 | static int eeepc_new_rfkill(struct rfkill **rfkill, | ||
| 1066 | const char *name, struct device *dev, | ||
| 1067 | enum rfkill_type type, int cm) | ||
| 1068 | { | ||
| 1069 | int result; | ||
| 1070 | |||
| 1071 | result = get_acpi(cm); | ||
| 1072 | if (result < 0) | ||
| 1073 | return result; | ||
| 1074 | |||
| 1075 | *rfkill = rfkill_alloc(name, dev, type, | ||
| 1076 | &eeepc_rfkill_ops, (void *)(unsigned long)cm); | ||
| 1077 | |||
| 1078 | if (!*rfkill) | ||
| 1079 | return -EINVAL; | ||
| 1080 | |||
| 1081 | rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); | ||
| 1082 | result = rfkill_register(*rfkill); | ||
| 1083 | if (result) { | ||
| 1084 | rfkill_destroy(*rfkill); | ||
| 1085 | *rfkill = NULL; | ||
| 1086 | return result; | ||
| 1087 | } | ||
| 1088 | return 0; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | |||
| 1092 | static int eeepc_rfkill_init(struct device *dev) | ||
| 1093 | { | ||
| 1094 | int result = 0; | ||
| 1095 | |||
| 1096 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 1097 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 1098 | |||
| 1099 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | ||
| 1100 | "eeepc-wlan", dev, | ||
| 1101 | RFKILL_TYPE_WLAN, CM_ASL_WLAN); | ||
| 1102 | |||
| 1103 | if (result && result != -ENODEV) | ||
| 1104 | goto exit; | ||
| 1105 | |||
| 1106 | result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, | ||
| 1107 | "eeepc-bluetooth", dev, | ||
| 1108 | RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); | ||
| 1109 | |||
| 1110 | if (result && result != -ENODEV) | ||
| 1111 | goto exit; | ||
| 1112 | |||
| 1113 | result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, | ||
| 1114 | "eeepc-wwan3g", dev, | ||
| 1115 | RFKILL_TYPE_WWAN, CM_ASL_3G); | ||
| 1116 | |||
| 1117 | if (result && result != -ENODEV) | ||
| 1118 | goto exit; | ||
| 1119 | |||
| 1120 | result = eeepc_setup_pci_hotplug(); | ||
| 1121 | /* | ||
| 1122 | * If we get -EBUSY then something else is handling the PCI hotplug - | ||
| 1123 | * don't fail in this case | ||
| 1124 | */ | ||
| 1125 | if (result == -EBUSY) | ||
| 1126 | result = 0; | ||
| 1127 | |||
| 1128 | exit: | ||
| 1129 | if (result && result != -ENODEV) | ||
| 1130 | eeepc_rfkill_exit(); | ||
| 1131 | return result; | ||
| 1132 | } | ||
| 1133 | |||
| 925 | static int eeepc_backlight_init(struct device *dev) | 1134 | static int eeepc_backlight_init(struct device *dev) |
| 926 | { | 1135 | { |
| 927 | struct backlight_device *bd; | 1136 | struct backlight_device *bd; |
| @@ -929,8 +1138,7 @@ static int eeepc_backlight_init(struct device *dev) | |||
| 929 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | 1138 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, |
| 930 | NULL, &eeepcbl_ops); | 1139 | NULL, &eeepcbl_ops); |
| 931 | if (IS_ERR(bd)) { | 1140 | if (IS_ERR(bd)) { |
| 932 | printk(EEEPC_ERR | 1141 | pr_err("Could not register eeepc backlight device\n"); |
| 933 | "Could not register eeepc backlight device\n"); | ||
| 934 | eeepc_backlight_device = NULL; | 1142 | eeepc_backlight_device = NULL; |
| 935 | return PTR_ERR(bd); | 1143 | return PTR_ERR(bd); |
| 936 | } | 1144 | } |
| @@ -949,8 +1157,7 @@ static int eeepc_hwmon_init(struct device *dev) | |||
| 949 | 1157 | ||
| 950 | hwmon = hwmon_device_register(dev); | 1158 | hwmon = hwmon_device_register(dev); |
| 951 | if (IS_ERR(hwmon)) { | 1159 | if (IS_ERR(hwmon)) { |
| 952 | printk(EEEPC_ERR | 1160 | pr_err("Could not register eeepc hwmon device\n"); |
| 953 | "Could not register eeepc hwmon device\n"); | ||
| 954 | eeepc_hwmon_device = NULL; | 1161 | eeepc_hwmon_device = NULL; |
| 955 | return PTR_ERR(hwmon); | 1162 | return PTR_ERR(hwmon); |
| 956 | } | 1163 | } |
| @@ -976,19 +1183,9 @@ static int __init eeepc_laptop_init(void) | |||
| 976 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1183 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
| 977 | return -ENODEV; | 1184 | return -ENODEV; |
| 978 | } | 1185 | } |
| 979 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
| 980 | 1186 | ||
| 981 | if (!acpi_video_backlight_support()) { | 1187 | eeepc_enable_camera(); |
| 982 | result = eeepc_backlight_init(dev); | ||
| 983 | if (result) | ||
| 984 | goto fail_backlight; | ||
| 985 | } else | ||
| 986 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
| 987 | "driver\n"); | ||
| 988 | 1188 | ||
| 989 | result = eeepc_hwmon_init(dev); | ||
| 990 | if (result) | ||
| 991 | goto fail_hwmon; | ||
| 992 | /* Register platform stuff */ | 1189 | /* Register platform stuff */ |
| 993 | result = platform_driver_register(&platform_driver); | 1190 | result = platform_driver_register(&platform_driver); |
| 994 | if (result) | 1191 | if (result) |
| @@ -1005,7 +1202,33 @@ static int __init eeepc_laptop_init(void) | |||
| 1005 | &platform_attribute_group); | 1202 | &platform_attribute_group); |
| 1006 | if (result) | 1203 | if (result) |
| 1007 | goto fail_sysfs; | 1204 | goto fail_sysfs; |
| 1205 | |||
| 1206 | dev = &platform_device->dev; | ||
| 1207 | |||
| 1208 | if (!acpi_video_backlight_support()) { | ||
| 1209 | result = eeepc_backlight_init(dev); | ||
| 1210 | if (result) | ||
| 1211 | goto fail_backlight; | ||
| 1212 | } else | ||
| 1213 | pr_info("Backlight controlled by ACPI video " | ||
| 1214 | "driver\n"); | ||
| 1215 | |||
| 1216 | result = eeepc_hwmon_init(dev); | ||
| 1217 | if (result) | ||
| 1218 | goto fail_hwmon; | ||
| 1219 | |||
| 1220 | result = eeepc_rfkill_init(dev); | ||
| 1221 | if (result) | ||
| 1222 | goto fail_rfkill; | ||
| 1223 | |||
| 1008 | return 0; | 1224 | return 0; |
| 1225 | fail_rfkill: | ||
| 1226 | eeepc_hwmon_exit(); | ||
| 1227 | fail_hwmon: | ||
| 1228 | eeepc_backlight_exit(); | ||
| 1229 | fail_backlight: | ||
| 1230 | sysfs_remove_group(&platform_device->dev.kobj, | ||
| 1231 | &platform_attribute_group); | ||
| 1009 | fail_sysfs: | 1232 | fail_sysfs: |
| 1010 | platform_device_del(platform_device); | 1233 | platform_device_del(platform_device); |
| 1011 | fail_platform_device2: | 1234 | fail_platform_device2: |
| @@ -1013,12 +1236,7 @@ fail_platform_device2: | |||
| 1013 | fail_platform_device1: | 1236 | fail_platform_device1: |
| 1014 | platform_driver_unregister(&platform_driver); | 1237 | platform_driver_unregister(&platform_driver); |
| 1015 | fail_platform_driver: | 1238 | fail_platform_driver: |
| 1016 | eeepc_hwmon_exit(); | ||
| 1017 | fail_hwmon: | ||
| 1018 | eeepc_backlight_exit(); | ||
| 1019 | fail_backlight: | ||
| 1020 | eeepc_input_exit(); | 1239 | eeepc_input_exit(); |
| 1021 | eeepc_rfkill_exit(); | ||
| 1022 | return result; | 1240 | return result; |
| 1023 | } | 1241 | } |
| 1024 | 1242 | ||
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 16fffe44e333..ca508564a181 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -47,7 +47,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); | |||
| 47 | #define HPWMI_DISPLAY_QUERY 0x1 | 47 | #define HPWMI_DISPLAY_QUERY 0x1 |
| 48 | #define HPWMI_HDDTEMP_QUERY 0x2 | 48 | #define HPWMI_HDDTEMP_QUERY 0x2 |
| 49 | #define HPWMI_ALS_QUERY 0x3 | 49 | #define HPWMI_ALS_QUERY 0x3 |
| 50 | #define HPWMI_DOCK_QUERY 0x4 | 50 | #define HPWMI_HARDWARE_QUERY 0x4 |
| 51 | #define HPWMI_WIRELESS_QUERY 0x5 | 51 | #define HPWMI_WIRELESS_QUERY 0x5 |
| 52 | #define HPWMI_HOTKEY_QUERY 0xc | 52 | #define HPWMI_HOTKEY_QUERY 0xc |
| 53 | 53 | ||
| @@ -75,10 +75,9 @@ struct key_entry { | |||
| 75 | u16 keycode; | 75 | u16 keycode; |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | enum { KE_KEY, KE_SW, KE_END }; | 78 | enum { KE_KEY, KE_END }; |
| 79 | 79 | ||
| 80 | static struct key_entry hp_wmi_keymap[] = { | 80 | static struct key_entry hp_wmi_keymap[] = { |
| 81 | {KE_SW, 0x01, SW_DOCK}, | ||
| 82 | {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, | 81 | {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, |
| 83 | {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, | 82 | {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, |
| 84 | {KE_KEY, 0x20e6, KEY_PROG1}, | 83 | {KE_KEY, 0x20e6, KEY_PROG1}, |
| @@ -151,13 +150,28 @@ static int hp_wmi_als_state(void) | |||
| 151 | 150 | ||
| 152 | static int hp_wmi_dock_state(void) | 151 | static int hp_wmi_dock_state(void) |
| 153 | { | 152 | { |
| 154 | return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); | 153 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); |
| 154 | |||
| 155 | if (ret < 0) | ||
| 156 | return ret; | ||
| 157 | |||
| 158 | return ret & 0x1; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int hp_wmi_tablet_state(void) | ||
| 162 | { | ||
| 163 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); | ||
| 164 | |||
| 165 | if (ret < 0) | ||
| 166 | return ret; | ||
| 167 | |||
| 168 | return (ret & 0x4) ? 1 : 0; | ||
| 155 | } | 169 | } |
| 156 | 170 | ||
| 157 | static int hp_wmi_set_block(void *data, bool blocked) | 171 | static int hp_wmi_set_block(void *data, bool blocked) |
| 158 | { | 172 | { |
| 159 | unsigned long b = (unsigned long) data; | 173 | unsigned long b = (unsigned long) data; |
| 160 | int query = BIT(b + 8) | ((!!blocked) << b); | 174 | int query = BIT(b + 8) | ((!blocked) << b); |
| 161 | 175 | ||
| 162 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); | 176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); |
| 163 | } | 177 | } |
| @@ -232,6 +246,15 @@ static ssize_t show_dock(struct device *dev, struct device_attribute *attr, | |||
| 232 | return sprintf(buf, "%d\n", value); | 246 | return sprintf(buf, "%d\n", value); |
| 233 | } | 247 | } |
| 234 | 248 | ||
| 249 | static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, | ||
| 250 | char *buf) | ||
| 251 | { | ||
| 252 | int value = hp_wmi_tablet_state(); | ||
| 253 | if (value < 0) | ||
| 254 | return -EINVAL; | ||
| 255 | return sprintf(buf, "%d\n", value); | ||
| 256 | } | ||
| 257 | |||
| 235 | static ssize_t set_als(struct device *dev, struct device_attribute *attr, | 258 | static ssize_t set_als(struct device *dev, struct device_attribute *attr, |
| 236 | const char *buf, size_t count) | 259 | const char *buf, size_t count) |
| 237 | { | 260 | { |
| @@ -244,6 +267,7 @@ static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); | |||
| 244 | static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); | 267 | static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); |
| 245 | static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); | 268 | static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); |
| 246 | static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); | 269 | static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); |
| 270 | static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); | ||
| 247 | 271 | ||
| 248 | static struct key_entry *hp_wmi_get_entry_by_scancode(int code) | 272 | static struct key_entry *hp_wmi_get_entry_by_scancode(int code) |
| 249 | { | 273 | { |
| @@ -326,13 +350,13 @@ static void hp_wmi_notify(u32 value, void *context) | |||
| 326 | key->keycode, 0); | 350 | key->keycode, 0); |
| 327 | input_sync(hp_wmi_input_dev); | 351 | input_sync(hp_wmi_input_dev); |
| 328 | break; | 352 | break; |
| 329 | case KE_SW: | ||
| 330 | input_report_switch(hp_wmi_input_dev, | ||
| 331 | key->keycode, | ||
| 332 | hp_wmi_dock_state()); | ||
| 333 | input_sync(hp_wmi_input_dev); | ||
| 334 | break; | ||
| 335 | } | 353 | } |
| 354 | } else if (eventcode == 0x1) { | ||
| 355 | input_report_switch(hp_wmi_input_dev, SW_DOCK, | ||
| 356 | hp_wmi_dock_state()); | ||
| 357 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | ||
| 358 | hp_wmi_tablet_state()); | ||
| 359 | input_sync(hp_wmi_input_dev); | ||
| 336 | } else if (eventcode == 0x5) { | 360 | } else if (eventcode == 0x5) { |
| 337 | if (wifi_rfkill) | 361 | if (wifi_rfkill) |
| 338 | rfkill_set_sw_state(wifi_rfkill, | 362 | rfkill_set_sw_state(wifi_rfkill, |
| @@ -369,18 +393,19 @@ static int __init hp_wmi_input_setup(void) | |||
| 369 | set_bit(EV_KEY, hp_wmi_input_dev->evbit); | 393 | set_bit(EV_KEY, hp_wmi_input_dev->evbit); |
| 370 | set_bit(key->keycode, hp_wmi_input_dev->keybit); | 394 | set_bit(key->keycode, hp_wmi_input_dev->keybit); |
| 371 | break; | 395 | break; |
| 372 | case KE_SW: | ||
| 373 | set_bit(EV_SW, hp_wmi_input_dev->evbit); | ||
| 374 | set_bit(key->keycode, hp_wmi_input_dev->swbit); | ||
| 375 | |||
| 376 | /* Set initial dock state */ | ||
| 377 | input_report_switch(hp_wmi_input_dev, key->keycode, | ||
| 378 | hp_wmi_dock_state()); | ||
| 379 | input_sync(hp_wmi_input_dev); | ||
| 380 | break; | ||
| 381 | } | 396 | } |
| 382 | } | 397 | } |
| 383 | 398 | ||
| 399 | set_bit(EV_SW, hp_wmi_input_dev->evbit); | ||
| 400 | set_bit(SW_DOCK, hp_wmi_input_dev->swbit); | ||
| 401 | set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); | ||
| 402 | |||
| 403 | /* Set initial hardware state */ | ||
| 404 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); | ||
| 405 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | ||
| 406 | hp_wmi_tablet_state()); | ||
| 407 | input_sync(hp_wmi_input_dev); | ||
| 408 | |||
| 384 | err = input_register_device(hp_wmi_input_dev); | 409 | err = input_register_device(hp_wmi_input_dev); |
| 385 | 410 | ||
| 386 | if (err) { | 411 | if (err) { |
| @@ -397,6 +422,7 @@ static void cleanup_sysfs(struct platform_device *device) | |||
| 397 | device_remove_file(&device->dev, &dev_attr_hddtemp); | 422 | device_remove_file(&device->dev, &dev_attr_hddtemp); |
| 398 | device_remove_file(&device->dev, &dev_attr_als); | 423 | device_remove_file(&device->dev, &dev_attr_als); |
| 399 | device_remove_file(&device->dev, &dev_attr_dock); | 424 | device_remove_file(&device->dev, &dev_attr_dock); |
| 425 | device_remove_file(&device->dev, &dev_attr_tablet); | ||
| 400 | } | 426 | } |
| 401 | 427 | ||
| 402 | static int __init hp_wmi_bios_setup(struct platform_device *device) | 428 | static int __init hp_wmi_bios_setup(struct platform_device *device) |
| @@ -416,6 +442,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
| 416 | err = device_create_file(&device->dev, &dev_attr_dock); | 442 | err = device_create_file(&device->dev, &dev_attr_dock); |
| 417 | if (err) | 443 | if (err) |
| 418 | goto add_sysfs_error; | 444 | goto add_sysfs_error; |
| 445 | err = device_create_file(&device->dev, &dev_attr_tablet); | ||
| 446 | if (err) | ||
| 447 | goto add_sysfs_error; | ||
| 419 | 448 | ||
| 420 | if (wireless & 0x1) { | 449 | if (wireless & 0x1) { |
| 421 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, | 450 | wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, |
| @@ -485,23 +514,17 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) | |||
| 485 | 514 | ||
| 486 | static int hp_wmi_resume_handler(struct platform_device *device) | 515 | static int hp_wmi_resume_handler(struct platform_device *device) |
| 487 | { | 516 | { |
| 488 | struct key_entry *key; | ||
| 489 | |||
| 490 | /* | 517 | /* |
| 491 | * Docking state may have changed while suspended, so trigger | 518 | * Hardware state may have changed while suspended, so trigger |
| 492 | * an input event for the current state. As this is a switch, | 519 | * input events for the current state. As this is a switch, |
| 493 | * the input layer will only actually pass it on if the state | 520 | * the input layer will only actually pass it on if the state |
| 494 | * changed. | 521 | * changed. |
| 495 | */ | 522 | */ |
| 496 | for (key = hp_wmi_keymap; key->type != KE_END; key++) { | 523 | |
| 497 | switch (key->type) { | 524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); |
| 498 | case KE_SW: | 525 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, |
| 499 | input_report_switch(hp_wmi_input_dev, key->keycode, | 526 | hp_wmi_tablet_state()); |
| 500 | hp_wmi_dock_state()); | 527 | input_sync(hp_wmi_input_dev); |
| 501 | input_sync(hp_wmi_input_dev); | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | } | ||
| 505 | 528 | ||
| 506 | return 0; | 529 | return 0; |
| 507 | } | 530 | } |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 40d64c03278c..a463fd72c495 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #define TPACPI_VERSION "0.23" | 24 | #define TPACPI_VERSION "0.23" |
| 25 | #define TPACPI_SYSFS_VERSION 0x020300 | 25 | #define TPACPI_SYSFS_VERSION 0x020400 |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Changelog: | 28 | * Changelog: |
| @@ -257,6 +257,8 @@ static struct { | |||
| 257 | u32 wan:1; | 257 | u32 wan:1; |
| 258 | u32 uwb:1; | 258 | u32 uwb:1; |
| 259 | u32 fan_ctrl_status_undef:1; | 259 | u32 fan_ctrl_status_undef:1; |
| 260 | u32 second_fan:1; | ||
| 261 | u32 beep_needs_two_args:1; | ||
| 260 | u32 input_device_registered:1; | 262 | u32 input_device_registered:1; |
| 261 | u32 platform_drv_registered:1; | 263 | u32 platform_drv_registered:1; |
| 262 | u32 platform_drv_attrs_registered:1; | 264 | u32 platform_drv_attrs_registered:1; |
| @@ -277,8 +279,10 @@ struct thinkpad_id_data { | |||
| 277 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ | 279 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ |
| 278 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ | 280 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ |
| 279 | 281 | ||
| 280 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | 282 | u16 bios_model; /* 1Y = 0x5931, 0 = unknown */ |
| 281 | u16 ec_model; | 283 | u16 ec_model; |
| 284 | u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */ | ||
| 285 | u16 ec_release; | ||
| 282 | 286 | ||
| 283 | char *model_str; /* ThinkPad T43 */ | 287 | char *model_str; /* ThinkPad T43 */ |
| 284 | char *nummodel_str; /* 9384A9C for a 9384-A9C model */ | 288 | char *nummodel_str; /* 9384A9C for a 9384-A9C model */ |
| @@ -355,6 +359,73 @@ static void tpacpi_log_usertask(const char * const what) | |||
| 355 | } \ | 359 | } \ |
| 356 | } while (0) | 360 | } while (0) |
| 357 | 361 | ||
| 362 | /* | ||
| 363 | * Quirk handling helpers | ||
| 364 | * | ||
| 365 | * ThinkPad IDs and versions seen in the field so far | ||
| 366 | * are two-characters from the set [0-9A-Z], i.e. base 36. | ||
| 367 | * | ||
| 368 | * We use values well outside that range as specials. | ||
| 369 | */ | ||
| 370 | |||
| 371 | #define TPACPI_MATCH_ANY 0xffffU | ||
| 372 | #define TPACPI_MATCH_UNKNOWN 0U | ||
| 373 | |||
| 374 | /* TPID('1', 'Y') == 0x5931 */ | ||
| 375 | #define TPID(__c1, __c2) (((__c2) << 8) | (__c1)) | ||
| 376 | |||
| 377 | #define TPACPI_Q_IBM(__id1, __id2, __quirk) \ | ||
| 378 | { .vendor = PCI_VENDOR_ID_IBM, \ | ||
| 379 | .bios = TPID(__id1, __id2), \ | ||
| 380 | .ec = TPACPI_MATCH_ANY, \ | ||
| 381 | .quirks = (__quirk) } | ||
| 382 | |||
| 383 | #define TPACPI_Q_LNV(__id1, __id2, __quirk) \ | ||
| 384 | { .vendor = PCI_VENDOR_ID_LENOVO, \ | ||
| 385 | .bios = TPID(__id1, __id2), \ | ||
| 386 | .ec = TPACPI_MATCH_ANY, \ | ||
| 387 | .quirks = (__quirk) } | ||
| 388 | |||
| 389 | struct tpacpi_quirk { | ||
| 390 | unsigned int vendor; | ||
| 391 | u16 bios; | ||
| 392 | u16 ec; | ||
| 393 | unsigned long quirks; | ||
| 394 | }; | ||
| 395 | |||
| 396 | /** | ||
| 397 | * tpacpi_check_quirks() - search BIOS/EC version on a list | ||
| 398 | * @qlist: array of &struct tpacpi_quirk | ||
| 399 | * @qlist_size: number of elements in @qlist | ||
| 400 | * | ||
| 401 | * Iterates over a quirks list until one is found that matches the | ||
| 402 | * ThinkPad's vendor, BIOS and EC model. | ||
| 403 | * | ||
| 404 | * Returns 0 if nothing matches, otherwise returns the quirks field of | ||
| 405 | * the matching &struct tpacpi_quirk entry. | ||
| 406 | * | ||
| 407 | * The match criteria is: vendor, ec and bios much match. | ||
| 408 | */ | ||
| 409 | static unsigned long __init tpacpi_check_quirks( | ||
| 410 | const struct tpacpi_quirk *qlist, | ||
| 411 | unsigned int qlist_size) | ||
| 412 | { | ||
| 413 | while (qlist_size) { | ||
| 414 | if ((qlist->vendor == thinkpad_id.vendor || | ||
| 415 | qlist->vendor == TPACPI_MATCH_ANY) && | ||
| 416 | (qlist->bios == thinkpad_id.bios_model || | ||
| 417 | qlist->bios == TPACPI_MATCH_ANY) && | ||
| 418 | (qlist->ec == thinkpad_id.ec_model || | ||
| 419 | qlist->ec == TPACPI_MATCH_ANY)) | ||
| 420 | return qlist->quirks; | ||
| 421 | |||
| 422 | qlist_size--; | ||
| 423 | qlist++; | ||
| 424 | } | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | |||
| 358 | /**************************************************************************** | 429 | /**************************************************************************** |
| 359 | **************************************************************************** | 430 | **************************************************************************** |
| 360 | * | 431 | * |
| @@ -2880,7 +2951,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2880 | /* update bright_acpimode... */ | 2951 | /* update bright_acpimode... */ |
| 2881 | tpacpi_check_std_acpi_brightness_support(); | 2952 | tpacpi_check_std_acpi_brightness_support(); |
| 2882 | 2953 | ||
| 2883 | if (tp_features.bright_acpimode) { | 2954 | if (tp_features.bright_acpimode && acpi_video_backlight_support()) { |
| 2884 | printk(TPACPI_INFO | 2955 | printk(TPACPI_INFO |
| 2885 | "This ThinkPad has standard ACPI backlight " | 2956 | "This ThinkPad has standard ACPI backlight " |
| 2886 | "brightness control, supported by the ACPI " | 2957 | "brightness control, supported by the ACPI " |
| @@ -4773,7 +4844,7 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ | |||
| 4773 | "LED", /* all others */ | 4844 | "LED", /* all others */ |
| 4774 | ); /* R30, R31 */ | 4845 | ); /* R30, R31 */ |
| 4775 | 4846 | ||
| 4776 | #define TPACPI_LED_NUMLEDS 8 | 4847 | #define TPACPI_LED_NUMLEDS 16 |
| 4777 | static struct tpacpi_led_classdev *tpacpi_leds; | 4848 | static struct tpacpi_led_classdev *tpacpi_leds; |
| 4778 | static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; | 4849 | static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; |
| 4779 | static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | 4850 | static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { |
| @@ -4786,15 +4857,20 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | |||
| 4786 | "tpacpi::dock_batt", | 4857 | "tpacpi::dock_batt", |
| 4787 | "tpacpi::unknown_led", | 4858 | "tpacpi::unknown_led", |
| 4788 | "tpacpi::standby", | 4859 | "tpacpi::standby", |
| 4860 | "tpacpi::dock_status1", | ||
| 4861 | "tpacpi::dock_status2", | ||
| 4862 | "tpacpi::unknown_led2", | ||
| 4863 | "tpacpi::unknown_led3", | ||
| 4864 | "tpacpi::thinkvantage", | ||
| 4789 | }; | 4865 | }; |
| 4790 | #define TPACPI_SAFE_LEDS 0x0081U | 4866 | #define TPACPI_SAFE_LEDS 0x1081U |
| 4791 | 4867 | ||
| 4792 | static inline bool tpacpi_is_led_restricted(const unsigned int led) | 4868 | static inline bool tpacpi_is_led_restricted(const unsigned int led) |
| 4793 | { | 4869 | { |
| 4794 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | 4870 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS |
| 4795 | return false; | 4871 | return false; |
| 4796 | #else | 4872 | #else |
| 4797 | return (TPACPI_SAFE_LEDS & (1 << led)) == 0; | 4873 | return (1U & (TPACPI_SAFE_LEDS >> led)) == 0; |
| 4798 | #endif | 4874 | #endif |
| 4799 | } | 4875 | } |
| 4800 | 4876 | ||
| @@ -4956,6 +5032,10 @@ static int __init tpacpi_init_led(unsigned int led) | |||
| 4956 | 5032 | ||
| 4957 | tpacpi_leds[led].led = led; | 5033 | tpacpi_leds[led].led = led; |
| 4958 | 5034 | ||
| 5035 | /* LEDs with no name don't get registered */ | ||
| 5036 | if (!tpacpi_led_names[led]) | ||
| 5037 | return 0; | ||
| 5038 | |||
| 4959 | tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; | 5039 | tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; |
| 4960 | tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; | 5040 | tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; |
| 4961 | if (led_supported == TPACPI_LED_570) | 5041 | if (led_supported == TPACPI_LED_570) |
| @@ -4974,10 +5054,59 @@ static int __init tpacpi_init_led(unsigned int led) | |||
| 4974 | return rc; | 5054 | return rc; |
| 4975 | } | 5055 | } |
| 4976 | 5056 | ||
| 5057 | static const struct tpacpi_quirk led_useful_qtable[] __initconst = { | ||
| 5058 | TPACPI_Q_IBM('1', 'E', 0x009f), /* A30 */ | ||
| 5059 | TPACPI_Q_IBM('1', 'N', 0x009f), /* A31 */ | ||
| 5060 | TPACPI_Q_IBM('1', 'G', 0x009f), /* A31 */ | ||
| 5061 | |||
| 5062 | TPACPI_Q_IBM('1', 'I', 0x0097), /* T30 */ | ||
| 5063 | TPACPI_Q_IBM('1', 'R', 0x0097), /* T40, T41, T42, R50, R51 */ | ||
| 5064 | TPACPI_Q_IBM('7', '0', 0x0097), /* T43, R52 */ | ||
| 5065 | TPACPI_Q_IBM('1', 'Y', 0x0097), /* T43 */ | ||
| 5066 | TPACPI_Q_IBM('1', 'W', 0x0097), /* R50e */ | ||
| 5067 | TPACPI_Q_IBM('1', 'V', 0x0097), /* R51 */ | ||
| 5068 | TPACPI_Q_IBM('7', '8', 0x0097), /* R51e */ | ||
| 5069 | TPACPI_Q_IBM('7', '6', 0x0097), /* R52 */ | ||
| 5070 | |||
| 5071 | TPACPI_Q_IBM('1', 'K', 0x00bf), /* X30 */ | ||
| 5072 | TPACPI_Q_IBM('1', 'Q', 0x00bf), /* X31, X32 */ | ||
| 5073 | TPACPI_Q_IBM('1', 'U', 0x00bf), /* X40 */ | ||
| 5074 | TPACPI_Q_IBM('7', '4', 0x00bf), /* X41 */ | ||
| 5075 | TPACPI_Q_IBM('7', '5', 0x00bf), /* X41t */ | ||
| 5076 | |||
| 5077 | TPACPI_Q_IBM('7', '9', 0x1f97), /* T60 (1) */ | ||
| 5078 | TPACPI_Q_IBM('7', '7', 0x1f97), /* Z60* (1) */ | ||
| 5079 | TPACPI_Q_IBM('7', 'F', 0x1f97), /* Z61* (1) */ | ||
| 5080 | TPACPI_Q_IBM('7', 'B', 0x1fb7), /* X60 (1) */ | ||
| 5081 | |||
| 5082 | /* (1) - may have excess leds enabled on MSB */ | ||
| 5083 | |||
| 5084 | /* Defaults (order matters, keep last, don't reorder!) */ | ||
| 5085 | { /* Lenovo */ | ||
| 5086 | .vendor = PCI_VENDOR_ID_LENOVO, | ||
| 5087 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | ||
| 5088 | .quirks = 0x1fffU, | ||
| 5089 | }, | ||
| 5090 | { /* IBM ThinkPads with no EC version string */ | ||
| 5091 | .vendor = PCI_VENDOR_ID_IBM, | ||
| 5092 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_UNKNOWN, | ||
| 5093 | .quirks = 0x00ffU, | ||
| 5094 | }, | ||
| 5095 | { /* IBM ThinkPads with EC version string */ | ||
| 5096 | .vendor = PCI_VENDOR_ID_IBM, | ||
| 5097 | .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | ||
| 5098 | .quirks = 0x00bfU, | ||
| 5099 | }, | ||
| 5100 | }; | ||
| 5101 | |||
| 5102 | #undef TPACPI_LEDQ_IBM | ||
| 5103 | #undef TPACPI_LEDQ_LNV | ||
| 5104 | |||
| 4977 | static int __init led_init(struct ibm_init_struct *iibm) | 5105 | static int __init led_init(struct ibm_init_struct *iibm) |
| 4978 | { | 5106 | { |
| 4979 | unsigned int i; | 5107 | unsigned int i; |
| 4980 | int rc; | 5108 | int rc; |
| 5109 | unsigned long useful_leds; | ||
| 4981 | 5110 | ||
| 4982 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); | 5111 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); |
| 4983 | 5112 | ||
| @@ -4999,6 +5128,9 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
| 4999 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", | 5128 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", |
| 5000 | str_supported(led_supported), led_supported); | 5129 | str_supported(led_supported), led_supported); |
| 5001 | 5130 | ||
| 5131 | if (led_supported == TPACPI_LED_NONE) | ||
| 5132 | return 1; | ||
| 5133 | |||
| 5002 | tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, | 5134 | tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, |
| 5003 | GFP_KERNEL); | 5135 | GFP_KERNEL); |
| 5004 | if (!tpacpi_leds) { | 5136 | if (!tpacpi_leds) { |
| @@ -5006,8 +5138,12 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
| 5006 | return -ENOMEM; | 5138 | return -ENOMEM; |
| 5007 | } | 5139 | } |
| 5008 | 5140 | ||
| 5141 | useful_leds = tpacpi_check_quirks(led_useful_qtable, | ||
| 5142 | ARRAY_SIZE(led_useful_qtable)); | ||
| 5143 | |||
| 5009 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { | 5144 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { |
| 5010 | if (!tpacpi_is_led_restricted(i)) { | 5145 | if (!tpacpi_is_led_restricted(i) && |
| 5146 | test_bit(i, &useful_leds)) { | ||
| 5011 | rc = tpacpi_init_led(i); | 5147 | rc = tpacpi_init_led(i); |
| 5012 | if (rc < 0) { | 5148 | if (rc < 0) { |
| 5013 | led_exit(); | 5149 | led_exit(); |
| @@ -5017,12 +5153,11 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
| 5017 | } | 5153 | } |
| 5018 | 5154 | ||
| 5019 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS | 5155 | #ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS |
| 5020 | if (led_supported != TPACPI_LED_NONE) | 5156 | printk(TPACPI_NOTICE |
| 5021 | printk(TPACPI_NOTICE | 5157 | "warning: userspace override of important " |
| 5022 | "warning: userspace override of important " | 5158 | "firmware LEDs is enabled\n"); |
| 5023 | "firmware LEDs is enabled\n"); | ||
| 5024 | #endif | 5159 | #endif |
| 5025 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; | 5160 | return 0; |
| 5026 | } | 5161 | } |
| 5027 | 5162 | ||
| 5028 | #define str_led_status(s) \ | 5163 | #define str_led_status(s) \ |
| @@ -5052,7 +5187,7 @@ static int led_read(char *p) | |||
| 5052 | } | 5187 | } |
| 5053 | 5188 | ||
| 5054 | len += sprintf(p + len, "commands:\t" | 5189 | len += sprintf(p + len, "commands:\t" |
| 5055 | "<led> on, <led> off, <led> blink (<led> is 0-7)\n"); | 5190 | "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); |
| 5056 | 5191 | ||
| 5057 | return len; | 5192 | return len; |
| 5058 | } | 5193 | } |
| @@ -5067,7 +5202,7 @@ static int led_write(char *buf) | |||
| 5067 | return -ENODEV; | 5202 | return -ENODEV; |
| 5068 | 5203 | ||
| 5069 | while ((cmd = next_cmd(&buf))) { | 5204 | while ((cmd = next_cmd(&buf))) { |
| 5070 | if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7) | 5205 | if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 15) |
| 5071 | return -EINVAL; | 5206 | return -EINVAL; |
| 5072 | 5207 | ||
| 5073 | if (strstr(cmd, "off")) { | 5208 | if (strstr(cmd, "off")) { |
| @@ -5101,8 +5236,17 @@ static struct ibm_struct led_driver_data = { | |||
| 5101 | 5236 | ||
| 5102 | TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ | 5237 | TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ |
| 5103 | 5238 | ||
| 5239 | #define TPACPI_BEEP_Q1 0x0001 | ||
| 5240 | |||
| 5241 | static const struct tpacpi_quirk beep_quirk_table[] __initconst = { | ||
| 5242 | TPACPI_Q_IBM('I', 'M', TPACPI_BEEP_Q1), /* 570 */ | ||
| 5243 | TPACPI_Q_IBM('I', 'U', TPACPI_BEEP_Q1), /* 570E - unverified */ | ||
| 5244 | }; | ||
| 5245 | |||
| 5104 | static int __init beep_init(struct ibm_init_struct *iibm) | 5246 | static int __init beep_init(struct ibm_init_struct *iibm) |
| 5105 | { | 5247 | { |
| 5248 | unsigned long quirks; | ||
| 5249 | |||
| 5106 | vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); | 5250 | vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); |
| 5107 | 5251 | ||
| 5108 | TPACPI_ACPIHANDLE_INIT(beep); | 5252 | TPACPI_ACPIHANDLE_INIT(beep); |
| @@ -5110,6 +5254,11 @@ static int __init beep_init(struct ibm_init_struct *iibm) | |||
| 5110 | vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", | 5254 | vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", |
| 5111 | str_supported(beep_handle != NULL)); | 5255 | str_supported(beep_handle != NULL)); |
| 5112 | 5256 | ||
| 5257 | quirks = tpacpi_check_quirks(beep_quirk_table, | ||
| 5258 | ARRAY_SIZE(beep_quirk_table)); | ||
| 5259 | |||
| 5260 | tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1); | ||
| 5261 | |||
| 5113 | return (beep_handle)? 0 : 1; | 5262 | return (beep_handle)? 0 : 1; |
| 5114 | } | 5263 | } |
| 5115 | 5264 | ||
| @@ -5141,8 +5290,15 @@ static int beep_write(char *buf) | |||
| 5141 | /* beep_cmd set */ | 5290 | /* beep_cmd set */ |
| 5142 | } else | 5291 | } else |
| 5143 | return -EINVAL; | 5292 | return -EINVAL; |
| 5144 | if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0)) | 5293 | if (tp_features.beep_needs_two_args) { |
| 5145 | return -EIO; | 5294 | if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", |
| 5295 | beep_cmd, 0)) | ||
| 5296 | return -EIO; | ||
| 5297 | } else { | ||
| 5298 | if (!acpi_evalf(beep_handle, NULL, NULL, "vd", | ||
| 5299 | beep_cmd)) | ||
| 5300 | return -EIO; | ||
| 5301 | } | ||
| 5146 | } | 5302 | } |
| 5147 | 5303 | ||
| 5148 | return 0; | 5304 | return 0; |
| @@ -5569,6 +5725,10 @@ static struct ibm_struct ecdump_driver_data = { | |||
| 5569 | * Bit 3-0: backlight brightness level | 5725 | * Bit 3-0: backlight brightness level |
| 5570 | * | 5726 | * |
| 5571 | * brightness_get_raw returns status data in the HBRV layout | 5727 | * brightness_get_raw returns status data in the HBRV layout |
| 5728 | * | ||
| 5729 | * WARNING: The X61 has been verified to use HBRV for something else, so | ||
| 5730 | * this should be used _only_ on IBM ThinkPads, and maybe with some careful | ||
| 5731 | * testing on the very early *60 Lenovo models... | ||
| 5572 | */ | 5732 | */ |
| 5573 | 5733 | ||
| 5574 | enum { | 5734 | enum { |
| @@ -5869,6 +6029,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
| 5869 | brightness_mode); | 6029 | brightness_mode); |
| 5870 | } | 6030 | } |
| 5871 | 6031 | ||
| 6032 | /* Safety */ | ||
| 6033 | if (thinkpad_id.vendor != PCI_VENDOR_ID_IBM && | ||
| 6034 | (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM || | ||
| 6035 | brightness_mode == TPACPI_BRGHT_MODE_EC)) | ||
| 6036 | return -EINVAL; | ||
| 6037 | |||
| 5872 | if (tpacpi_brightness_get_raw(&b) < 0) | 6038 | if (tpacpi_brightness_get_raw(&b) < 0) |
| 5873 | return 1; | 6039 | return 1; |
| 5874 | 6040 | ||
| @@ -6161,6 +6327,21 @@ static struct ibm_struct volume_driver_data = { | |||
| 6161 | * For firmware bugs, refer to: | 6327 | * For firmware bugs, refer to: |
| 6162 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues | 6328 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues |
| 6163 | * | 6329 | * |
| 6330 | * ---- | ||
| 6331 | * | ||
| 6332 | * ThinkPad EC register 0x31 bit 0 (only on select models) | ||
| 6333 | * | ||
| 6334 | * When bit 0 of EC register 0x31 is zero, the tachometer registers | ||
| 6335 | * show the speed of the main fan. When bit 0 of EC register 0x31 | ||
| 6336 | * is one, the tachometer registers show the speed of the auxiliary | ||
| 6337 | * fan. | ||
| 6338 | * | ||
| 6339 | * Fan control seems to affect both fans, regardless of the state | ||
| 6340 | * of this bit. | ||
| 6341 | * | ||
| 6342 | * So far, only the firmware for the X60/X61 non-tablet versions | ||
| 6343 | * seem to support this (firmware TP-7M). | ||
| 6344 | * | ||
| 6164 | * TPACPI_FAN_WR_ACPI_FANS: | 6345 | * TPACPI_FAN_WR_ACPI_FANS: |
| 6165 | * ThinkPad X31, X40, X41. Not available in the X60. | 6346 | * ThinkPad X31, X40, X41. Not available in the X60. |
| 6166 | * | 6347 | * |
| @@ -6187,6 +6368,8 @@ enum { /* Fan control constants */ | |||
| 6187 | fan_status_offset = 0x2f, /* EC register 0x2f */ | 6368 | fan_status_offset = 0x2f, /* EC register 0x2f */ |
| 6188 | fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) | 6369 | fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) |
| 6189 | * 0x84 must be read before 0x85 */ | 6370 | * 0x84 must be read before 0x85 */ |
| 6371 | fan_select_offset = 0x31, /* EC register 0x31 (Firmware 7M) | ||
| 6372 | bit 0 selects which fan is active */ | ||
| 6190 | 6373 | ||
| 6191 | TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ | 6374 | TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ |
| 6192 | TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ | 6375 | TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ |
| @@ -6249,30 +6432,18 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */ | |||
| 6249 | * We assume 0x07 really means auto mode while this quirk is active, | 6432 | * We assume 0x07 really means auto mode while this quirk is active, |
| 6250 | * as this is far more likely than the ThinkPad being in level 7, | 6433 | * as this is far more likely than the ThinkPad being in level 7, |
| 6251 | * which is only used by the firmware during thermal emergencies. | 6434 | * which is only used by the firmware during thermal emergencies. |
| 6435 | * | ||
| 6436 | * Enable for TP-1Y (T43), TP-78 (R51e), TP-76 (R52), | ||
| 6437 | * TP-70 (T43, R52), which are known to be buggy. | ||
| 6252 | */ | 6438 | */ |
| 6253 | 6439 | ||
| 6254 | static void fan_quirk1_detect(void) | 6440 | static void fan_quirk1_setup(void) |
| 6255 | { | 6441 | { |
| 6256 | /* In some ThinkPads, neither the EC nor the ACPI | ||
| 6257 | * DSDT initialize the HFSP register, and it ends up | ||
| 6258 | * being initially set to 0x07 when it *could* be | ||
| 6259 | * either 0x07 or 0x80. | ||
| 6260 | * | ||
| 6261 | * Enable for TP-1Y (T43), TP-78 (R51e), | ||
| 6262 | * TP-76 (R52), TP-70 (T43, R52), which are known | ||
| 6263 | * to be buggy. */ | ||
| 6264 | if (fan_control_initial_status == 0x07) { | 6442 | if (fan_control_initial_status == 0x07) { |
| 6265 | switch (thinkpad_id.ec_model) { | 6443 | printk(TPACPI_NOTICE |
| 6266 | case 0x5931: /* TP-1Y */ | 6444 | "fan_init: initial fan status is unknown, " |
| 6267 | case 0x3837: /* TP-78 */ | 6445 | "assuming it is in auto mode\n"); |
| 6268 | case 0x3637: /* TP-76 */ | 6446 | tp_features.fan_ctrl_status_undef = 1; |
| 6269 | case 0x3037: /* TP-70 */ | ||
| 6270 | printk(TPACPI_NOTICE | ||
| 6271 | "fan_init: initial fan status is unknown, " | ||
| 6272 | "assuming it is in auto mode\n"); | ||
| 6273 | tp_features.fan_ctrl_status_undef = 1; | ||
| 6274 | ;; | ||
| 6275 | } | ||
| 6276 | } | 6447 | } |
| 6277 | } | 6448 | } |
| 6278 | 6449 | ||
| @@ -6292,6 +6463,38 @@ static void fan_quirk1_handle(u8 *fan_status) | |||
| 6292 | } | 6463 | } |
| 6293 | } | 6464 | } |
| 6294 | 6465 | ||
| 6466 | /* Select main fan on X60/X61, NOOP on others */ | ||
| 6467 | static bool fan_select_fan1(void) | ||
| 6468 | { | ||
| 6469 | if (tp_features.second_fan) { | ||
| 6470 | u8 val; | ||
| 6471 | |||
| 6472 | if (ec_read(fan_select_offset, &val) < 0) | ||
| 6473 | return false; | ||
| 6474 | val &= 0xFEU; | ||
| 6475 | if (ec_write(fan_select_offset, val) < 0) | ||
| 6476 | return false; | ||
| 6477 | } | ||
| 6478 | return true; | ||
| 6479 | } | ||
| 6480 | |||
| 6481 | /* Select secondary fan on X60/X61 */ | ||
| 6482 | static bool fan_select_fan2(void) | ||
| 6483 | { | ||
| 6484 | u8 val; | ||
| 6485 | |||
| 6486 | if (!tp_features.second_fan) | ||
| 6487 | return false; | ||
| 6488 | |||
| 6489 | if (ec_read(fan_select_offset, &val) < 0) | ||
| 6490 | return false; | ||
| 6491 | val |= 0x01U; | ||
| 6492 | if (ec_write(fan_select_offset, val) < 0) | ||
| 6493 | return false; | ||
| 6494 | |||
| 6495 | return true; | ||
| 6496 | } | ||
| 6497 | |||
| 6295 | /* | 6498 | /* |
| 6296 | * Call with fan_mutex held | 6499 | * Call with fan_mutex held |
| 6297 | */ | 6500 | */ |
| @@ -6369,6 +6572,8 @@ static int fan_get_speed(unsigned int *speed) | |||
| 6369 | switch (fan_status_access_mode) { | 6572 | switch (fan_status_access_mode) { |
| 6370 | case TPACPI_FAN_RD_TPEC: | 6573 | case TPACPI_FAN_RD_TPEC: |
| 6371 | /* all except 570, 600e/x, 770e, 770x */ | 6574 | /* all except 570, 600e/x, 770e, 770x */ |
| 6575 | if (unlikely(!fan_select_fan1())) | ||
| 6576 | return -EIO; | ||
| 6372 | if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || | 6577 | if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || |
| 6373 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) | 6578 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) |
| 6374 | return -EIO; | 6579 | return -EIO; |
| @@ -6385,6 +6590,34 @@ static int fan_get_speed(unsigned int *speed) | |||
| 6385 | return 0; | 6590 | return 0; |
| 6386 | } | 6591 | } |
| 6387 | 6592 | ||
| 6593 | static int fan2_get_speed(unsigned int *speed) | ||
| 6594 | { | ||
| 6595 | u8 hi, lo; | ||
| 6596 | bool rc; | ||
| 6597 | |||
| 6598 | switch (fan_status_access_mode) { | ||
| 6599 | case TPACPI_FAN_RD_TPEC: | ||
| 6600 | /* all except 570, 600e/x, 770e, 770x */ | ||
| 6601 | if (unlikely(!fan_select_fan2())) | ||
| 6602 | return -EIO; | ||
| 6603 | rc = !acpi_ec_read(fan_rpm_offset, &lo) || | ||
| 6604 | !acpi_ec_read(fan_rpm_offset + 1, &hi); | ||
| 6605 | fan_select_fan1(); /* play it safe */ | ||
| 6606 | if (rc) | ||
| 6607 | return -EIO; | ||
| 6608 | |||
| 6609 | if (likely(speed)) | ||
| 6610 | *speed = (hi << 8) | lo; | ||
| 6611 | |||
| 6612 | break; | ||
| 6613 | |||
| 6614 | default: | ||
| 6615 | return -ENXIO; | ||
| 6616 | } | ||
| 6617 | |||
| 6618 | return 0; | ||
| 6619 | } | ||
| 6620 | |||
| 6388 | static int fan_set_level(int level) | 6621 | static int fan_set_level(int level) |
| 6389 | { | 6622 | { |
| 6390 | if (!fan_control_allowed) | 6623 | if (!fan_control_allowed) |
| @@ -6790,6 +7023,25 @@ static struct device_attribute dev_attr_fan_fan1_input = | |||
| 6790 | __ATTR(fan1_input, S_IRUGO, | 7023 | __ATTR(fan1_input, S_IRUGO, |
| 6791 | fan_fan1_input_show, NULL); | 7024 | fan_fan1_input_show, NULL); |
| 6792 | 7025 | ||
| 7026 | /* sysfs fan fan2_input ------------------------------------------------ */ | ||
| 7027 | static ssize_t fan_fan2_input_show(struct device *dev, | ||
| 7028 | struct device_attribute *attr, | ||
| 7029 | char *buf) | ||
| 7030 | { | ||
| 7031 | int res; | ||
| 7032 | unsigned int speed; | ||
| 7033 | |||
| 7034 | res = fan2_get_speed(&speed); | ||
| 7035 | if (res < 0) | ||
| 7036 | return res; | ||
| 7037 | |||
| 7038 | return snprintf(buf, PAGE_SIZE, "%u\n", speed); | ||
| 7039 | } | ||
| 7040 | |||
| 7041 | static struct device_attribute dev_attr_fan_fan2_input = | ||
| 7042 | __ATTR(fan2_input, S_IRUGO, | ||
| 7043 | fan_fan2_input_show, NULL); | ||
| 7044 | |||
| 6793 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ | 7045 | /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ |
| 6794 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, | 7046 | static ssize_t fan_fan_watchdog_show(struct device_driver *drv, |
| 6795 | char *buf) | 7047 | char *buf) |
| @@ -6823,6 +7075,7 @@ static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO, | |||
| 6823 | static struct attribute *fan_attributes[] = { | 7075 | static struct attribute *fan_attributes[] = { |
| 6824 | &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, | 7076 | &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, |
| 6825 | &dev_attr_fan_fan1_input.attr, | 7077 | &dev_attr_fan_fan1_input.attr, |
| 7078 | NULL, /* for fan2_input */ | ||
| 6826 | NULL | 7079 | NULL |
| 6827 | }; | 7080 | }; |
| 6828 | 7081 | ||
| @@ -6830,9 +7083,36 @@ static const struct attribute_group fan_attr_group = { | |||
| 6830 | .attrs = fan_attributes, | 7083 | .attrs = fan_attributes, |
| 6831 | }; | 7084 | }; |
| 6832 | 7085 | ||
| 7086 | #define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */ | ||
| 7087 | #define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */ | ||
| 7088 | |||
| 7089 | #define TPACPI_FAN_QI(__id1, __id2, __quirks) \ | ||
| 7090 | { .vendor = PCI_VENDOR_ID_IBM, \ | ||
| 7091 | .bios = TPACPI_MATCH_ANY, \ | ||
| 7092 | .ec = TPID(__id1, __id2), \ | ||
| 7093 | .quirks = __quirks } | ||
| 7094 | |||
| 7095 | #define TPACPI_FAN_QL(__id1, __id2, __quirks) \ | ||
| 7096 | { .vendor = PCI_VENDOR_ID_LENOVO, \ | ||
| 7097 | .bios = TPACPI_MATCH_ANY, \ | ||
| 7098 | .ec = TPID(__id1, __id2), \ | ||
| 7099 | .quirks = __quirks } | ||
| 7100 | |||
| 7101 | static const struct tpacpi_quirk fan_quirk_table[] __initconst = { | ||
| 7102 | TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1), | ||
| 7103 | TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1), | ||
| 7104 | TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1), | ||
| 7105 | TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1), | ||
| 7106 | TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN), | ||
| 7107 | }; | ||
| 7108 | |||
| 7109 | #undef TPACPI_FAN_QL | ||
| 7110 | #undef TPACPI_FAN_QI | ||
| 7111 | |||
| 6833 | static int __init fan_init(struct ibm_init_struct *iibm) | 7112 | static int __init fan_init(struct ibm_init_struct *iibm) |
| 6834 | { | 7113 | { |
| 6835 | int rc; | 7114 | int rc; |
| 7115 | unsigned long quirks; | ||
| 6836 | 7116 | ||
| 6837 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, | 7117 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, |
| 6838 | "initializing fan subdriver\n"); | 7118 | "initializing fan subdriver\n"); |
| @@ -6843,12 +7123,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 6843 | fan_control_commands = 0; | 7123 | fan_control_commands = 0; |
| 6844 | fan_watchdog_maxinterval = 0; | 7124 | fan_watchdog_maxinterval = 0; |
| 6845 | tp_features.fan_ctrl_status_undef = 0; | 7125 | tp_features.fan_ctrl_status_undef = 0; |
| 7126 | tp_features.second_fan = 0; | ||
| 6846 | fan_control_desired_level = 7; | 7127 | fan_control_desired_level = 7; |
| 6847 | 7128 | ||
| 6848 | TPACPI_ACPIHANDLE_INIT(fans); | 7129 | TPACPI_ACPIHANDLE_INIT(fans); |
| 6849 | TPACPI_ACPIHANDLE_INIT(gfan); | 7130 | TPACPI_ACPIHANDLE_INIT(gfan); |
| 6850 | TPACPI_ACPIHANDLE_INIT(sfan); | 7131 | TPACPI_ACPIHANDLE_INIT(sfan); |
| 6851 | 7132 | ||
| 7133 | quirks = tpacpi_check_quirks(fan_quirk_table, | ||
| 7134 | ARRAY_SIZE(fan_quirk_table)); | ||
| 7135 | |||
| 6852 | if (gfan_handle) { | 7136 | if (gfan_handle) { |
| 6853 | /* 570, 600e/x, 770e, 770x */ | 7137 | /* 570, 600e/x, 770e, 770x */ |
| 6854 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; | 7138 | fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; |
| @@ -6858,7 +7142,13 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 6858 | if (likely(acpi_ec_read(fan_status_offset, | 7142 | if (likely(acpi_ec_read(fan_status_offset, |
| 6859 | &fan_control_initial_status))) { | 7143 | &fan_control_initial_status))) { |
| 6860 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; | 7144 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; |
| 6861 | fan_quirk1_detect(); | 7145 | if (quirks & TPACPI_FAN_Q1) |
| 7146 | fan_quirk1_setup(); | ||
| 7147 | if (quirks & TPACPI_FAN_2FAN) { | ||
| 7148 | tp_features.second_fan = 1; | ||
| 7149 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, | ||
| 7150 | "secondary fan support enabled\n"); | ||
| 7151 | } | ||
| 6862 | } else { | 7152 | } else { |
| 6863 | printk(TPACPI_ERR | 7153 | printk(TPACPI_ERR |
| 6864 | "ThinkPad ACPI EC access misbehaving, " | 7154 | "ThinkPad ACPI EC access misbehaving, " |
| @@ -6914,6 +7204,11 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 6914 | 7204 | ||
| 6915 | if (fan_status_access_mode != TPACPI_FAN_NONE || | 7205 | if (fan_status_access_mode != TPACPI_FAN_NONE || |
| 6916 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { | 7206 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { |
| 7207 | if (tp_features.second_fan) { | ||
| 7208 | /* attach second fan tachometer */ | ||
| 7209 | fan_attributes[ARRAY_SIZE(fan_attributes)-2] = | ||
| 7210 | &dev_attr_fan_fan2_input.attr; | ||
| 7211 | } | ||
| 6917 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, | 7212 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
| 6918 | &fan_attr_group); | 7213 | &fan_attr_group); |
| 6919 | if (rc < 0) | 7214 | if (rc < 0) |
| @@ -7385,6 +7680,24 @@ err_out: | |||
| 7385 | 7680 | ||
| 7386 | /* Probing */ | 7681 | /* Probing */ |
| 7387 | 7682 | ||
| 7683 | static bool __pure __init tpacpi_is_fw_digit(const char c) | ||
| 7684 | { | ||
| 7685 | return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); | ||
| 7686 | } | ||
| 7687 | |||
| 7688 | /* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */ | ||
| 7689 | static bool __pure __init tpacpi_is_valid_fw_id(const char* const s, | ||
| 7690 | const char t) | ||
| 7691 | { | ||
| 7692 | return s && strlen(s) >= 8 && | ||
| 7693 | tpacpi_is_fw_digit(s[0]) && | ||
| 7694 | tpacpi_is_fw_digit(s[1]) && | ||
| 7695 | s[2] == t && s[3] == 'T' && | ||
| 7696 | tpacpi_is_fw_digit(s[4]) && | ||
| 7697 | tpacpi_is_fw_digit(s[5]) && | ||
| 7698 | s[6] == 'W' && s[7] == 'W'; | ||
| 7699 | } | ||
| 7700 | |||
| 7388 | /* returns 0 - probe ok, or < 0 - probe error. | 7701 | /* returns 0 - probe ok, or < 0 - probe error. |
| 7389 | * Probe ok doesn't mean thinkpad found. | 7702 | * Probe ok doesn't mean thinkpad found. |
| 7390 | * On error, kfree() cleanup on tp->* is not performed, caller must do it */ | 7703 | * On error, kfree() cleanup on tp->* is not performed, caller must do it */ |
| @@ -7411,10 +7724,15 @@ static int __must_check __init get_thinkpad_model_data( | |||
| 7411 | tp->bios_version_str = kstrdup(s, GFP_KERNEL); | 7724 | tp->bios_version_str = kstrdup(s, GFP_KERNEL); |
| 7412 | if (s && !tp->bios_version_str) | 7725 | if (s && !tp->bios_version_str) |
| 7413 | return -ENOMEM; | 7726 | return -ENOMEM; |
| 7414 | if (!tp->bios_version_str) | 7727 | |
| 7728 | /* Really ancient ThinkPad 240X will fail this, which is fine */ | ||
| 7729 | if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E')) | ||
| 7415 | return 0; | 7730 | return 0; |
| 7731 | |||
| 7416 | tp->bios_model = tp->bios_version_str[0] | 7732 | tp->bios_model = tp->bios_version_str[0] |
| 7417 | | (tp->bios_version_str[1] << 8); | 7733 | | (tp->bios_version_str[1] << 8); |
| 7734 | tp->bios_release = (tp->bios_version_str[4] << 8) | ||
| 7735 | | tp->bios_version_str[5]; | ||
| 7418 | 7736 | ||
| 7419 | /* | 7737 | /* |
| 7420 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 7738 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
| @@ -7433,8 +7751,21 @@ static int __must_check __init get_thinkpad_model_data( | |||
| 7433 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | 7751 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); |
| 7434 | if (!tp->ec_version_str) | 7752 | if (!tp->ec_version_str) |
| 7435 | return -ENOMEM; | 7753 | return -ENOMEM; |
| 7436 | tp->ec_model = ec_fw_string[0] | 7754 | |
| 7437 | | (ec_fw_string[1] << 8); | 7755 | if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) { |
| 7756 | tp->ec_model = ec_fw_string[0] | ||
| 7757 | | (ec_fw_string[1] << 8); | ||
| 7758 | tp->ec_release = (ec_fw_string[4] << 8) | ||
| 7759 | | ec_fw_string[5]; | ||
| 7760 | } else { | ||
| 7761 | printk(TPACPI_NOTICE | ||
| 7762 | "ThinkPad firmware release %s " | ||
| 7763 | "doesn't match the known patterns\n", | ||
| 7764 | ec_fw_string); | ||
| 7765 | printk(TPACPI_NOTICE | ||
| 7766 | "please report this to %s\n", | ||
| 7767 | TPACPI_MAIL); | ||
| 7768 | } | ||
| 7438 | break; | 7769 | break; |
| 7439 | } | 7770 | } |
| 7440 | } | 7771 | } |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 7f207f335bec..ef3a2cd3a7a0 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -287,6 +287,25 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | |||
| 287 | ACPI_DECODE_16); | 287 | ACPI_DECODE_16); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, | ||
| 291 | struct acpi_resource *res) | ||
| 292 | { | ||
| 293 | struct acpi_resource_extended_address64 *p = &res->data.ext_address64; | ||
| 294 | |||
| 295 | if (p->producer_consumer == ACPI_PRODUCER) | ||
| 296 | return; | ||
| 297 | |||
| 298 | if (p->resource_type == ACPI_MEMORY_RANGE) | ||
| 299 | pnpacpi_parse_allocated_memresource(dev, | ||
| 300 | p->minimum, p->address_length, | ||
| 301 | p->info.mem.write_protect); | ||
| 302 | else if (p->resource_type == ACPI_IO_RANGE) | ||
| 303 | pnpacpi_parse_allocated_ioresource(dev, | ||
| 304 | p->minimum, p->address_length, | ||
| 305 | p->granularity == 0xfff ? ACPI_DECODE_10 : | ||
| 306 | ACPI_DECODE_16); | ||
| 307 | } | ||
| 308 | |||
| 290 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | 309 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, |
| 291 | void *data) | 310 | void *data) |
| 292 | { | 311 | { |
| @@ -400,8 +419,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
| 400 | break; | 419 | break; |
| 401 | 420 | ||
| 402 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 421 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
| 403 | if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) | 422 | pnpacpi_parse_allocated_ext_address_space(dev, res); |
| 404 | return AE_OK; | ||
| 405 | break; | 423 | break; |
| 406 | 424 | ||
| 407 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 425 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| @@ -630,6 +648,28 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | |||
| 630 | IORESOURCE_IO_FIXED); | 648 | IORESOURCE_IO_FIXED); |
| 631 | } | 649 | } |
| 632 | 650 | ||
| 651 | static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, | ||
| 652 | unsigned int option_flags, | ||
| 653 | struct acpi_resource *r) | ||
| 654 | { | ||
| 655 | struct acpi_resource_extended_address64 *p = &r->data.ext_address64; | ||
| 656 | unsigned char flags = 0; | ||
| 657 | |||
| 658 | if (p->address_length == 0) | ||
| 659 | return; | ||
| 660 | |||
| 661 | if (p->resource_type == ACPI_MEMORY_RANGE) { | ||
| 662 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) | ||
| 663 | flags = IORESOURCE_MEM_WRITEABLE; | ||
| 664 | pnp_register_mem_resource(dev, option_flags, p->minimum, | ||
| 665 | p->minimum, 0, p->address_length, | ||
| 666 | flags); | ||
| 667 | } else if (p->resource_type == ACPI_IO_RANGE) | ||
| 668 | pnp_register_port_resource(dev, option_flags, p->minimum, | ||
| 669 | p->minimum, 0, p->address_length, | ||
| 670 | IORESOURCE_IO_FIXED); | ||
| 671 | } | ||
| 672 | |||
| 633 | struct acpipnp_parse_option_s { | 673 | struct acpipnp_parse_option_s { |
| 634 | struct pnp_dev *dev; | 674 | struct pnp_dev *dev; |
| 635 | unsigned int option_flags; | 675 | unsigned int option_flags; |
| @@ -711,6 +751,7 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
| 711 | break; | 751 | break; |
| 712 | 752 | ||
| 713 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 753 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
| 754 | pnpacpi_parse_ext_address_option(dev, option_flags, res); | ||
| 714 | break; | 755 | break; |
| 715 | 756 | ||
| 716 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 757 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| @@ -765,6 +806,7 @@ static int pnpacpi_supported_resource(struct acpi_resource *res) | |||
| 765 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 806 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
| 766 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 807 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
| 767 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 808 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
| 809 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | ||
| 768 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 810 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| 769 | return 1; | 811 | return 1; |
| 770 | } | 812 | } |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 33da1127992a..7eda34838bfe 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
| @@ -82,6 +82,14 @@ config BATTERY_DA9030 | |||
| 82 | Say Y here to enable support for batteries charger integrated into | 82 | Say Y here to enable support for batteries charger integrated into |
| 83 | DA9030 PMIC. | 83 | DA9030 PMIC. |
| 84 | 84 | ||
| 85 | config BATTERY_MAX17040 | ||
| 86 | tristate "Maxim MAX17040 Fuel Gauge" | ||
| 87 | depends on I2C | ||
| 88 | help | ||
| 89 | MAX17040 is fuel-gauge systems for lithium-ion (Li+) batteries | ||
| 90 | in handheld and portable equipment. The MAX17040 is configured | ||
| 91 | to operate with a single lithium cell | ||
| 92 | |||
| 85 | config CHARGER_PCF50633 | 93 | config CHARGER_PCF50633 |
| 86 | tristate "NXP PCF50633 MBC" | 94 | tristate "NXP PCF50633 MBC" |
| 87 | depends on MFD_PCF50633 | 95 | depends on MFD_PCF50633 |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 2fcf41d13e5c..daf3179689aa 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
| @@ -25,4 +25,5 @@ obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o | |||
| 25 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o | 25 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o |
| 26 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | 26 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o |
| 27 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 27 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
| 28 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o \ No newline at end of file | 28 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o |
| 29 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | ||
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c index 1662bb0f23a5..3364198134a1 100644 --- a/drivers/power/da9030_battery.c +++ b/drivers/power/da9030_battery.c | |||
| @@ -22,8 +22,6 @@ | |||
| 22 | #include <linux/debugfs.h> | 22 | #include <linux/debugfs.h> |
| 23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
| 24 | 24 | ||
| 25 | #define DA9030_STATUS_CHDET (1 << 3) | ||
| 26 | |||
| 27 | #define DA9030_FAULT_LOG 0x0a | 25 | #define DA9030_FAULT_LOG 0x0a |
| 28 | #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) | 26 | #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) |
| 29 | #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4) | 27 | #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4) |
| @@ -244,6 +242,8 @@ static void da9030_set_charge(struct da9030_charger *charger, int on) | |||
| 244 | } | 242 | } |
| 245 | 243 | ||
| 246 | da903x_write(charger->master, DA9030_CHARGE_CONTROL, val); | 244 | da903x_write(charger->master, DA9030_CHARGE_CONTROL, val); |
| 245 | |||
| 246 | power_supply_changed(&charger->psy); | ||
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | static void da9030_charger_check_state(struct da9030_charger *charger) | 249 | static void da9030_charger_check_state(struct da9030_charger *charger) |
| @@ -258,6 +258,12 @@ static void da9030_charger_check_state(struct da9030_charger *charger) | |||
| 258 | da9030_set_charge(charger, 1); | 258 | da9030_set_charge(charger, 1); |
| 259 | } | 259 | } |
| 260 | } else { | 260 | } else { |
| 261 | /* Charger has been pulled out */ | ||
| 262 | if (!charger->chdet) { | ||
| 263 | da9030_set_charge(charger, 0); | ||
| 264 | return; | ||
| 265 | } | ||
| 266 | |||
| 261 | if (charger->adc.vbat_res >= | 267 | if (charger->adc.vbat_res >= |
| 262 | charger->thresholds.vbat_charge_stop) { | 268 | charger->thresholds.vbat_charge_stop) { |
| 263 | da9030_set_charge(charger, 0); | 269 | da9030_set_charge(charger, 0); |
| @@ -395,13 +401,11 @@ static int da9030_battery_event(struct notifier_block *nb, unsigned long event, | |||
| 395 | { | 401 | { |
| 396 | struct da9030_charger *charger = | 402 | struct da9030_charger *charger = |
| 397 | container_of(nb, struct da9030_charger, nb); | 403 | container_of(nb, struct da9030_charger, nb); |
| 398 | int status; | ||
| 399 | 404 | ||
| 400 | switch (event) { | 405 | switch (event) { |
| 401 | case DA9030_EVENT_CHDET: | 406 | case DA9030_EVENT_CHDET: |
| 402 | status = da903x_query_status(charger->master, | 407 | cancel_delayed_work_sync(&charger->work); |
| 403 | DA9030_STATUS_CHDET); | 408 | schedule_work(&charger->work.work); |
| 404 | da9030_set_charge(charger, status); | ||
| 405 | break; | 409 | break; |
| 406 | case DA9030_EVENT_VBATMON: | 410 | case DA9030_EVENT_VBATMON: |
| 407 | da9030_battery_vbat_event(charger); | 411 | da9030_battery_vbat_event(charger); |
| @@ -565,7 +569,8 @@ static int da9030_battery_remove(struct platform_device *dev) | |||
| 565 | da903x_unregister_notifier(charger->master, &charger->nb, | 569 | da903x_unregister_notifier(charger->master, &charger->nb, |
| 566 | DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | | 570 | DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | |
| 567 | DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); | 571 | DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); |
| 568 | cancel_delayed_work(&charger->work); | 572 | cancel_delayed_work_sync(&charger->work); |
| 573 | da9030_set_charge(charger, 0); | ||
| 569 | power_supply_unregister(&charger->psy); | 574 | power_supply_unregister(&charger->psy); |
| 570 | 575 | ||
| 571 | kfree(charger); | 576 | kfree(charger); |
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index a52d4a11652d..520b5c49ff30 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c | |||
| @@ -62,6 +62,10 @@ static unsigned int cache_time = 1000; | |||
| 62 | module_param(cache_time, uint, 0644); | 62 | module_param(cache_time, uint, 0644); |
| 63 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 63 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
| 64 | 64 | ||
| 65 | static unsigned int pmod_enabled; | ||
| 66 | module_param(pmod_enabled, bool, 0644); | ||
| 67 | MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit"); | ||
| 68 | |||
| 65 | /* Some batteries have their rated capacity stored a N * 10 mAh, while | 69 | /* Some batteries have their rated capacity stored a N * 10 mAh, while |
| 66 | * others use an index into this table. */ | 70 | * others use an index into this table. */ |
| 67 | static int rated_capacities[] = { | 71 | static int rated_capacities[] = { |
| @@ -259,6 +263,17 @@ static void ds2760_battery_update_status(struct ds2760_device_info *di) | |||
| 259 | power_supply_changed(&di->bat); | 263 | power_supply_changed(&di->bat); |
| 260 | } | 264 | } |
| 261 | 265 | ||
| 266 | static void ds2760_battery_write_status(struct ds2760_device_info *di, | ||
| 267 | char status) | ||
| 268 | { | ||
| 269 | if (status == di->raw[DS2760_STATUS_REG]) | ||
| 270 | return; | ||
| 271 | |||
| 272 | w1_ds2760_write(di->w1_dev, &status, DS2760_STATUS_WRITE_REG, 1); | ||
| 273 | w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1); | ||
| 274 | w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1); | ||
| 275 | } | ||
| 276 | |||
| 262 | static void ds2760_battery_work(struct work_struct *work) | 277 | static void ds2760_battery_work(struct work_struct *work) |
| 263 | { | 278 | { |
| 264 | struct ds2760_device_info *di = container_of(work, | 279 | struct ds2760_device_info *di = container_of(work, |
| @@ -342,9 +357,9 @@ static enum power_supply_property ds2760_battery_props[] = { | |||
| 342 | 357 | ||
| 343 | static int ds2760_battery_probe(struct platform_device *pdev) | 358 | static int ds2760_battery_probe(struct platform_device *pdev) |
| 344 | { | 359 | { |
| 360 | char status; | ||
| 345 | int retval = 0; | 361 | int retval = 0; |
| 346 | struct ds2760_device_info *di; | 362 | struct ds2760_device_info *di; |
| 347 | struct ds2760_platform_data *pdata; | ||
| 348 | 363 | ||
| 349 | di = kzalloc(sizeof(*di), GFP_KERNEL); | 364 | di = kzalloc(sizeof(*di), GFP_KERNEL); |
| 350 | if (!di) { | 365 | if (!di) { |
| @@ -354,14 +369,13 @@ static int ds2760_battery_probe(struct platform_device *pdev) | |||
| 354 | 369 | ||
| 355 | platform_set_drvdata(pdev, di); | 370 | platform_set_drvdata(pdev, di); |
| 356 | 371 | ||
| 357 | pdata = pdev->dev.platform_data; | 372 | di->dev = &pdev->dev; |
| 358 | di->dev = &pdev->dev; | 373 | di->w1_dev = pdev->dev.parent; |
| 359 | di->w1_dev = pdev->dev.parent; | 374 | di->bat.name = dev_name(&pdev->dev); |
| 360 | di->bat.name = dev_name(&pdev->dev); | 375 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
| 361 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 376 | di->bat.properties = ds2760_battery_props; |
| 362 | di->bat.properties = ds2760_battery_props; | 377 | di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props); |
| 363 | di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props); | 378 | di->bat.get_property = ds2760_battery_get_property; |
| 364 | di->bat.get_property = ds2760_battery_get_property; | ||
| 365 | di->bat.external_power_changed = | 379 | di->bat.external_power_changed = |
| 366 | ds2760_battery_external_power_changed; | 380 | ds2760_battery_external_power_changed; |
| 367 | 381 | ||
| @@ -373,6 +387,16 @@ static int ds2760_battery_probe(struct platform_device *pdev) | |||
| 373 | goto batt_failed; | 387 | goto batt_failed; |
| 374 | } | 388 | } |
| 375 | 389 | ||
| 390 | /* enable sleep mode feature */ | ||
| 391 | ds2760_battery_read_status(di); | ||
| 392 | status = di->raw[DS2760_STATUS_REG]; | ||
| 393 | if (pmod_enabled) | ||
| 394 | status |= DS2760_STATUS_PMOD; | ||
| 395 | else | ||
| 396 | status &= ~DS2760_STATUS_PMOD; | ||
| 397 | |||
| 398 | ds2760_battery_write_status(di, status); | ||
| 399 | |||
| 376 | INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work); | 400 | INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work); |
| 377 | di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); | 401 | di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); |
| 378 | if (!di->monitor_wqueue) { | 402 | if (!di->monitor_wqueue) { |
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c new file mode 100644 index 000000000000..87b98bf27ae1 --- /dev/null +++ b/drivers/power/max17040_battery.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | /* | ||
| 2 | * max17040_battery.c | ||
| 3 | * fuel-gauge systems for lithium-ion (Li+) batteries | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009 Samsung Electronics | ||
| 6 | * Minkyu Kang <mk7.kang@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/i2c.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/power_supply.h> | ||
| 21 | #include <linux/max17040_battery.h> | ||
| 22 | |||
| 23 | #define MAX17040_VCELL_MSB 0x02 | ||
| 24 | #define MAX17040_VCELL_LSB 0x03 | ||
| 25 | #define MAX17040_SOC_MSB 0x04 | ||
| 26 | #define MAX17040_SOC_LSB 0x05 | ||
| 27 | #define MAX17040_MODE_MSB 0x06 | ||
| 28 | #define MAX17040_MODE_LSB 0x07 | ||
| 29 | #define MAX17040_VER_MSB 0x08 | ||
| 30 | #define MAX17040_VER_LSB 0x09 | ||
| 31 | #define MAX17040_RCOMP_MSB 0x0C | ||
| 32 | #define MAX17040_RCOMP_LSB 0x0D | ||
| 33 | #define MAX17040_CMD_MSB 0xFE | ||
| 34 | #define MAX17040_CMD_LSB 0xFF | ||
| 35 | |||
| 36 | #define MAX17040_DELAY 1000 | ||
| 37 | #define MAX17040_BATTERY_FULL 95 | ||
| 38 | |||
| 39 | struct max17040_chip { | ||
| 40 | struct i2c_client *client; | ||
| 41 | struct delayed_work work; | ||
| 42 | struct power_supply battery; | ||
| 43 | struct max17040_platform_data *pdata; | ||
| 44 | |||
| 45 | /* State Of Connect */ | ||
| 46 | int online; | ||
| 47 | /* battery voltage */ | ||
| 48 | int vcell; | ||
| 49 | /* battery capacity */ | ||
| 50 | int soc; | ||
| 51 | /* State Of Charge */ | ||
| 52 | int status; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static int max17040_get_property(struct power_supply *psy, | ||
| 56 | enum power_supply_property psp, | ||
| 57 | union power_supply_propval *val) | ||
| 58 | { | ||
| 59 | struct max17040_chip *chip = container_of(psy, | ||
| 60 | struct max17040_chip, battery); | ||
| 61 | |||
| 62 | switch (psp) { | ||
| 63 | case POWER_SUPPLY_PROP_STATUS: | ||
| 64 | val->intval = chip->status; | ||
| 65 | break; | ||
| 66 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 67 | val->intval = chip->online; | ||
| 68 | break; | ||
| 69 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
| 70 | val->intval = chip->vcell; | ||
| 71 | break; | ||
| 72 | case POWER_SUPPLY_PROP_CAPACITY: | ||
| 73 | val->intval = chip->soc; | ||
| 74 | break; | ||
| 75 | default: | ||
| 76 | return -EINVAL; | ||
| 77 | } | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int max17040_write_reg(struct i2c_client *client, int reg, u8 value) | ||
| 82 | { | ||
| 83 | int ret; | ||
| 84 | |||
| 85 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
| 86 | |||
| 87 | if (ret < 0) | ||
| 88 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
| 89 | |||
| 90 | return ret; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int max17040_read_reg(struct i2c_client *client, int reg) | ||
| 94 | { | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | ret = i2c_smbus_read_byte_data(client, reg); | ||
| 98 | |||
| 99 | if (ret < 0) | ||
| 100 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
| 101 | |||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void max17040_reset(struct i2c_client *client) | ||
| 106 | { | ||
| 107 | max17040_write_reg(client, MAX17040_CMD_MSB, 0x54); | ||
| 108 | max17040_write_reg(client, MAX17040_CMD_LSB, 0x00); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void max17040_get_vcell(struct i2c_client *client) | ||
| 112 | { | ||
| 113 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 114 | u8 msb; | ||
| 115 | u8 lsb; | ||
| 116 | |||
| 117 | msb = max17040_read_reg(client, MAX17040_VCELL_MSB); | ||
| 118 | lsb = max17040_read_reg(client, MAX17040_VCELL_LSB); | ||
| 119 | |||
| 120 | chip->vcell = (msb << 4) + (lsb >> 4); | ||
| 121 | } | ||
| 122 | |||
| 123 | static void max17040_get_soc(struct i2c_client *client) | ||
| 124 | { | ||
| 125 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 126 | u8 msb; | ||
| 127 | u8 lsb; | ||
| 128 | |||
| 129 | msb = max17040_read_reg(client, MAX17040_SOC_MSB); | ||
| 130 | lsb = max17040_read_reg(client, MAX17040_SOC_LSB); | ||
| 131 | |||
| 132 | chip->soc = msb; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void max17040_get_version(struct i2c_client *client) | ||
| 136 | { | ||
| 137 | u8 msb; | ||
| 138 | u8 lsb; | ||
| 139 | |||
| 140 | msb = max17040_read_reg(client, MAX17040_VER_MSB); | ||
| 141 | lsb = max17040_read_reg(client, MAX17040_VER_LSB); | ||
| 142 | |||
| 143 | dev_info(&client->dev, "MAX17040 Fuel-Gauge Ver %d%d\n", msb, lsb); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void max17040_get_online(struct i2c_client *client) | ||
| 147 | { | ||
| 148 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 149 | |||
| 150 | if (chip->pdata->battery_online) | ||
| 151 | chip->online = chip->pdata->battery_online(); | ||
| 152 | else | ||
| 153 | chip->online = 1; | ||
| 154 | } | ||
| 155 | |||
| 156 | static void max17040_get_status(struct i2c_client *client) | ||
| 157 | { | ||
| 158 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 159 | |||
| 160 | if (!chip->pdata->charger_online || !chip->pdata->charger_enable) { | ||
| 161 | chip->status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
| 162 | return; | ||
| 163 | } | ||
| 164 | |||
| 165 | if (chip->pdata->charger_online()) { | ||
| 166 | if (chip->pdata->charger_enable()) | ||
| 167 | chip->status = POWER_SUPPLY_STATUS_CHARGING; | ||
| 168 | else | ||
| 169 | chip->status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
| 170 | } else { | ||
| 171 | chip->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (chip->soc > MAX17040_BATTERY_FULL) | ||
| 175 | chip->status = POWER_SUPPLY_STATUS_FULL; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void max17040_work(struct work_struct *work) | ||
| 179 | { | ||
| 180 | struct max17040_chip *chip; | ||
| 181 | |||
| 182 | chip = container_of(work, struct max17040_chip, work.work); | ||
| 183 | |||
| 184 | max17040_get_vcell(chip->client); | ||
| 185 | max17040_get_soc(chip->client); | ||
| 186 | max17040_get_online(chip->client); | ||
| 187 | max17040_get_status(chip->client); | ||
| 188 | |||
| 189 | schedule_delayed_work(&chip->work, MAX17040_DELAY); | ||
| 190 | } | ||
| 191 | |||
| 192 | static enum power_supply_property max17040_battery_props[] = { | ||
| 193 | POWER_SUPPLY_PROP_STATUS, | ||
| 194 | POWER_SUPPLY_PROP_ONLINE, | ||
| 195 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 196 | POWER_SUPPLY_PROP_CAPACITY, | ||
| 197 | }; | ||
| 198 | |||
| 199 | static int __devinit max17040_probe(struct i2c_client *client, | ||
| 200 | const struct i2c_device_id *id) | ||
| 201 | { | ||
| 202 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
| 203 | struct max17040_chip *chip; | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | ||
| 207 | return -EIO; | ||
| 208 | |||
| 209 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 210 | if (!chip) | ||
| 211 | return -ENOMEM; | ||
| 212 | |||
| 213 | chip->client = client; | ||
| 214 | chip->pdata = client->dev.platform_data; | ||
| 215 | |||
| 216 | i2c_set_clientdata(client, chip); | ||
| 217 | |||
| 218 | chip->battery.name = "battery"; | ||
| 219 | chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 220 | chip->battery.get_property = max17040_get_property; | ||
| 221 | chip->battery.properties = max17040_battery_props; | ||
| 222 | chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props); | ||
| 223 | |||
| 224 | ret = power_supply_register(&client->dev, &chip->battery); | ||
| 225 | if (ret) { | ||
| 226 | dev_err(&client->dev, "failed: power supply register\n"); | ||
| 227 | i2c_set_clientdata(client, NULL); | ||
| 228 | kfree(chip); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | max17040_reset(client); | ||
| 233 | max17040_get_version(client); | ||
| 234 | |||
| 235 | INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17040_work); | ||
| 236 | schedule_delayed_work(&chip->work, MAX17040_DELAY); | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | static int __devexit max17040_remove(struct i2c_client *client) | ||
| 242 | { | ||
| 243 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 244 | |||
| 245 | power_supply_unregister(&chip->battery); | ||
| 246 | cancel_delayed_work(&chip->work); | ||
| 247 | i2c_set_clientdata(client, NULL); | ||
| 248 | kfree(chip); | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | #ifdef CONFIG_PM | ||
| 253 | |||
| 254 | static int max17040_suspend(struct i2c_client *client, | ||
| 255 | pm_message_t state) | ||
| 256 | { | ||
| 257 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 258 | |||
| 259 | cancel_delayed_work(&chip->work); | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int max17040_resume(struct i2c_client *client) | ||
| 264 | { | ||
| 265 | struct max17040_chip *chip = i2c_get_clientdata(client); | ||
| 266 | |||
| 267 | schedule_delayed_work(&chip->work, MAX17040_DELAY); | ||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 271 | #else | ||
| 272 | |||
| 273 | #define max17040_suspend NULL | ||
| 274 | #define max17040_resume NULL | ||
| 275 | |||
| 276 | #endif /* CONFIG_PM */ | ||
| 277 | |||
| 278 | static const struct i2c_device_id max17040_id[] = { | ||
| 279 | { "max17040", 0 }, | ||
| 280 | { } | ||
| 281 | }; | ||
| 282 | MODULE_DEVICE_TABLE(i2c, max17040_id); | ||
| 283 | |||
| 284 | static struct i2c_driver max17040_i2c_driver = { | ||
| 285 | .driver = { | ||
| 286 | .name = "max17040", | ||
| 287 | }, | ||
| 288 | .probe = max17040_probe, | ||
| 289 | .remove = __devexit_p(max17040_remove), | ||
| 290 | .suspend = max17040_suspend, | ||
| 291 | .resume = max17040_resume, | ||
| 292 | .id_table = max17040_id, | ||
| 293 | }; | ||
| 294 | |||
| 295 | static int __init max17040_init(void) | ||
| 296 | { | ||
| 297 | return i2c_add_driver(&max17040_i2c_driver); | ||
| 298 | } | ||
| 299 | module_init(max17040_init); | ||
| 300 | |||
| 301 | static void __exit max17040_exit(void) | ||
| 302 | { | ||
| 303 | i2c_del_driver(&max17040_i2c_driver); | ||
| 304 | } | ||
| 305 | module_exit(max17040_exit); | ||
| 306 | |||
| 307 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
| 308 | MODULE_DESCRIPTION("MAX17040 Fuel Gauge"); | ||
| 309 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index 8bde92126d34..b787335a8419 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c | |||
| @@ -33,14 +33,14 @@ static enum power_supply_property *prop; | |||
| 33 | 33 | ||
| 34 | static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) | 34 | static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) |
| 35 | { | 35 | { |
| 36 | return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, | 36 | return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), |
| 37 | pdata->batt_aux) * pdata->batt_mult / | 37 | pdata->batt_aux) * pdata->batt_mult / |
| 38 | pdata->batt_div; | 38 | pdata->batt_div; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) | 41 | static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) |
| 42 | { | 42 | { |
| 43 | return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, | 43 | return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), |
| 44 | pdata->temp_aux) * pdata->temp_mult / | 44 | pdata->temp_aux) * pdata->temp_mult / |
| 45 | pdata->temp_div; | 45 | pdata->temp_div; |
| 46 | } | 46 | } |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index aafd3e6ebb0d..a118eb0f1e67 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
| 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
| 4 | * | 4 | * |
| 5 | * Copyright 2004-2008 Analog Devices Inc. | 5 | * Copyright 2004-2009 Analog Devices Inc. |
| 6 | * | 6 | * |
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
| 8 | * | 8 | * |
| @@ -363,7 +363,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
| 363 | struct bfin_rtc *rtc; | 363 | struct bfin_rtc *rtc; |
| 364 | struct device *dev = &pdev->dev; | 364 | struct device *dev = &pdev->dev; |
| 365 | int ret = 0; | 365 | int ret = 0; |
| 366 | unsigned long timeout; | 366 | unsigned long timeout = jiffies + HZ; |
| 367 | 367 | ||
| 368 | dev_dbg_stamp(dev); | 368 | dev_dbg_stamp(dev); |
| 369 | 369 | ||
| @@ -374,32 +374,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
| 374 | platform_set_drvdata(pdev, rtc); | 374 | platform_set_drvdata(pdev, rtc); |
| 375 | device_init_wakeup(dev, 1); | 375 | device_init_wakeup(dev, 1); |
| 376 | 376 | ||
| 377 | /* Register our RTC with the RTC framework */ | ||
| 378 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, | ||
| 379 | THIS_MODULE); | ||
| 380 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
| 381 | ret = PTR_ERR(rtc->rtc_dev); | ||
| 382 | goto err; | ||
| 383 | } | ||
| 384 | |||
| 377 | /* Grab the IRQ and init the hardware */ | 385 | /* Grab the IRQ and init the hardware */ |
| 378 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); | 386 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); |
| 379 | if (unlikely(ret)) | 387 | if (unlikely(ret)) |
| 380 | goto err; | 388 | goto err_reg; |
| 381 | /* sometimes the bootloader touched things, but the write complete was not | 389 | /* sometimes the bootloader touched things, but the write complete was not |
| 382 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... | 390 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
| 383 | */ | 391 | */ |
| 384 | timeout = jiffies + HZ; | ||
| 385 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | 392 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) |
| 386 | if (time_after(jiffies, timeout)) | 393 | if (time_after(jiffies, timeout)) |
| 387 | break; | 394 | break; |
| 388 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); | 395 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
| 389 | bfin_write_RTC_SWCNT(0); | 396 | bfin_write_RTC_SWCNT(0); |
| 390 | 397 | ||
| 391 | /* Register our RTC with the RTC framework */ | ||
| 392 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); | ||
| 393 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
| 394 | ret = PTR_ERR(rtc->rtc_dev); | ||
| 395 | goto err_irq; | ||
| 396 | } | ||
| 397 | |||
| 398 | return 0; | 398 | return 0; |
| 399 | 399 | ||
| 400 | err_irq: | 400 | err_reg: |
| 401 | free_irq(IRQ_RTC, dev); | 401 | rtc_device_unregister(rtc->rtc_dev); |
| 402 | err: | 402 | err: |
| 403 | kfree(rtc); | 403 | kfree(rtc); |
| 404 | return ret; | 404 | return ret; |
| 405 | } | 405 | } |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 32b27739ec2a..713f7bf5afb3 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
| @@ -283,7 +283,7 @@ static void ds1374_work(struct work_struct *work) | |||
| 283 | 283 | ||
| 284 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | 284 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); |
| 285 | if (stat < 0) | 285 | if (stat < 0) |
| 286 | return; | 286 | goto unlock; |
| 287 | 287 | ||
| 288 | if (stat & DS1374_REG_SR_AF) { | 288 | if (stat & DS1374_REG_SR_AF) { |
| 289 | stat &= ~DS1374_REG_SR_AF; | 289 | stat &= ~DS1374_REG_SR_AF; |
| @@ -302,7 +302,7 @@ static void ds1374_work(struct work_struct *work) | |||
| 302 | out: | 302 | out: |
| 303 | if (!ds1374->exiting) | 303 | if (!ds1374->exiting) |
| 304 | enable_irq(client->irq); | 304 | enable_irq(client->irq); |
| 305 | 305 | unlock: | |
| 306 | mutex_unlock(&ds1374->mutex); | 306 | mutex_unlock(&ds1374->mutex); |
| 307 | } | 307 | } |
| 308 | 308 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff854..2c839d0d21bd 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -33,7 +33,7 @@ | |||
| 33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
| 34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 35 | 35 | ||
| 36 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 36 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
| 37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
| 38 | MODULE_LICENSE("GPL v2"); | 38 | MODULE_LICENSE("GPL v2"); |
| 39 | 39 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index f8b1f04f26b8..c11770f5b368 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -1696,8 +1696,7 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
| 1696 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | 1696 | DBF_DEV_EVENT(DBF_ERR, device, "%s", |
| 1697 | "unsolicited interrupt received " | 1697 | "unsolicited interrupt received " |
| 1698 | "(sense available)"); | 1698 | "(sense available)"); |
| 1699 | device->discipline->dump_sense_dbf(device, NULL, irb, | 1699 | device->discipline->dump_sense_dbf(device, irb, "unsolicited"); |
| 1700 | "unsolicited"); | ||
| 1701 | } | 1700 | } |
| 1702 | 1701 | ||
| 1703 | dasd_schedule_device_bh(device); | 1702 | dasd_schedule_device_bh(device); |
| @@ -2941,42 +2940,20 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) | |||
| 2941 | } | 2940 | } |
| 2942 | 2941 | ||
| 2943 | static void | 2942 | static void |
| 2944 | dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, | 2943 | dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct irb *irb, |
| 2945 | struct irb *irb, char *reason) | 2944 | char *reason) |
| 2946 | { | 2945 | { |
| 2947 | u64 *sense; | 2946 | u64 *sense; |
| 2948 | int sl; | ||
| 2949 | struct tsb *tsb; | ||
| 2950 | 2947 | ||
| 2951 | sense = NULL; | 2948 | sense = (u64 *) dasd_get_sense(irb); |
| 2952 | tsb = NULL; | ||
| 2953 | if (req && scsw_is_tm(&req->irb.scsw)) { | ||
| 2954 | if (irb->scsw.tm.tcw) | ||
| 2955 | tsb = tcw_get_tsb( | ||
| 2956 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); | ||
| 2957 | if (tsb && (irb->scsw.tm.fcxs == 0x01)) { | ||
| 2958 | switch (tsb->flags & 0x07) { | ||
| 2959 | case 1: /* tsa_iostat */ | ||
| 2960 | sense = (u64 *)tsb->tsa.iostat.sense; | ||
| 2961 | break; | ||
| 2962 | case 2: /* ts_ddpc */ | ||
| 2963 | sense = (u64 *)tsb->tsa.ddpc.sense; | ||
| 2964 | break; | ||
| 2965 | case 3: /* tsa_intrg */ | ||
| 2966 | break; | ||
| 2967 | } | ||
| 2968 | } | ||
| 2969 | } else { | ||
| 2970 | if (irb->esw.esw0.erw.cons) | ||
| 2971 | sense = (u64 *)irb->ecw; | ||
| 2972 | } | ||
| 2973 | if (sense) { | 2949 | if (sense) { |
| 2974 | for (sl = 0; sl < 4; sl++) { | 2950 | DBF_DEV_EVENT(DBF_EMERG, device, |
| 2975 | DBF_DEV_EVENT(DBF_EMERG, device, | 2951 | "%s: %s %02x%02x%02x %016llx %016llx %016llx " |
| 2976 | "%s: %016llx %016llx %016llx %016llx", | 2952 | "%016llx", reason, |
| 2977 | reason, sense[0], sense[1], sense[2], | 2953 | scsw_is_tm(&irb->scsw) ? "t" : "c", |
| 2978 | sense[3]); | 2954 | scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw), |
| 2979 | } | 2955 | scsw_dstat(&irb->scsw), sense[0], sense[1], |
| 2956 | sense[2], sense[3]); | ||
| 2980 | } else { | 2957 | } else { |
| 2981 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", | 2958 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", |
| 2982 | "SORRY - NO VALID SENSE AVAILABLE\n"); | 2959 | "SORRY - NO VALID SENSE AVAILABLE\n"); |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index d970ce2814be..cb8f9cef7429 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
| @@ -172,7 +172,7 @@ dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb) | |||
| 172 | device = cqr->startdev; | 172 | device = cqr->startdev; |
| 173 | /* dump sense data to s390 debugfeature*/ | 173 | /* dump sense data to s390 debugfeature*/ |
| 174 | if (device->discipline && device->discipline->dump_sense_dbf) | 174 | if (device->discipline && device->discipline->dump_sense_dbf) |
| 175 | device->discipline->dump_sense_dbf(device, cqr, irb, "log"); | 175 | device->discipline->dump_sense_dbf(device, irb, "log"); |
| 176 | } | 176 | } |
| 177 | EXPORT_SYMBOL(dasd_log_sense_dbf); | 177 | EXPORT_SYMBOL(dasd_log_sense_dbf); |
| 178 | 178 | ||
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index e21ee735f926..31849ad5e59f 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
| @@ -241,7 +241,7 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, | |||
| 241 | /* check for unsolicited interrupts */ | 241 | /* check for unsolicited interrupts */ |
| 242 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 242 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
| 243 | "unsolicited interrupt received"); | 243 | "unsolicited interrupt received"); |
| 244 | device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited"); | 244 | device->discipline->dump_sense_dbf(device, irb, "unsolicited"); |
| 245 | dasd_schedule_device_bh(device); | 245 | dasd_schedule_device_bh(device); |
| 246 | return; | 246 | return; |
| 247 | }; | 247 | }; |
| @@ -444,17 +444,20 @@ dasd_fba_fill_info(struct dasd_device * device, | |||
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | static void | 446 | static void |
| 447 | dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, | 447 | dasd_fba_dump_sense_dbf(struct dasd_device *device, struct irb *irb, |
| 448 | struct irb *irb, char *reason) | 448 | char *reason) |
| 449 | { | 449 | { |
| 450 | int sl; | 450 | u64 *sense; |
| 451 | if (irb->esw.esw0.erw.cons) { | 451 | |
| 452 | for (sl = 0; sl < 4; sl++) { | 452 | sense = (u64 *) dasd_get_sense(irb); |
| 453 | DBF_DEV_EVENT(DBF_EMERG, device, | 453 | if (sense) { |
| 454 | "%s: %08x %08x %08x %08x", | 454 | DBF_DEV_EVENT(DBF_EMERG, device, |
| 455 | reason, irb->ecw[8 * 0], irb->ecw[8 * 1], | 455 | "%s: %s %02x%02x%02x %016llx %016llx %016llx " |
| 456 | irb->ecw[8 * 2], irb->ecw[8 * 3]); | 456 | "%016llx", reason, |
| 457 | } | 457 | scsw_is_tm(&irb->scsw) ? "t" : "c", |
| 458 | scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw), | ||
| 459 | scsw_dstat(&irb->scsw), sense[0], sense[1], | ||
| 460 | sense[2], sense[3]); | ||
| 458 | } else { | 461 | } else { |
| 459 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", | 462 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", |
| 460 | "SORRY - NO VALID SENSE AVAILABLE\n"); | 463 | "SORRY - NO VALID SENSE AVAILABLE\n"); |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index fd63b2f2bda9..b699ca356ac5 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -284,8 +284,7 @@ struct dasd_discipline { | |||
| 284 | dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); | 284 | dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); |
| 285 | void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, | 285 | void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, |
| 286 | struct irb *); | 286 | struct irb *); |
| 287 | void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *, | 287 | void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *); |
| 288 | struct irb *, char *); | ||
| 289 | 288 | ||
| 290 | void (*handle_unsolicited_interrupt) (struct dasd_device *, | 289 | void (*handle_unsolicited_interrupt) (struct dasd_device *, |
| 291 | struct irb *); | 290 | struct irb *); |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 4ce3f72ee1c1..df918ef27965 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/major.h> | 16 | #include <linux/major.h> |
| 17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 18 | #include <linux/blkpg.h> | 18 | #include <linux/blkpg.h> |
| 19 | #include <linux/smp_lock.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/ccwdev.h> | 21 | #include <asm/ccwdev.h> |
| 21 | #include <asm/cmb.h> | 22 | #include <asm/cmb.h> |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 016f9e9d2591..d34617682a62 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
| @@ -964,7 +964,8 @@ static int dcssblk_freeze(struct device *dev) | |||
| 964 | break; | 964 | break; |
| 965 | } | 965 | } |
| 966 | if (rc) | 966 | if (rc) |
| 967 | pr_err("Suspend failed because device %s is writeable.\n", | 967 | pr_err("Suspending the system failed because DCSS device %s " |
| 968 | "is writable\n", | ||
| 968 | dev_info->segment_name); | 969 | dev_info->segment_name); |
| 969 | return rc; | 970 | return rc; |
| 970 | } | 971 | } |
| @@ -987,8 +988,8 @@ static int dcssblk_restore(struct device *dev) | |||
| 987 | goto out_panic; | 988 | goto out_panic; |
| 988 | } | 989 | } |
| 989 | if (start != entry->start || end != entry->end) { | 990 | if (start != entry->start || end != entry->end) { |
| 990 | pr_err("Mismatch of start / end address after " | 991 | pr_err("The address range of DCSS %s changed " |
| 991 | "resuming device %s\n", | 992 | "while the system was suspended\n", |
| 992 | entry->segment_name); | 993 | entry->segment_name); |
| 993 | goto out_panic; | 994 | goto out_panic; |
| 994 | } | 995 | } |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 2e9e1ecd6d82..db442cd6621e 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
| @@ -443,7 +443,7 @@ fail: | |||
| 443 | */ | 443 | */ |
| 444 | static void xpram_resume_error(const char *message) | 444 | static void xpram_resume_error(const char *message) |
| 445 | { | 445 | { |
| 446 | pr_err("Resume error: %s\n", message); | 446 | pr_err("Resuming the system failed: %s\n", message); |
| 447 | panic("xpram resume error\n"); | 447 | panic("xpram resume error\n"); |
| 448 | } | 448 | } |
| 449 | 449 | ||
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7892550d7932..3234e90bd7f9 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c | |||
| @@ -320,7 +320,7 @@ static int mon_open(struct inode *inode, struct file *filp) | |||
| 320 | goto out_path; | 320 | goto out_path; |
| 321 | } | 321 | } |
| 322 | filp->private_data = monpriv; | 322 | filp->private_data = monpriv; |
| 323 | dev_set_drvdata(&monreader_device, monpriv); | 323 | dev_set_drvdata(monreader_device, monpriv); |
| 324 | unlock_kernel(); | 324 | unlock_kernel(); |
| 325 | return nonseekable_open(inode, filp); | 325 | return nonseekable_open(inode, filp); |
| 326 | 326 | ||
| @@ -463,7 +463,7 @@ static struct miscdevice mon_dev = { | |||
| 463 | *****************************************************************************/ | 463 | *****************************************************************************/ |
| 464 | static int monreader_freeze(struct device *dev) | 464 | static int monreader_freeze(struct device *dev) |
| 465 | { | 465 | { |
| 466 | struct mon_private *monpriv = dev_get_drvdata(&dev); | 466 | struct mon_private *monpriv = dev_get_drvdata(dev); |
| 467 | int rc; | 467 | int rc; |
| 468 | 468 | ||
| 469 | if (!monpriv) | 469 | if (!monpriv) |
diff --git a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h index 85f491ea929c..7a7bfc947d97 100644 --- a/drivers/s390/char/sclp_rw.h +++ b/drivers/s390/char/sclp_rw.h | |||
| @@ -92,5 +92,10 @@ void sclp_set_columns(struct sclp_buffer *, unsigned short); | |||
| 92 | void sclp_set_htab(struct sclp_buffer *, unsigned short); | 92 | void sclp_set_htab(struct sclp_buffer *, unsigned short); |
| 93 | int sclp_chars_in_buffer(struct sclp_buffer *); | 93 | int sclp_chars_in_buffer(struct sclp_buffer *); |
| 94 | 94 | ||
| 95 | #ifdef CONFIG_SCLP_CONSOLE | ||
| 95 | void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event); | 96 | void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event); |
| 97 | #else | ||
| 98 | static inline void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) { } | ||
| 99 | #endif | ||
| 100 | |||
| 96 | #endif /* __SCLP_RW_H__ */ | 101 | #endif /* __SCLP_RW_H__ */ |
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c index cb7854c10c04..f2bc287b69e4 100644 --- a/drivers/s390/char/vmwatchdog.c +++ b/drivers/s390/char/vmwatchdog.c | |||
| @@ -250,14 +250,14 @@ static int vmwdt_resume(void) | |||
| 250 | static int vmwdt_suspend(void) | 250 | static int vmwdt_suspend(void) |
| 251 | { | 251 | { |
| 252 | if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) { | 252 | if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) { |
| 253 | pr_err("The watchdog is in use. " | 253 | pr_err("The system cannot be suspended while the watchdog" |
| 254 | "This prevents hibernation or suspend.\n"); | 254 | " is in use\n"); |
| 255 | return NOTIFY_BAD; | 255 | return NOTIFY_BAD; |
| 256 | } | 256 | } |
| 257 | if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) { | 257 | if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) { |
| 258 | clear_bit(VMWDT_OPEN, &vmwdt_is_open); | 258 | clear_bit(VMWDT_OPEN, &vmwdt_is_open); |
| 259 | pr_err("The watchdog is running. " | 259 | pr_err("The system cannot be suspended while the watchdog" |
| 260 | "This prevents hibernation or suspend.\n"); | 260 | " is running\n"); |
| 261 | return NOTIFY_BAD; | 261 | return NOTIFY_BAD; |
| 262 | } | 262 | } |
| 263 | return NOTIFY_DONE; | 263 | return NOTIFY_DONE; |
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0471f8800483..4240b05aef6d 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c | |||
| @@ -2826,8 +2826,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd) | |||
| 2826 | */ | 2826 | */ |
| 2827 | 2827 | ||
| 2828 | local_irq_restore(flags); | 2828 | local_irq_restore(flags); |
| 2829 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" | 2829 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); |
| 2830 | KERN_INFO " before abortion\n", HOSTNO); | ||
| 2831 | 2830 | ||
| 2832 | /* Maybe it is sufficient just to release the ST-DMA lock... (if | 2831 | /* Maybe it is sufficient just to release the ST-DMA lock... (if |
| 2833 | * possible at all) At least, we should check if the lock could be | 2832 | * possible at all) At least, we should check if the lock could be |
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild index 25a2032bfa26..70d060b7ff4f 100644 --- a/drivers/scsi/cxgb3i/Kbuild +++ b/drivers/scsi/cxgb3i/Kbuild | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 | 1 | EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3 |
| 2 | 2 | ||
| 3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o | 3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o |
| 4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o | 4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index 74369a3f963b..c399f485aa7d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/inet.h> | 14 | #include <linux/inet.h> |
| 15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
| 16 | #include <linux/if_vlan.h> | ||
| 16 | #include <net/dst.h> | 17 | #include <net/dst.h> |
| 17 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
| 18 | #include <scsi/scsi_cmnd.h> | 19 | #include <scsi/scsi_cmnd.h> |
| @@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) | |||
| 184 | struct cxgb3i_adapter *snic; | 185 | struct cxgb3i_adapter *snic; |
| 185 | int i; | 186 | int i; |
| 186 | 187 | ||
| 188 | if (ndev->priv_flags & IFF_802_1Q_VLAN) | ||
| 189 | ndev = vlan_dev_real_dev(ndev); | ||
| 190 | |||
| 187 | read_lock(&cxgb3i_snic_rwlock); | 191 | read_lock(&cxgb3i_snic_rwlock); |
| 188 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { | 192 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { |
| 189 | for (i = 0; i < snic->hba_cnt; i++) { | 193 | for (i = 0; i < snic->hba_cnt; i++) { |
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index a84072865fc2..2c266c01dc5a 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
| @@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
| 473 | * limitation for the device. Try 40-bit first, and | 473 | * limitation for the device. Try 40-bit first, and |
| 474 | * fail to 32-bit. | 474 | * fail to 32-bit. |
| 475 | */ | 475 | */ |
| 476 | err = pci_set_dma_mask(pdev, DMA_40BIT_MASK); | 476 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); |
| 477 | if (err) { | 477 | if (err) { |
| 478 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 478 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
| 479 | if (err) { | 479 | if (err) { |
| 480 | shost_printk(KERN_ERR, fnic->lport->host, | 480 | shost_printk(KERN_ERR, fnic->lport->host, |
| 481 | "No usable DMA configuration " | 481 | "No usable DMA configuration " |
| 482 | "aborting\n"); | 482 | "aborting\n"); |
| 483 | goto err_out_release_regions; | 483 | goto err_out_release_regions; |
| 484 | } | 484 | } |
| 485 | err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | 485 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
| 486 | if (err) { | 486 | if (err) { |
| 487 | shost_printk(KERN_ERR, fnic->lport->host, | 487 | shost_printk(KERN_ERR, fnic->lport->host, |
| 488 | "Unable to obtain 32-bit DMA " | 488 | "Unable to obtain 32-bit DMA " |
| @@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
| 490 | goto err_out_release_regions; | 490 | goto err_out_release_regions; |
| 491 | } | 491 | } |
| 492 | } else { | 492 | } else { |
| 493 | err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); | 493 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)); |
| 494 | if (err) { | 494 | if (err) { |
| 495 | shost_printk(KERN_ERR, fnic->lport->host, | 495 | shost_printk(KERN_ERR, fnic->lport->host, |
| 496 | "Unable to obtain 40-bit DMA " | 496 | "Unable to obtain 40-bit DMA " |
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index eabf36502856..bfc996971b81 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
| @@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
| 245 | struct vnic_wq_copy *wq, | 245 | struct vnic_wq_copy *wq, |
| 246 | struct fnic_io_req *io_req, | 246 | struct fnic_io_req *io_req, |
| 247 | struct scsi_cmnd *sc, | 247 | struct scsi_cmnd *sc, |
| 248 | u32 sg_count) | 248 | int sg_count) |
| 249 | { | 249 | { |
| 250 | struct scatterlist *sg; | 250 | struct scatterlist *sg; |
| 251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | 251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); |
| @@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
| 260 | char msg[2]; | 260 | char msg[2]; |
| 261 | 261 | ||
| 262 | if (sg_count) { | 262 | if (sg_count) { |
| 263 | BUG_ON(sg_count < 0); | ||
| 264 | BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT); | ||
| 265 | |||
| 266 | /* For each SGE, create a device desc entry */ | 263 | /* For each SGE, create a device desc entry */ |
| 267 | desc = io_req->sgl_list; | 264 | desc = io_req->sgl_list; |
| 268 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { | 265 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { |
| @@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 344 | struct fnic *fnic; | 341 | struct fnic *fnic; |
| 345 | struct vnic_wq_copy *wq; | 342 | struct vnic_wq_copy *wq; |
| 346 | int ret; | 343 | int ret; |
| 347 | u32 sg_count; | 344 | int sg_count; |
| 348 | unsigned long flags; | 345 | unsigned long flags; |
| 349 | unsigned long ptr; | 346 | unsigned long ptr; |
| 350 | 347 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 869a11bdccbd..9928704e235f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
| @@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
| 1095 | MAX_INDIRECT_BUFS); | 1095 | MAX_INDIRECT_BUFS); |
| 1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | 1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; |
| 1097 | } | 1097 | } |
| 1098 | |||
| 1099 | if (hostdata->madapter_info.os_type == 3) { | ||
| 1100 | enable_fast_fail(hostdata); | ||
| 1101 | return; | ||
| 1102 | } | ||
| 1098 | } | 1103 | } |
| 1099 | 1104 | ||
| 1100 | enable_fast_fail(hostdata); | 1105 | send_srp_login(hostdata); |
| 1101 | } | 1106 | } |
| 1102 | 1107 | ||
| 1103 | /** | 1108 | /** |
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index b12ad7c7c673..18735b39b3d3 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c | |||
| @@ -75,8 +75,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd * | |||
| 75 | int i; | 75 | int i; |
| 76 | printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); | 76 | printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); |
| 77 | for (i = 0; i < cmd->cmd_len; ++i) | 77 | for (i = 0; i < cmd->cmd_len; ++i) |
| 78 | printk(" %.2x", cmd->cmnd[i]); | 78 | printk(KERN_CONT " %.2x", cmd->cmnd[i]); |
| 79 | printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", | 79 | printk(KERN_CONT "\n"); |
| 80 | printk(KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", | ||
| 80 | scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd)); | 81 | scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd)); |
| 81 | } | 82 | } |
| 82 | #endif | 83 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 650bcef08f2a..cd78c501803a 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
| 11 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
| 12 | #include <linux/smp_lock.h> | ||
| 13 | #include <linux/list.h> | 12 | #include <linux/list.h> |
| 14 | 13 | ||
| 15 | #include <scsi/scsi_tcq.h> | 14 | #include <scsi/scsi_tcq.h> |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2eee9e6e4fe8..292c02f810d0 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -3670,13 +3670,14 @@ static void | |||
| 3670 | fc_bsg_goose_queue(struct fc_rport *rport) | 3670 | fc_bsg_goose_queue(struct fc_rport *rport) |
| 3671 | { | 3671 | { |
| 3672 | int flagset; | 3672 | int flagset; |
| 3673 | unsigned long flags; | ||
| 3673 | 3674 | ||
| 3674 | if (!rport->rqst_q) | 3675 | if (!rport->rqst_q) |
| 3675 | return; | 3676 | return; |
| 3676 | 3677 | ||
| 3677 | get_device(&rport->dev); | 3678 | get_device(&rport->dev); |
| 3678 | 3679 | ||
| 3679 | spin_lock(rport->rqst_q->queue_lock); | 3680 | spin_lock_irqsave(rport->rqst_q->queue_lock, flags); |
| 3680 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && | 3681 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && |
| 3681 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); | 3682 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); |
| 3682 | if (flagset) | 3683 | if (flagset) |
| @@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) | |||
| 3684 | __blk_run_queue(rport->rqst_q); | 3685 | __blk_run_queue(rport->rqst_q); |
| 3685 | if (flagset) | 3686 | if (flagset) |
| 3686 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); | 3687 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); |
| 3687 | spin_unlock(rport->rqst_q->queue_lock); | 3688 | spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); |
| 3688 | 3689 | ||
| 3689 | put_device(&rport->dev); | 3690 | put_device(&rport->dev); |
| 3690 | } | 3691 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8201387b4daa..9230402c45af 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
| @@ -210,13 +210,11 @@ static void sg_put_dev(Sg_device *sdp); | |||
| 210 | static int sg_allow_access(struct file *filp, unsigned char *cmd) | 210 | static int sg_allow_access(struct file *filp, unsigned char *cmd) |
| 211 | { | 211 | { |
| 212 | struct sg_fd *sfp = (struct sg_fd *)filp->private_data; | 212 | struct sg_fd *sfp = (struct sg_fd *)filp->private_data; |
| 213 | struct request_queue *q = sfp->parentdp->device->request_queue; | ||
| 214 | 213 | ||
| 215 | if (sfp->parentdp->device->type == TYPE_SCANNER) | 214 | if (sfp->parentdp->device->type == TYPE_SCANNER) |
| 216 | return 0; | 215 | return 0; |
| 217 | 216 | ||
| 218 | return blk_verify_command(&q->cmd_filter, | 217 | return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); |
| 219 | cmd, filp->f_mode & FMODE_WRITE); | ||
| 220 | } | 218 | } |
| 221 | 219 | ||
| 222 | static int | 220 | static int |
| @@ -621,7 +619,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) | |||
| 621 | if (strcmp(current->comm, cmd) && printk_ratelimit()) { | 619 | if (strcmp(current->comm, cmd) && printk_ratelimit()) { |
| 622 | printk(KERN_WARNING | 620 | printk(KERN_WARNING |
| 623 | "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--" | 621 | "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--" |
| 624 | "guessing data in;\n" KERN_WARNING " " | 622 | "guessing data in;\n " |
| 625 | "program %s not setting count and/or reply_len properly\n", | 623 | "program %s not setting count and/or reply_len properly\n", |
| 626 | old_hdr.reply_len - (int)SZ_SG_HEADER, | 624 | old_hdr.reply_len - (int)SZ_SG_HEADER, |
| 627 | input_size, (unsigned int) cmnd[0], | 625 | input_size, (unsigned int) cmnd[0], |
| @@ -1658,6 +1656,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
| 1658 | md->nr_entries = req_schp->k_use_sg; | 1656 | md->nr_entries = req_schp->k_use_sg; |
| 1659 | md->offset = 0; | 1657 | md->offset = 0; |
| 1660 | md->null_mapped = hp->dxferp ? 0 : 1; | 1658 | md->null_mapped = hp->dxferp ? 0 : 1; |
| 1659 | if (dxfer_dir == SG_DXFER_TO_FROM_DEV) | ||
| 1660 | md->from_user = 1; | ||
| 1661 | else | ||
| 1662 | md->from_user = 0; | ||
| 1661 | } | 1663 | } |
| 1662 | 1664 | ||
| 1663 | if (iov_count) { | 1665 | if (iov_count) { |
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index bcaba86060ab..75da6e58ce55 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c | |||
| @@ -2860,8 +2860,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) | |||
| 2860 | */ | 2860 | */ |
| 2861 | 2861 | ||
| 2862 | local_irq_restore(flags); | 2862 | local_irq_restore(flags); |
| 2863 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" | 2863 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); |
| 2864 | KERN_INFO " before abortion\n", HOSTNO); | ||
| 2865 | 2864 | ||
| 2866 | return SCSI_ABORT_NOT_RUNNING; | 2865 | return SCSI_ABORT_NOT_RUNNING; |
| 2867 | } | 2866 | } |
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 97f3158fa7b5..27e84e4b1fa9 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c | |||
| @@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev) | |||
| 134 | 134 | ||
| 135 | host = ncr_attach(&zalon7xx_template, unit, &device); | 135 | host = ncr_attach(&zalon7xx_template, unit, &device); |
| 136 | if (!host) | 136 | if (!host) |
| 137 | goto fail; | 137 | return -ENODEV; |
| 138 | 138 | ||
| 139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { | 139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { |
| 140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", | 140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index e371a9c15341..e7108e75653d 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
| @@ -60,11 +60,12 @@ struct serial_private { | |||
| 60 | 60 | ||
| 61 | static void moan_device(const char *str, struct pci_dev *dev) | 61 | static void moan_device(const char *str, struct pci_dev *dev) |
| 62 | { | 62 | { |
| 63 | printk(KERN_WARNING "%s: %s\n" | 63 | printk(KERN_WARNING |
| 64 | KERN_WARNING "Please send the output of lspci -vv, this\n" | 64 | "%s: %s\n" |
| 65 | KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" | 65 | "Please send the output of lspci -vv, this\n" |
| 66 | KERN_WARNING "manufacturer and name of serial board or\n" | 66 | "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" |
| 67 | KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n", | 67 | "manufacturer and name of serial board or\n" |
| 68 | "modem board to rmk+serial@arm.linux.org.uk.\n", | ||
| 68 | pci_name(dev), str, dev->vendor, dev->device, | 69 | pci_name(dev), str, dev->vendor, dev->device, |
| 69 | dev->subsystem_vendor, dev->subsystem_device); | 70 | dev->subsystem_vendor, dev->subsystem_device); |
| 70 | } | 71 | } |
| @@ -398,8 +399,7 @@ static int sbs_init(struct pci_dev *dev) | |||
| 398 | { | 399 | { |
| 399 | u8 __iomem *p; | 400 | u8 __iomem *p; |
| 400 | 401 | ||
| 401 | p = ioremap_nocache(pci_resource_start(dev, 0), | 402 | p = pci_ioremap_bar(dev, 0); |
| 402 | pci_resource_len(dev, 0)); | ||
| 403 | 403 | ||
| 404 | if (p == NULL) | 404 | if (p == NULL) |
| 405 | return -ENOMEM; | 405 | return -ENOMEM; |
| @@ -423,8 +423,7 @@ static void __devexit sbs_exit(struct pci_dev *dev) | |||
| 423 | { | 423 | { |
| 424 | u8 __iomem *p; | 424 | u8 __iomem *p; |
| 425 | 425 | ||
| 426 | p = ioremap_nocache(pci_resource_start(dev, 0), | 426 | p = pci_ioremap_bar(dev, 0); |
| 427 | pci_resource_len(dev, 0)); | ||
| 428 | /* FIXME: What if resource_len < OCT_REG_CR_OFF */ | 427 | /* FIXME: What if resource_len < OCT_REG_CR_OFF */ |
| 429 | if (p != NULL) | 428 | if (p != NULL) |
| 430 | writeb(0, p + OCT_REG_CR_OFF); | 429 | writeb(0, p + OCT_REG_CR_OFF); |
| @@ -761,6 +760,8 @@ static int pci_netmos_init(struct pci_dev *dev) | |||
| 761 | /* subdevice 0x00PS means <P> parallel, <S> serial */ | 760 | /* subdevice 0x00PS means <P> parallel, <S> serial */ |
| 762 | unsigned int num_serial = dev->subsystem_device & 0xf; | 761 | unsigned int num_serial = dev->subsystem_device & 0xf; |
| 763 | 762 | ||
| 763 | if (dev->device == PCI_DEVICE_ID_NETMOS_9901) | ||
| 764 | return 0; | ||
| 764 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && | 765 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && |
| 765 | dev->subsystem_device == 0x0299) | 766 | dev->subsystem_device == 0x0299) |
| 766 | return 0; | 767 | return 0; |
| @@ -3559,6 +3560,10 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
| 3559 | PCI_VENDOR_ID_IBM, 0x0299, | 3560 | PCI_VENDOR_ID_IBM, 0x0299, |
| 3560 | 0, 0, pbn_b0_bt_2_115200 }, | 3561 | 0, 0, pbn_b0_bt_2_115200 }, |
| 3561 | 3562 | ||
| 3563 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | ||
| 3564 | 0xA000, 0x1000, | ||
| 3565 | 0, 0, pbn_b0_1_115200 }, | ||
| 3566 | |||
| 3562 | /* | 3567 | /* |
| 3563 | * These entries match devices with class COMMUNICATION_SERIAL, | 3568 | * These entries match devices with class COMMUNICATION_SERIAL, |
| 3564 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL | 3569 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 34b4ae0fe760..c108b1a0ce98 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
| @@ -236,7 +236,6 @@ static int sport_startup(struct uart_port *port) | |||
| 236 | int retval; | 236 | int retval; |
| 237 | 237 | ||
| 238 | pr_debug("%s enter\n", __func__); | 238 | pr_debug("%s enter\n", __func__); |
| 239 | memset(buffer, 20, '\0'); | ||
| 240 | snprintf(buffer, 20, "%s rx", up->name); | 239 | snprintf(buffer, 20, "%s rx", up->name); |
| 241 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 240 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); |
| 242 | if (retval) { | 241 | if (retval) { |
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 9f2891c2c4a2..cd1b6a45bb82 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
| @@ -1548,8 +1548,7 @@ static int __devinit icom_probe(struct pci_dev *dev, | |||
| 1548 | goto probe_exit1; | 1548 | goto probe_exit1; |
| 1549 | } | 1549 | } |
| 1550 | 1550 | ||
| 1551 | icom_adapter->base_addr = ioremap(icom_adapter->base_addr_pci, | 1551 | icom_adapter->base_addr = pci_ioremap_bar(dev, 0); |
| 1552 | pci_resource_len(dev, 0)); | ||
| 1553 | 1552 | ||
| 1554 | if (!icom_adapter->base_addr) | 1553 | if (!icom_adapter->base_addr) |
| 1555 | goto probe_exit1; | 1554 | goto probe_exit1; |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 107ce2e187b8..00f4577d2f7f 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
| @@ -467,7 +467,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) | |||
| 467 | printk(KERN_INFO "jsm: linemap is full, added device failed\n"); | 467 | printk(KERN_INFO "jsm: linemap is full, added device failed\n"); |
| 468 | continue; | 468 | continue; |
| 469 | } else | 469 | } else |
| 470 | set_bit((int)line, linemap); | 470 | set_bit(line, linemap); |
| 471 | brd->channels[i]->uart_port.line = line; | 471 | brd->channels[i]->uart_port.line = line; |
| 472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) |
| 473 | printk(KERN_INFO "jsm: add device failed\n"); | 473 | printk(KERN_INFO "jsm: add device failed\n"); |
| @@ -503,7 +503,7 @@ int jsm_remove_uart_port(struct jsm_board *brd) | |||
| 503 | 503 | ||
| 504 | ch = brd->channels[i]; | 504 | ch = brd->channels[i]; |
| 505 | 505 | ||
| 506 | clear_bit((int)(ch->uart_port.line), linemap); | 506 | clear_bit(ch->uart_port.line, linemap); |
| 507 | uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port); | 507 | uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port); |
| 508 | } | 508 | } |
| 509 | 509 | ||
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c index 698048f64f5e..f7c24baa1416 100644 --- a/drivers/serial/msm_serial.c +++ b/drivers/serial/msm_serial.c | |||
| @@ -730,7 +730,6 @@ static int __devexit msm_serial_remove(struct platform_device *pdev) | |||
| 730 | } | 730 | } |
| 731 | 731 | ||
| 732 | static struct platform_driver msm_platform_driver = { | 732 | static struct platform_driver msm_platform_driver = { |
| 733 | .probe = msm_serial_probe, | ||
| 734 | .remove = msm_serial_remove, | 733 | .remove = msm_serial_remove, |
| 735 | .driver = { | 734 | .driver = { |
| 736 | .name = "msm_serial", | 735 | .name = "msm_serial", |
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 7313c2edcb83..54dd16d66a4b 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
| @@ -461,6 +461,94 @@ static void serial_txx9_break_ctl(struct uart_port *port, int break_state) | |||
| 461 | spin_unlock_irqrestore(&up->port.lock, flags); | 461 | spin_unlock_irqrestore(&up->port.lock, flags); |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | #if defined(CONFIG_SERIAL_TXX9_CONSOLE) || (CONFIG_CONSOLE_POLL) | ||
| 465 | /* | ||
| 466 | * Wait for transmitter & holding register to empty | ||
| 467 | */ | ||
| 468 | static void wait_for_xmitr(struct uart_txx9_port *up) | ||
| 469 | { | ||
| 470 | unsigned int tmout = 10000; | ||
| 471 | |||
| 472 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 473 | while (--tmout && | ||
| 474 | !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS)) | ||
| 475 | udelay(1); | ||
| 476 | |||
| 477 | /* Wait up to 1s for flow control if necessary */ | ||
| 478 | if (up->port.flags & UPF_CONS_FLOW) { | ||
| 479 | tmout = 1000000; | ||
| 480 | while (--tmout && | ||
| 481 | (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS)) | ||
| 482 | udelay(1); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | #endif | ||
| 486 | |||
| 487 | #ifdef CONFIG_CONSOLE_POLL | ||
| 488 | /* | ||
| 489 | * Console polling routines for writing and reading from the uart while | ||
| 490 | * in an interrupt or debug context. | ||
| 491 | */ | ||
| 492 | |||
| 493 | static int serial_txx9_get_poll_char(struct uart_port *port) | ||
| 494 | { | ||
| 495 | unsigned int ier; | ||
| 496 | unsigned char c; | ||
| 497 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * First save the IER then disable the interrupts | ||
| 501 | */ | ||
| 502 | ier = sio_in(up, TXX9_SIDICR); | ||
| 503 | sio_out(up, TXX9_SIDICR, 0); | ||
| 504 | |||
| 505 | while (sio_in(up, TXX9_SIDISR) & TXX9_SIDISR_UVALID) | ||
| 506 | ; | ||
| 507 | |||
| 508 | c = sio_in(up, TXX9_SIRFIFO); | ||
| 509 | |||
| 510 | /* | ||
| 511 | * Finally, clear RX interrupt status | ||
| 512 | * and restore the IER | ||
| 513 | */ | ||
| 514 | sio_mask(up, TXX9_SIDISR, TXX9_SIDISR_RDIS); | ||
| 515 | sio_out(up, TXX9_SIDICR, ier); | ||
| 516 | return c; | ||
| 517 | } | ||
| 518 | |||
| 519 | |||
| 520 | static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c) | ||
| 521 | { | ||
| 522 | unsigned int ier; | ||
| 523 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | ||
| 524 | |||
| 525 | /* | ||
| 526 | * First save the IER then disable the interrupts | ||
| 527 | */ | ||
| 528 | ier = sio_in(up, TXX9_SIDICR); | ||
| 529 | sio_out(up, TXX9_SIDICR, 0); | ||
| 530 | |||
| 531 | wait_for_xmitr(up); | ||
| 532 | /* | ||
| 533 | * Send the character out. | ||
| 534 | * If a LF, also do CR... | ||
| 535 | */ | ||
| 536 | sio_out(up, TXX9_SITFIFO, c); | ||
| 537 | if (c == 10) { | ||
| 538 | wait_for_xmitr(up); | ||
| 539 | sio_out(up, TXX9_SITFIFO, 13); | ||
| 540 | } | ||
| 541 | |||
| 542 | /* | ||
| 543 | * Finally, wait for transmitter to become empty | ||
| 544 | * and restore the IER | ||
| 545 | */ | ||
| 546 | wait_for_xmitr(up); | ||
| 547 | sio_out(up, TXX9_SIDICR, ier); | ||
| 548 | } | ||
| 549 | |||
| 550 | #endif /* CONFIG_CONSOLE_POLL */ | ||
| 551 | |||
| 464 | static int serial_txx9_startup(struct uart_port *port) | 552 | static int serial_txx9_startup(struct uart_port *port) |
| 465 | { | 553 | { |
| 466 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 554 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
| @@ -781,6 +869,10 @@ static struct uart_ops serial_txx9_pops = { | |||
| 781 | .release_port = serial_txx9_release_port, | 869 | .release_port = serial_txx9_release_port, |
| 782 | .request_port = serial_txx9_request_port, | 870 | .request_port = serial_txx9_request_port, |
| 783 | .config_port = serial_txx9_config_port, | 871 | .config_port = serial_txx9_config_port, |
| 872 | #ifdef CONFIG_CONSOLE_POLL | ||
| 873 | .poll_get_char = serial_txx9_get_poll_char, | ||
| 874 | .poll_put_char = serial_txx9_put_poll_char, | ||
| 875 | #endif | ||
| 784 | }; | 876 | }; |
| 785 | 877 | ||
| 786 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; | 878 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; |
| @@ -803,27 +895,6 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv, | |||
| 803 | 895 | ||
| 804 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | 896 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE |
| 805 | 897 | ||
| 806 | /* | ||
| 807 | * Wait for transmitter & holding register to empty | ||
| 808 | */ | ||
| 809 | static inline void wait_for_xmitr(struct uart_txx9_port *up) | ||
| 810 | { | ||
| 811 | unsigned int tmout = 10000; | ||
| 812 | |||
| 813 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 814 | while (--tmout && | ||
| 815 | !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS)) | ||
| 816 | udelay(1); | ||
| 817 | |||
| 818 | /* Wait up to 1s for flow control if necessary */ | ||
| 819 | if (up->port.flags & UPF_CONS_FLOW) { | ||
| 820 | tmout = 1000000; | ||
| 821 | while (--tmout && | ||
| 822 | (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS)) | ||
| 823 | udelay(1); | ||
| 824 | } | ||
| 825 | } | ||
| 826 | |||
| 827 | static void serial_txx9_console_putchar(struct uart_port *port, int ch) | 898 | static void serial_txx9_console_putchar(struct uart_port *port, int ch) |
| 828 | { | 899 | { |
| 829 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 900 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 66f52674ca0c..8e2feb563347 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -707,24 +707,25 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) | |||
| 707 | 707 | ||
| 708 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | 708 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) |
| 709 | { | 709 | { |
| 710 | unsigned short ssr_status, scr_status; | 710 | unsigned short ssr_status, scr_status, err_enabled; |
| 711 | struct uart_port *port = ptr; | 711 | struct uart_port *port = ptr; |
| 712 | irqreturn_t ret = IRQ_NONE; | 712 | irqreturn_t ret = IRQ_NONE; |
| 713 | 713 | ||
| 714 | ssr_status = sci_in(port, SCxSR); | 714 | ssr_status = sci_in(port, SCxSR); |
| 715 | scr_status = sci_in(port, SCSCR); | 715 | scr_status = sci_in(port, SCSCR); |
| 716 | err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); | ||
| 716 | 717 | ||
| 717 | /* Tx Interrupt */ | 718 | /* Tx Interrupt */ |
| 718 | if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE)) | 719 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE)) |
| 719 | ret = sci_tx_interrupt(irq, ptr); | 720 | ret = sci_tx_interrupt(irq, ptr); |
| 720 | /* Rx Interrupt */ | 721 | /* Rx Interrupt */ |
| 721 | if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE)) | 722 | if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE)) |
| 722 | ret = sci_rx_interrupt(irq, ptr); | 723 | ret = sci_rx_interrupt(irq, ptr); |
| 723 | /* Error Interrupt */ | 724 | /* Error Interrupt */ |
| 724 | if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE)) | 725 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) |
| 725 | ret = sci_er_interrupt(irq, ptr); | 726 | ret = sci_er_interrupt(irq, ptr); |
| 726 | /* Break Interrupt */ | 727 | /* Break Interrupt */ |
| 727 | if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE)) | 728 | if ((ssr_status & SCxSR_BRK(port)) && err_enabled) |
| 728 | ret = sci_br_interrupt(irq, ptr); | 729 | ret = sci_br_interrupt(irq, ptr); |
| 729 | 730 | ||
| 730 | return ret; | 731 | return ret; |
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 0573f3b5175e..dac550e57c29 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for NEC VR4100 series Serial Interface Unit. | 2 | * Driver for NEC VR4100 series Serial Interface Unit. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
| 5 | * | 5 | * |
| 6 | * Based on drivers/serial/8250.c, by Russell King. | 6 | * Based on drivers/serial/8250.c, by Russell King. |
| 7 | * | 7 | * |
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index aa90ddb37066..8980a5640bd9 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c | |||
| @@ -514,6 +514,8 @@ static int __init uwire_probe(struct platform_device *pdev) | |||
| 514 | /* the spi->mode bits understood by this driver: */ | 514 | /* the spi->mode bits understood by this driver: */ |
| 515 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 515 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
| 516 | 516 | ||
| 517 | master->flags = SPI_MASTER_HALF_DUPLEX; | ||
| 518 | |||
| 517 | master->bus_num = 2; /* "official" */ | 519 | master->bus_num = 2; /* "official" */ |
| 518 | master->num_chipselect = 4; | 520 | master->num_chipselect = 4; |
| 519 | master->setup = uwire_setup; | 521 | master->setup = uwire_setup; |
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 2a5abc08e857..f1db395dd889 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c | |||
| @@ -258,6 +258,11 @@ static void bitbang_work(struct work_struct *work) | |||
| 258 | struct spi_bitbang *bitbang = | 258 | struct spi_bitbang *bitbang = |
| 259 | container_of(work, struct spi_bitbang, work); | 259 | container_of(work, struct spi_bitbang, work); |
| 260 | unsigned long flags; | 260 | unsigned long flags; |
| 261 | int do_setup = -1; | ||
| 262 | int (*setup_transfer)(struct spi_device *, | ||
| 263 | struct spi_transfer *); | ||
| 264 | |||
| 265 | setup_transfer = bitbang->setup_transfer; | ||
| 261 | 266 | ||
| 262 | spin_lock_irqsave(&bitbang->lock, flags); | 267 | spin_lock_irqsave(&bitbang->lock, flags); |
| 263 | bitbang->busy = 1; | 268 | bitbang->busy = 1; |
| @@ -269,8 +274,6 @@ static void bitbang_work(struct work_struct *work) | |||
| 269 | unsigned tmp; | 274 | unsigned tmp; |
| 270 | unsigned cs_change; | 275 | unsigned cs_change; |
| 271 | int status; | 276 | int status; |
| 272 | int (*setup_transfer)(struct spi_device *, | ||
| 273 | struct spi_transfer *); | ||
| 274 | 277 | ||
| 275 | m = container_of(bitbang->queue.next, struct spi_message, | 278 | m = container_of(bitbang->queue.next, struct spi_message, |
| 276 | queue); | 279 | queue); |
| @@ -287,19 +290,19 @@ static void bitbang_work(struct work_struct *work) | |||
| 287 | tmp = 0; | 290 | tmp = 0; |
| 288 | cs_change = 1; | 291 | cs_change = 1; |
| 289 | status = 0; | 292 | status = 0; |
| 290 | setup_transfer = NULL; | ||
| 291 | 293 | ||
| 292 | list_for_each_entry (t, &m->transfers, transfer_list) { | 294 | list_for_each_entry (t, &m->transfers, transfer_list) { |
| 293 | 295 | ||
| 294 | /* override or restore speed and wordsize */ | 296 | /* override speed or wordsize? */ |
| 295 | if (t->speed_hz || t->bits_per_word) { | 297 | if (t->speed_hz || t->bits_per_word) |
| 296 | setup_transfer = bitbang->setup_transfer; | 298 | do_setup = 1; |
| 299 | |||
| 300 | /* init (-1) or override (1) transfer params */ | ||
| 301 | if (do_setup != 0) { | ||
| 297 | if (!setup_transfer) { | 302 | if (!setup_transfer) { |
| 298 | status = -ENOPROTOOPT; | 303 | status = -ENOPROTOOPT; |
| 299 | break; | 304 | break; |
| 300 | } | 305 | } |
| 301 | } | ||
| 302 | if (setup_transfer) { | ||
| 303 | status = setup_transfer(spi, t); | 306 | status = setup_transfer(spi, t); |
| 304 | if (status < 0) | 307 | if (status < 0) |
| 305 | break; | 308 | break; |
| @@ -363,9 +366,10 @@ static void bitbang_work(struct work_struct *work) | |||
| 363 | m->status = status; | 366 | m->status = status; |
| 364 | m->complete(m->context); | 367 | m->complete(m->context); |
| 365 | 368 | ||
| 366 | /* restore speed and wordsize */ | 369 | /* restore speed and wordsize if it was overridden */ |
| 367 | if (setup_transfer) | 370 | if (do_setup == 1) |
| 368 | setup_transfer(spi, NULL); | 371 | setup_transfer(spi, NULL); |
| 372 | do_setup = 0; | ||
| 369 | 373 | ||
| 370 | /* normally deactivate chipselect ... unless no error and | 374 | /* normally deactivate chipselect ... unless no error and |
| 371 | * cs_change has hinted that the next message will probably | 375 | * cs_change has hinted that the next message will probably |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 5d869c4d3eb2..606e7a40a8da 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
| @@ -58,15 +58,20 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; | |||
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | /* Bit masks for spi_device.mode management. Note that incorrect | 60 | /* Bit masks for spi_device.mode management. Note that incorrect |
| 61 | * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other | 61 | * settings for some settings can cause *lots* of trouble for other |
| 62 | * devices on a shared bus: CS_HIGH, because this device will be | 62 | * devices on a shared bus: |
| 63 | * active when it shouldn't be; 3WIRE, because when active it won't | ||
| 64 | * behave as it should. | ||
| 65 | * | 63 | * |
| 66 | * REVISIT should changing those two modes be privileged? | 64 | * - CS_HIGH ... this device will be active when it shouldn't be |
| 65 | * - 3WIRE ... when active, it won't behave as it should | ||
| 66 | * - NO_CS ... there will be no explicit message boundaries; this | ||
| 67 | * is completely incompatible with the shared bus model | ||
| 68 | * - READY ... transfers may proceed when they shouldn't. | ||
| 69 | * | ||
| 70 | * REVISIT should changing those flags be privileged? | ||
| 67 | */ | 71 | */ |
| 68 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ | 72 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ |
| 69 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) | 73 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ |
| 74 | | SPI_NO_CS | SPI_READY) | ||
| 70 | 75 | ||
| 71 | struct spidev_data { | 76 | struct spidev_data { |
| 72 | dev_t devt; | 77 | dev_t devt; |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3fd3e3b412b6..3c6feed46f6e 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
| @@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { | |||
| 49 | 49 | ||
| 50 | static inline u32 ssb_irqflag(struct ssb_device *dev) | 50 | static inline u32 ssb_irqflag(struct ssb_device *dev) |
| 51 | { | 51 | { |
| 52 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | 52 | u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); |
| 53 | if (tpsflag) | ||
| 54 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | ||
| 55 | else | ||
| 56 | /* not irq supported */ | ||
| 57 | return 0x3f; | ||
| 58 | } | ||
| 59 | |||
| 60 | static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) | ||
| 61 | { | ||
| 62 | struct ssb_bus *bus = rdev->bus; | ||
| 63 | int i; | ||
| 64 | for (i = 0; i < bus->nr_devices; i++) { | ||
| 65 | struct ssb_device *dev; | ||
| 66 | dev = &(bus->devices[i]); | ||
| 67 | if (ssb_irqflag(dev) == irqflag) | ||
| 68 | return dev; | ||
| 69 | } | ||
| 70 | return NULL; | ||
| 53 | } | 71 | } |
| 54 | 72 | ||
| 55 | /* Get the MIPS IRQ assignment for a specified device. | 73 | /* Get the MIPS IRQ assignment for a specified device. |
| 56 | * If unassigned, 0 is returned. | 74 | * If unassigned, 0 is returned. |
| 75 | * If disabled, 5 is returned. | ||
| 76 | * If not supported, 6 is returned. | ||
| 57 | */ | 77 | */ |
| 58 | unsigned int ssb_mips_irq(struct ssb_device *dev) | 78 | unsigned int ssb_mips_irq(struct ssb_device *dev) |
| 59 | { | 79 | { |
| 60 | struct ssb_bus *bus = dev->bus; | 80 | struct ssb_bus *bus = dev->bus; |
| 81 | struct ssb_device *mdev = bus->mipscore.dev; | ||
| 61 | u32 irqflag; | 82 | u32 irqflag; |
| 62 | u32 ipsflag; | 83 | u32 ipsflag; |
| 63 | u32 tmp; | 84 | u32 tmp; |
| 64 | unsigned int irq; | 85 | unsigned int irq; |
| 65 | 86 | ||
| 66 | irqflag = ssb_irqflag(dev); | 87 | irqflag = ssb_irqflag(dev); |
| 88 | if (irqflag == 0x3f) | ||
| 89 | return 6; | ||
| 67 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); | 90 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); |
| 68 | for (irq = 1; irq <= 4; irq++) { | 91 | for (irq = 1; irq <= 4; irq++) { |
| 69 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); | 92 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); |
| 70 | if (tmp == irqflag) | 93 | if (tmp == irqflag) |
| 71 | break; | 94 | break; |
| 72 | } | 95 | } |
| 73 | if (irq == 5) | 96 | if (irq == 5) { |
| 74 | irq = 0; | 97 | if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) |
| 98 | irq = 0; | ||
| 99 | } | ||
| 75 | 100 | ||
| 76 | return irq; | 101 | return irq; |
| 77 | } | 102 | } |
| @@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) | |||
| 97 | struct ssb_device *mdev = bus->mipscore.dev; | 122 | struct ssb_device *mdev = bus->mipscore.dev; |
| 98 | u32 irqflag = ssb_irqflag(dev); | 123 | u32 irqflag = ssb_irqflag(dev); |
| 99 | 124 | ||
| 125 | BUG_ON(oldirq == 6); | ||
| 126 | |||
| 100 | dev->irq = irq + 2; | 127 | dev->irq = irq + 2; |
| 101 | 128 | ||
| 102 | ssb_dprintk(KERN_INFO PFX | ||
| 103 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
| 104 | dev->id.coreid, oldirq, irq); | ||
| 105 | /* clear the old irq */ | 129 | /* clear the old irq */ |
| 106 | if (oldirq == 0) | 130 | if (oldirq == 0) |
| 107 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); | 131 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); |
| 108 | else | 132 | else if (oldirq != 5) |
| 109 | clear_irq(bus, oldirq); | 133 | clear_irq(bus, oldirq); |
| 110 | 134 | ||
| 111 | /* assign the new one */ | 135 | /* assign the new one */ |
| 112 | if (irq == 0) { | 136 | if (irq == 0) { |
| 113 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); | 137 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); |
| 114 | } else { | 138 | } else { |
| 139 | u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); | ||
| 140 | if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { | ||
| 141 | u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; | ||
| 142 | struct ssb_device *olddev = find_device(dev, oldipsflag); | ||
| 143 | if (olddev) | ||
| 144 | set_irq(olddev, 0); | ||
| 145 | } | ||
| 115 | irqflag <<= ipsflag_irq_shift[irq]; | 146 | irqflag <<= ipsflag_irq_shift[irq]; |
| 116 | irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); | 147 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
| 117 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | 148 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); |
| 118 | } | 149 | } |
| 150 | ssb_dprintk(KERN_INFO PFX | ||
| 151 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
| 152 | dev->id.coreid, oldirq+2, irq+2); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void print_irq(struct ssb_device *dev, unsigned int irq) | ||
| 156 | { | ||
| 157 | int i; | ||
| 158 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | ||
| 159 | ssb_dprintk(KERN_INFO PFX | ||
| 160 | "core 0x%04x, irq :", dev->id.coreid); | ||
| 161 | for (i = 0; i <= 6; i++) { | ||
| 162 | ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); | ||
| 163 | } | ||
| 164 | ssb_dprintk("\n"); | ||
| 165 | } | ||
| 166 | |||
| 167 | static void dump_irq(struct ssb_bus *bus) | ||
| 168 | { | ||
| 169 | int i; | ||
| 170 | for (i = 0; i < bus->nr_devices; i++) { | ||
| 171 | struct ssb_device *dev; | ||
| 172 | dev = &(bus->devices[i]); | ||
| 173 | print_irq(dev, ssb_mips_irq(dev)); | ||
| 174 | } | ||
| 119 | } | 175 | } |
| 120 | 176 | ||
| 121 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) | 177 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) |
| @@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
| 197 | 253 | ||
| 198 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ | 254 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ |
| 199 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { | 255 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { |
| 256 | int mips_irq; | ||
| 200 | dev = &(bus->devices[i]); | 257 | dev = &(bus->devices[i]); |
| 201 | dev->irq = ssb_mips_irq(dev) + 2; | 258 | mips_irq = ssb_mips_irq(dev); |
| 259 | if (mips_irq > 4) | ||
| 260 | dev->irq = 0; | ||
| 261 | else | ||
| 262 | dev->irq = mips_irq + 2; | ||
| 263 | if (dev->irq > 5) | ||
| 264 | continue; | ||
| 202 | switch (dev->id.coreid) { | 265 | switch (dev->id.coreid) { |
| 203 | case SSB_DEV_USB11_HOST: | 266 | case SSB_DEV_USB11_HOST: |
| 204 | /* shouldn't need a separate irq line for non-4710, most of them have a proper | 267 | /* shouldn't need a separate irq line for non-4710, most of them have a proper |
| 205 | * external usb controller on the pci */ | 268 | * external usb controller on the pci */ |
| 206 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { | 269 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { |
| 207 | set_irq(dev, irq++); | 270 | set_irq(dev, irq++); |
| 208 | break; | ||
| 209 | } | 271 | } |
| 272 | break; | ||
| 210 | /* fallthrough */ | 273 | /* fallthrough */ |
| 211 | case SSB_DEV_PCI: | 274 | case SSB_DEV_PCI: |
| 212 | case SSB_DEV_ETHERNET: | 275 | case SSB_DEV_ETHERNET: |
| @@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
| 220 | } | 283 | } |
| 221 | } | 284 | } |
| 222 | } | 285 | } |
| 286 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | ||
| 287 | dump_irq(bus); | ||
| 223 | 288 | ||
| 224 | ssb_mips_serial_init(mcore); | 289 | ssb_mips_serial_init(mcore); |
| 225 | ssb_mips_flash_detect(mcore); | 290 | ssb_mips_flash_detect(mcore); |
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbfadbac67e8..100e7a5c5ea1 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
| @@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) | |||
| 583 | ssb_printk("."); | 583 | ssb_printk("."); |
| 584 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); | 584 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); |
| 585 | if (err) { | 585 | if (err) { |
| 586 | ssb_printk("\n" KERN_NOTICE PFX | 586 | ssb_printk(KERN_NOTICE PFX |
| 587 | "Failed to write to SPROM.\n"); | 587 | "Failed to write to SPROM.\n"); |
| 588 | failed = 1; | 588 | failed = 1; |
| 589 | break; | 589 | break; |
| @@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) | |||
| 591 | } | 591 | } |
| 592 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); | 592 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); |
| 593 | if (err) { | 593 | if (err) { |
| 594 | ssb_printk("\n" KERN_NOTICE PFX | 594 | ssb_printk(KERN_NOTICE PFX |
| 595 | "Could not disable SPROM write access.\n"); | 595 | "Could not disable SPROM write access.\n"); |
| 596 | failed = 1; | 596 | failed = 1; |
| 597 | } | 597 | } |
| @@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
| 678 | sprom->board_rev = tuple.TupleData[1]; | 678 | sprom->board_rev = tuple.TupleData[1]; |
| 679 | break; | 679 | break; |
| 680 | case SSB_PCMCIA_CIS_PA: | 680 | case SSB_PCMCIA_CIS_PA: |
| 681 | GOTO_ERROR_ON(tuple.TupleDataLen != 9, | 681 | GOTO_ERROR_ON((tuple.TupleDataLen != 9) && |
| 682 | (tuple.TupleDataLen != 10), | ||
| 682 | "pa tpl size"); | 683 | "pa tpl size"); |
| 683 | sprom->pa0b0 = tuple.TupleData[1] | | 684 | sprom->pa0b0 = tuple.TupleData[1] | |
| 684 | ((u16)tuple.TupleData[2] << 8); | 685 | ((u16)tuple.TupleData[2] << 8); |
| @@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
| 718 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; | 719 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; |
| 719 | break; | 720 | break; |
| 720 | case SSB_PCMCIA_CIS_BFLAGS: | 721 | case SSB_PCMCIA_CIS_BFLAGS: |
| 721 | GOTO_ERROR_ON(tuple.TupleDataLen != 3, | 722 | GOTO_ERROR_ON((tuple.TupleDataLen != 3) && |
| 723 | (tuple.TupleDataLen != 5), | ||
| 722 | "bfl tpl size"); | 724 | "bfl tpl size"); |
| 723 | sprom->boardflags_lo = tuple.TupleData[1] | | 725 | sprom->boardflags_lo = tuple.TupleData[1] | |
| 724 | ((u16)tuple.TupleData[2] << 8); | 726 | ((u16)tuple.TupleData[2] << 8); |
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index baf83c6a9412..e3c3adc282e2 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c | |||
| @@ -45,6 +45,8 @@ Devices: [JR3] PCI force sensor board (jr3_pci) | |||
| 45 | #include <linux/delay.h> | 45 | #include <linux/delay.h> |
| 46 | #include <linux/ctype.h> | 46 | #include <linux/ctype.h> |
| 47 | #include <linux/firmware.h> | 47 | #include <linux/firmware.h> |
| 48 | #include <linux/jiffies.h> | ||
| 49 | #include <linux/timer.h> | ||
| 48 | #include "comedi_pci.h" | 50 | #include "comedi_pci.h" |
| 49 | #include "jr3_pci.h" | 51 | #include "jr3_pci.h" |
| 50 | 52 | ||
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 92121cf8c45c..5d9bab352c1d 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c | |||
| @@ -111,9 +111,13 @@ static const struct s626_board s626_boards[] = { | |||
| 111 | #define PCI_VENDOR_ID_S626 0x1131 | 111 | #define PCI_VENDOR_ID_S626 0x1131 |
| 112 | #define PCI_DEVICE_ID_S626 0x7146 | 112 | #define PCI_DEVICE_ID_S626 0x7146 |
| 113 | 113 | ||
| 114 | /* | ||
| 115 | * For devices with vendor:device id == 0x1131:0x7146 you must specify | ||
| 116 | * also subvendor:subdevice ids, because otherwise it will conflict with | ||
| 117 | * Philips SAA7146 media/dvb based cards. | ||
| 118 | */ | ||
| 114 | static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { | 119 | static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { |
| 115 | {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 120 | {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, 0x6000, 0x0272, 0, 0, 0}, |
| 116 | 0}, | ||
| 117 | {0} | 121 | {0} |
| 118 | }; | 122 | }; |
| 119 | 123 | ||
| @@ -499,25 +503,26 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) | |||
| 499 | resource_size_t resourceStart; | 503 | resource_size_t resourceStart; |
| 500 | dma_addr_t appdma; | 504 | dma_addr_t appdma; |
| 501 | struct comedi_subdevice *s; | 505 | struct comedi_subdevice *s; |
| 502 | struct pci_dev *pdev; | 506 | const struct pci_device_id *ids; |
| 507 | struct pci_dev *pdev = NULL; | ||
| 503 | 508 | ||
| 504 | if (alloc_private(dev, sizeof(struct s626_private)) < 0) | 509 | if (alloc_private(dev, sizeof(struct s626_private)) < 0) |
| 505 | return -ENOMEM; | 510 | return -ENOMEM; |
| 506 | 511 | ||
| 507 | for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, | 512 | for (i = 0; i < (ARRAY_SIZE(s626_pci_table) - 1) && !pdev; i++) { |
| 508 | NULL); pdev != NULL; | 513 | ids = &s626_pci_table[i]; |
| 509 | pdev = pci_get_device(PCI_VENDOR_ID_S626, | 514 | do { |
| 510 | PCI_DEVICE_ID_S626, pdev)) { | 515 | pdev = pci_get_subsys(ids->vendor, ids->device, ids->subvendor, |
| 511 | if (it->options[0] || it->options[1]) { | 516 | ids->subdevice, pdev); |
| 512 | if (pdev->bus->number == it->options[0] && | 517 | |
| 513 | PCI_SLOT(pdev->devfn) == it->options[1]) { | 518 | if ((it->options[0] || it->options[1]) && pdev) { |
| 514 | /* matches requested bus/slot */ | 519 | /* matches requested bus/slot */ |
| 520 | if (pdev->bus->number == it->options[0] && | ||
| 521 | PCI_SLOT(pdev->devfn) == it->options[1]) | ||
| 522 | break; | ||
| 523 | } else | ||
| 515 | break; | 524 | break; |
| 516 | } | 525 | } while (1); |
| 517 | } else { | ||
| 518 | /* no bus/slot specified */ | ||
| 519 | break; | ||
| 520 | } | ||
| 521 | } | 526 | } |
| 522 | devpriv->pdev = pdev; | 527 | devpriv->pdev = pdev; |
| 523 | 528 | ||
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c index a5e4acab089e..bb22347af60e 100644 --- a/drivers/staging/go7007/s2250-loader.c +++ b/drivers/staging/go7007/s2250-loader.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/smp_lock.h> | ||
| 20 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
| 21 | #include <dvb-usb.h> | 22 | #include <dvb-usb.h> |
| 22 | 23 | ||
diff --git a/drivers/staging/meilhaus/TODO b/drivers/staging/meilhaus/TODO index 6ec25203089c..d6ce39823de6 100644 --- a/drivers/staging/meilhaus/TODO +++ b/drivers/staging/meilhaus/TODO | |||
| @@ -7,4 +7,4 @@ TODO: | |||
| 7 | - possible comedi merge | 7 | - possible comedi merge |
| 8 | 8 | ||
| 9 | Please send cleanup patches to Greg Kroah-Hartman <greg@kroah.com> | 9 | Please send cleanup patches to Greg Kroah-Hartman <greg@kroah.com> |
| 10 | and CC: David Kiliani <mail@davidkiliani.de> | 10 | and CC: David Kiliani <mail@davidkiliani.de> and Meilhaus Support <support@meilhaus.de> |
diff --git a/drivers/staging/octeon/Makefile b/drivers/staging/octeon/Makefile index 3c839e37d37f..c0a583cc2227 100644 --- a/drivers/staging/octeon/Makefile +++ b/drivers/staging/octeon/Makefile | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | obj-${CONFIG_OCTEON_ETHERNET} := octeon-ethernet.o | 12 | obj-${CONFIG_OCTEON_ETHERNET} := octeon-ethernet.o |
| 13 | 13 | ||
| 14 | octeon-ethernet-objs := ethernet.o | 14 | octeon-ethernet-objs := ethernet.o |
| 15 | octeon-ethernet-objs += ethernet-common.o | ||
| 16 | octeon-ethernet-objs += ethernet-mdio.o | 15 | octeon-ethernet-objs += ethernet-mdio.o |
| 17 | octeon-ethernet-objs += ethernet-mem.o | 16 | octeon-ethernet-objs += ethernet-mem.o |
| 18 | octeon-ethernet-objs += ethernet-proc.o | 17 | octeon-ethernet-objs += ethernet-proc.o |
diff --git a/drivers/staging/octeon/ethernet-common.c b/drivers/staging/octeon/ethernet-common.c deleted file mode 100644 index 3e6f5b8cc63d..000000000000 --- a/drivers/staging/octeon/ethernet-common.c +++ /dev/null | |||
| @@ -1,328 +0,0 @@ | |||
| 1 | /********************************************************************** | ||
| 2 | * Author: Cavium Networks | ||
| 3 | * | ||
| 4 | * Contact: support@caviumnetworks.com | ||
| 5 | * This file is part of the OCTEON SDK | ||
| 6 | * | ||
| 7 | * Copyright (c) 2003-2007 Cavium Networks | ||
| 8 | * | ||
| 9 | * This file is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License, Version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This file is distributed in the hope that it will be useful, but | ||
| 14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty | ||
| 15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or | ||
| 16 | * NONINFRINGEMENT. See the GNU General Public License for more | ||
| 17 | * details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this file; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 22 | * or visit http://www.gnu.org/licenses/. | ||
| 23 | * | ||
| 24 | * This file may also be available under a different license from Cavium. | ||
| 25 | * Contact Cavium Networks for more information | ||
| 26 | **********************************************************************/ | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/mii.h> | ||
| 29 | #include <net/dst.h> | ||
| 30 | |||
| 31 | #include <asm/atomic.h> | ||
| 32 | #include <asm/octeon/octeon.h> | ||
| 33 | |||
| 34 | #include "ethernet-defines.h" | ||
| 35 | #include "ethernet-tx.h" | ||
| 36 | #include "ethernet-mdio.h" | ||
| 37 | #include "ethernet-util.h" | ||
| 38 | #include "octeon-ethernet.h" | ||
| 39 | #include "ethernet-common.h" | ||
| 40 | |||
| 41 | #include "cvmx-pip.h" | ||
| 42 | #include "cvmx-pko.h" | ||
| 43 | #include "cvmx-fau.h" | ||
| 44 | #include "cvmx-helper.h" | ||
| 45 | |||
| 46 | #include "cvmx-gmxx-defs.h" | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Get the low level ethernet statistics | ||
| 50 | * | ||
| 51 | * @dev: Device to get the statistics from | ||
| 52 | * Returns Pointer to the statistics | ||
| 53 | */ | ||
| 54 | static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) | ||
| 55 | { | ||
| 56 | cvmx_pip_port_status_t rx_status; | ||
| 57 | cvmx_pko_port_status_t tx_status; | ||
| 58 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 59 | |||
| 60 | if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) { | ||
| 61 | if (octeon_is_simulation()) { | ||
| 62 | /* The simulator doesn't support statistics */ | ||
| 63 | memset(&rx_status, 0, sizeof(rx_status)); | ||
| 64 | memset(&tx_status, 0, sizeof(tx_status)); | ||
| 65 | } else { | ||
| 66 | cvmx_pip_get_port_status(priv->port, 1, &rx_status); | ||
| 67 | cvmx_pko_get_port_status(priv->port, 1, &tx_status); | ||
| 68 | } | ||
| 69 | |||
| 70 | priv->stats.rx_packets += rx_status.inb_packets; | ||
| 71 | priv->stats.tx_packets += tx_status.packets; | ||
| 72 | priv->stats.rx_bytes += rx_status.inb_octets; | ||
| 73 | priv->stats.tx_bytes += tx_status.octets; | ||
| 74 | priv->stats.multicast += rx_status.multicast_packets; | ||
| 75 | priv->stats.rx_crc_errors += rx_status.inb_errors; | ||
| 76 | priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets; | ||
| 77 | |||
| 78 | /* | ||
| 79 | * The drop counter must be incremented atomically | ||
| 80 | * since the RX tasklet also increments it. | ||
| 81 | */ | ||
| 82 | #ifdef CONFIG_64BIT | ||
| 83 | atomic64_add(rx_status.dropped_packets, | ||
| 84 | (atomic64_t *)&priv->stats.rx_dropped); | ||
| 85 | #else | ||
| 86 | atomic_add(rx_status.dropped_packets, | ||
| 87 | (atomic_t *)&priv->stats.rx_dropped); | ||
| 88 | #endif | ||
| 89 | } | ||
| 90 | |||
| 91 | return &priv->stats; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Set the multicast list. Currently unimplemented. | ||
| 96 | * | ||
| 97 | * @dev: Device to work on | ||
| 98 | */ | ||
| 99 | static void cvm_oct_common_set_multicast_list(struct net_device *dev) | ||
| 100 | { | ||
| 101 | union cvmx_gmxx_prtx_cfg gmx_cfg; | ||
| 102 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 103 | int interface = INTERFACE(priv->port); | ||
| 104 | int index = INDEX(priv->port); | ||
| 105 | |||
| 106 | if ((interface < 2) | ||
| 107 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 108 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 109 | union cvmx_gmxx_rxx_adr_ctl control; | ||
| 110 | control.u64 = 0; | ||
| 111 | control.s.bcst = 1; /* Allow broadcast MAC addresses */ | ||
| 112 | |||
| 113 | if (dev->mc_list || (dev->flags & IFF_ALLMULTI) || | ||
| 114 | (dev->flags & IFF_PROMISC)) | ||
| 115 | /* Force accept multicast packets */ | ||
| 116 | control.s.mcst = 2; | ||
| 117 | else | ||
| 118 | /* Force reject multicat packets */ | ||
| 119 | control.s.mcst = 1; | ||
| 120 | |||
| 121 | if (dev->flags & IFF_PROMISC) | ||
| 122 | /* | ||
| 123 | * Reject matches if promisc. Since CAM is | ||
| 124 | * shut off, should accept everything. | ||
| 125 | */ | ||
| 126 | control.s.cam_mode = 0; | ||
| 127 | else | ||
| 128 | /* Filter packets based on the CAM */ | ||
| 129 | control.s.cam_mode = 1; | ||
| 130 | |||
| 131 | gmx_cfg.u64 = | ||
| 132 | cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); | ||
| 133 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 134 | gmx_cfg.u64 & ~1ull); | ||
| 135 | |||
| 136 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), | ||
| 137 | control.u64); | ||
| 138 | if (dev->flags & IFF_PROMISC) | ||
| 139 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN | ||
| 140 | (index, interface), 0); | ||
| 141 | else | ||
| 142 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN | ||
| 143 | (index, interface), 1); | ||
| 144 | |||
| 145 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 146 | gmx_cfg.u64); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * Set the hardware MAC address for a device | ||
| 152 | * | ||
| 153 | * @dev: Device to change the MAC address for | ||
| 154 | * @addr: Address structure to change it too. MAC address is addr + 2. | ||
| 155 | * Returns Zero on success | ||
| 156 | */ | ||
| 157 | static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) | ||
| 158 | { | ||
| 159 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 160 | union cvmx_gmxx_prtx_cfg gmx_cfg; | ||
| 161 | int interface = INTERFACE(priv->port); | ||
| 162 | int index = INDEX(priv->port); | ||
| 163 | |||
| 164 | memcpy(dev->dev_addr, addr + 2, 6); | ||
| 165 | |||
| 166 | if ((interface < 2) | ||
| 167 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 168 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 169 | int i; | ||
| 170 | uint8_t *ptr = addr; | ||
| 171 | uint64_t mac = 0; | ||
| 172 | for (i = 0; i < 6; i++) | ||
| 173 | mac = (mac << 8) | (uint64_t) (ptr[i + 2]); | ||
| 174 | |||
| 175 | gmx_cfg.u64 = | ||
| 176 | cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); | ||
| 177 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 178 | gmx_cfg.u64 & ~1ull); | ||
| 179 | |||
| 180 | cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); | ||
| 181 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), | ||
| 182 | ptr[2]); | ||
| 183 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), | ||
| 184 | ptr[3]); | ||
| 185 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), | ||
| 186 | ptr[4]); | ||
| 187 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), | ||
| 188 | ptr[5]); | ||
| 189 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), | ||
| 190 | ptr[6]); | ||
| 191 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), | ||
| 192 | ptr[7]); | ||
| 193 | cvm_oct_common_set_multicast_list(dev); | ||
| 194 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 195 | gmx_cfg.u64); | ||
| 196 | } | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | /** | ||
| 201 | * Change the link MTU. Unimplemented | ||
| 202 | * | ||
| 203 | * @dev: Device to change | ||
| 204 | * @new_mtu: The new MTU | ||
| 205 | * | ||
| 206 | * Returns Zero on success | ||
| 207 | */ | ||
| 208 | static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) | ||
| 209 | { | ||
| 210 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 211 | int interface = INTERFACE(priv->port); | ||
| 212 | int index = INDEX(priv->port); | ||
| 213 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | ||
| 214 | int vlan_bytes = 4; | ||
| 215 | #else | ||
| 216 | int vlan_bytes = 0; | ||
| 217 | #endif | ||
| 218 | |||
| 219 | /* | ||
| 220 | * Limit the MTU to make sure the ethernet packets are between | ||
| 221 | * 64 bytes and 65535 bytes. | ||
| 222 | */ | ||
| 223 | if ((new_mtu + 14 + 4 + vlan_bytes < 64) | ||
| 224 | || (new_mtu + 14 + 4 + vlan_bytes > 65392)) { | ||
| 225 | pr_err("MTU must be between %d and %d.\n", | ||
| 226 | 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); | ||
| 227 | return -EINVAL; | ||
| 228 | } | ||
| 229 | dev->mtu = new_mtu; | ||
| 230 | |||
| 231 | if ((interface < 2) | ||
| 232 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 233 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 234 | /* Add ethernet header and FCS, and VLAN if configured. */ | ||
| 235 | int max_packet = new_mtu + 14 + 4 + vlan_bytes; | ||
| 236 | |||
| 237 | if (OCTEON_IS_MODEL(OCTEON_CN3XXX) | ||
| 238 | || OCTEON_IS_MODEL(OCTEON_CN58XX)) { | ||
| 239 | /* Signal errors on packets larger than the MTU */ | ||
| 240 | cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), | ||
| 241 | max_packet); | ||
| 242 | } else { | ||
| 243 | /* | ||
| 244 | * Set the hardware to truncate packets larger | ||
| 245 | * than the MTU and smaller the 64 bytes. | ||
| 246 | */ | ||
| 247 | union cvmx_pip_frm_len_chkx frm_len_chk; | ||
| 248 | frm_len_chk.u64 = 0; | ||
| 249 | frm_len_chk.s.minlen = 64; | ||
| 250 | frm_len_chk.s.maxlen = max_packet; | ||
| 251 | cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), | ||
| 252 | frm_len_chk.u64); | ||
| 253 | } | ||
| 254 | /* | ||
| 255 | * Set the hardware to truncate packets larger than | ||
| 256 | * the MTU. The jabber register must be set to a | ||
| 257 | * multiple of 8 bytes, so round up. | ||
| 258 | */ | ||
| 259 | cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), | ||
| 260 | (max_packet + 7) & ~7u); | ||
| 261 | } | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * Per network device initialization | ||
| 267 | * | ||
| 268 | * @dev: Device to initialize | ||
| 269 | * Returns Zero on success | ||
| 270 | */ | ||
| 271 | int cvm_oct_common_init(struct net_device *dev) | ||
| 272 | { | ||
| 273 | static int count; | ||
| 274 | char mac[8] = { 0x00, 0x00, | ||
| 275 | octeon_bootinfo->mac_addr_base[0], | ||
| 276 | octeon_bootinfo->mac_addr_base[1], | ||
| 277 | octeon_bootinfo->mac_addr_base[2], | ||
| 278 | octeon_bootinfo->mac_addr_base[3], | ||
| 279 | octeon_bootinfo->mac_addr_base[4], | ||
| 280 | octeon_bootinfo->mac_addr_base[5] + count | ||
| 281 | }; | ||
| 282 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 283 | |||
| 284 | /* | ||
| 285 | * Force the interface to use the POW send if always_use_pow | ||
| 286 | * was specified or it is in the pow send list. | ||
| 287 | */ | ||
| 288 | if ((pow_send_group != -1) | ||
| 289 | && (always_use_pow || strstr(pow_send_list, dev->name))) | ||
| 290 | priv->queue = -1; | ||
| 291 | |||
| 292 | if (priv->queue != -1) { | ||
| 293 | dev->hard_start_xmit = cvm_oct_xmit; | ||
| 294 | if (USE_HW_TCPUDP_CHECKSUM) | ||
| 295 | dev->features |= NETIF_F_IP_CSUM; | ||
| 296 | } else | ||
| 297 | dev->hard_start_xmit = cvm_oct_xmit_pow; | ||
| 298 | count++; | ||
| 299 | |||
| 300 | dev->get_stats = cvm_oct_common_get_stats; | ||
| 301 | dev->set_mac_address = cvm_oct_common_set_mac_address; | ||
| 302 | dev->set_multicast_list = cvm_oct_common_set_multicast_list; | ||
| 303 | dev->change_mtu = cvm_oct_common_change_mtu; | ||
| 304 | dev->do_ioctl = cvm_oct_ioctl; | ||
| 305 | /* We do our own locking, Linux doesn't need to */ | ||
| 306 | dev->features |= NETIF_F_LLTX; | ||
| 307 | SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); | ||
| 308 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 309 | dev->poll_controller = cvm_oct_poll_controller; | ||
| 310 | #endif | ||
| 311 | |||
| 312 | cvm_oct_mdio_setup_device(dev); | ||
| 313 | dev->set_mac_address(dev, mac); | ||
| 314 | dev->change_mtu(dev, dev->mtu); | ||
| 315 | |||
| 316 | /* | ||
| 317 | * Zero out stats for port so we won't mistakenly show | ||
| 318 | * counters from the bootloader. | ||
| 319 | */ | ||
| 320 | memset(dev->get_stats(dev), 0, sizeof(struct net_device_stats)); | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | void cvm_oct_common_uninit(struct net_device *dev) | ||
| 326 | { | ||
| 327 | /* Currently nothing to do */ | ||
| 328 | } | ||
diff --git a/drivers/staging/octeon/ethernet-common.h b/drivers/staging/octeon/ethernet-common.h deleted file mode 100644 index 2bd9cd76a398..000000000000 --- a/drivers/staging/octeon/ethernet-common.h +++ /dev/null | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | /********************************************************************* | ||
| 2 | * Author: Cavium Networks | ||
| 3 | * | ||
| 4 | * Contact: support@caviumnetworks.com | ||
| 5 | * This file is part of the OCTEON SDK | ||
| 6 | * | ||
| 7 | * Copyright (c) 2003-2007 Cavium Networks | ||
| 8 | * | ||
| 9 | * This file is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License, Version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This file is distributed in the hope that it will be useful, but | ||
| 14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty | ||
| 15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or | ||
| 16 | * NONINFRINGEMENT. See the GNU General Public License for more | ||
| 17 | * details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this file; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 22 | * or visit http://www.gnu.org/licenses/. | ||
| 23 | * | ||
| 24 | * This file may also be available under a different license from Cavium. | ||
| 25 | * Contact Cavium Networks for more information | ||
| 26 | *********************************************************************/ | ||
| 27 | |||
| 28 | int cvm_oct_common_init(struct net_device *dev); | ||
| 29 | void cvm_oct_common_uninit(struct net_device *dev); | ||
diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h index 8f7374e7664c..f13131b03c33 100644 --- a/drivers/staging/octeon/ethernet-defines.h +++ b/drivers/staging/octeon/ethernet-defines.h | |||
| @@ -117,6 +117,8 @@ | |||
| 117 | 117 | ||
| 118 | /* Maximum number of packets to process per interrupt. */ | 118 | /* Maximum number of packets to process per interrupt. */ |
| 119 | #define MAX_RX_PACKETS 120 | 119 | #define MAX_RX_PACKETS 120 |
| 120 | /* Maximum number of SKBs to try to free per xmit packet. */ | ||
| 121 | #define MAX_SKB_TO_FREE 10 | ||
| 120 | #define MAX_OUT_QUEUE_DEPTH 1000 | 122 | #define MAX_OUT_QUEUE_DEPTH 1000 |
| 121 | 123 | ||
| 122 | #ifndef CONFIG_SMP | 124 | #ifndef CONFIG_SMP |
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 8579f1670d1e..8704133fe127 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | 33 | ||
| 34 | #include "ethernet-defines.h" | 34 | #include "ethernet-defines.h" |
| 35 | #include "octeon-ethernet.h" | 35 | #include "octeon-ethernet.h" |
| 36 | #include "ethernet-common.h" | ||
| 37 | #include "ethernet-util.h" | 36 | #include "ethernet-util.h" |
| 38 | 37 | ||
| 39 | #include "cvmx-helper.h" | 38 | #include "cvmx-helper.h" |
| @@ -265,7 +264,7 @@ static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) | |||
| 265 | return return_status; | 264 | return return_status; |
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | static int cvm_oct_rgmii_open(struct net_device *dev) | 267 | int cvm_oct_rgmii_open(struct net_device *dev) |
| 269 | { | 268 | { |
| 270 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 269 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 271 | struct octeon_ethernet *priv = netdev_priv(dev); | 270 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -286,7 +285,7 @@ static int cvm_oct_rgmii_open(struct net_device *dev) | |||
| 286 | return 0; | 285 | return 0; |
| 287 | } | 286 | } |
| 288 | 287 | ||
| 289 | static int cvm_oct_rgmii_stop(struct net_device *dev) | 288 | int cvm_oct_rgmii_stop(struct net_device *dev) |
| 290 | { | 289 | { |
| 291 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 290 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 292 | struct octeon_ethernet *priv = netdev_priv(dev); | 291 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -305,9 +304,7 @@ int cvm_oct_rgmii_init(struct net_device *dev) | |||
| 305 | int r; | 304 | int r; |
| 306 | 305 | ||
| 307 | cvm_oct_common_init(dev); | 306 | cvm_oct_common_init(dev); |
| 308 | dev->open = cvm_oct_rgmii_open; | 307 | dev->netdev_ops->ndo_stop(dev); |
| 309 | dev->stop = cvm_oct_rgmii_stop; | ||
| 310 | dev->stop(dev); | ||
| 311 | 308 | ||
| 312 | /* | 309 | /* |
| 313 | * Due to GMX errata in CN3XXX series chips, it is necessary | 310 | * Due to GMX errata in CN3XXX series chips, it is necessary |
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 58fa39c1d675..2b54996bd85d 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c | |||
| @@ -34,13 +34,12 @@ | |||
| 34 | #include "ethernet-defines.h" | 34 | #include "ethernet-defines.h" |
| 35 | #include "octeon-ethernet.h" | 35 | #include "octeon-ethernet.h" |
| 36 | #include "ethernet-util.h" | 36 | #include "ethernet-util.h" |
| 37 | #include "ethernet-common.h" | ||
| 38 | 37 | ||
| 39 | #include "cvmx-helper.h" | 38 | #include "cvmx-helper.h" |
| 40 | 39 | ||
| 41 | #include "cvmx-gmxx-defs.h" | 40 | #include "cvmx-gmxx-defs.h" |
| 42 | 41 | ||
| 43 | static int cvm_oct_sgmii_open(struct net_device *dev) | 42 | int cvm_oct_sgmii_open(struct net_device *dev) |
| 44 | { | 43 | { |
| 45 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 44 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 46 | struct octeon_ethernet *priv = netdev_priv(dev); | 45 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -61,7 +60,7 @@ static int cvm_oct_sgmii_open(struct net_device *dev) | |||
| 61 | return 0; | 60 | return 0; |
| 62 | } | 61 | } |
| 63 | 62 | ||
| 64 | static int cvm_oct_sgmii_stop(struct net_device *dev) | 63 | int cvm_oct_sgmii_stop(struct net_device *dev) |
| 65 | { | 64 | { |
| 66 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 65 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 67 | struct octeon_ethernet *priv = netdev_priv(dev); | 66 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -113,9 +112,7 @@ int cvm_oct_sgmii_init(struct net_device *dev) | |||
| 113 | { | 112 | { |
| 114 | struct octeon_ethernet *priv = netdev_priv(dev); | 113 | struct octeon_ethernet *priv = netdev_priv(dev); |
| 115 | cvm_oct_common_init(dev); | 114 | cvm_oct_common_init(dev); |
| 116 | dev->open = cvm_oct_sgmii_open; | 115 | dev->netdev_ops->ndo_stop(dev); |
| 117 | dev->stop = cvm_oct_sgmii_stop; | ||
| 118 | dev->stop(dev); | ||
| 119 | if (!octeon_is_simulation()) | 116 | if (!octeon_is_simulation()) |
| 120 | priv->poll = cvm_oct_sgmii_poll; | 117 | priv->poll = cvm_oct_sgmii_poll; |
| 121 | 118 | ||
diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index e0971bbe4ddc..66190b0cb68f 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | 33 | ||
| 34 | #include "ethernet-defines.h" | 34 | #include "ethernet-defines.h" |
| 35 | #include "octeon-ethernet.h" | 35 | #include "octeon-ethernet.h" |
| 36 | #include "ethernet-common.h" | ||
| 37 | #include "ethernet-util.h" | 36 | #include "ethernet-util.h" |
| 38 | 37 | ||
| 39 | #include "cvmx-spi.h" | 38 | #include "cvmx-spi.h" |
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 77b7122c8fdb..81a851390f1b 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | #include "ethernet-defines.h" | 48 | #include "ethernet-defines.h" |
| 49 | #include "octeon-ethernet.h" | 49 | #include "octeon-ethernet.h" |
| 50 | #include "ethernet-tx.h" | ||
| 50 | #include "ethernet-util.h" | 51 | #include "ethernet-util.h" |
| 51 | 52 | ||
| 52 | #include "cvmx-wqe.h" | 53 | #include "cvmx-wqe.h" |
| @@ -82,8 +83,10 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 82 | uint64_t old_scratch2; | 83 | uint64_t old_scratch2; |
| 83 | int dropped; | 84 | int dropped; |
| 84 | int qos; | 85 | int qos; |
| 86 | int queue_it_up; | ||
| 85 | struct octeon_ethernet *priv = netdev_priv(dev); | 87 | struct octeon_ethernet *priv = netdev_priv(dev); |
| 86 | int32_t in_use; | 88 | int32_t skb_to_free; |
| 89 | int32_t undo; | ||
| 87 | int32_t buffers_to_free; | 90 | int32_t buffers_to_free; |
| 88 | #if REUSE_SKBUFFS_WITHOUT_FREE | 91 | #if REUSE_SKBUFFS_WITHOUT_FREE |
| 89 | unsigned char *fpa_head; | 92 | unsigned char *fpa_head; |
| @@ -120,15 +123,15 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 120 | old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); | 123 | old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); |
| 121 | 124 | ||
| 122 | /* | 125 | /* |
| 123 | * Assume we're going to be able t osend this | 126 | * Fetch and increment the number of packets to be |
| 124 | * packet. Fetch and increment the number of pending | 127 | * freed. |
| 125 | * packets for output. | ||
| 126 | */ | 128 | */ |
| 127 | cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, | 129 | cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, |
| 128 | FAU_NUM_PACKET_BUFFERS_TO_FREE, | 130 | FAU_NUM_PACKET_BUFFERS_TO_FREE, |
| 129 | 0); | 131 | 0); |
| 130 | cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, | 132 | cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, |
| 131 | priv->fau + qos * 4, 1); | 133 | priv->fau + qos * 4, |
| 134 | MAX_SKB_TO_FREE); | ||
| 132 | } | 135 | } |
| 133 | 136 | ||
| 134 | /* | 137 | /* |
| @@ -253,10 +256,10 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 253 | 256 | ||
| 254 | /* | 257 | /* |
| 255 | * The skbuff will be reused without ever being freed. We must | 258 | * The skbuff will be reused without ever being freed. We must |
| 256 | * cleanup a bunch of Linux stuff. | 259 | * cleanup a bunch of core things. |
| 257 | */ | 260 | */ |
| 258 | dst_release(skb->dst); | 261 | dst_release(skb_dst(skb)); |
| 259 | skb->dst = NULL; | 262 | skb_dst_set(skb, NULL); |
| 260 | #ifdef CONFIG_XFRM | 263 | #ifdef CONFIG_XFRM |
| 261 | secpath_put(skb->sp); | 264 | secpath_put(skb->sp); |
| 262 | skb->sp = NULL; | 265 | skb->sp = NULL; |
| @@ -286,16 +289,30 @@ dont_put_skbuff_in_hw: | |||
| 286 | if (USE_ASYNC_IOBDMA) { | 289 | if (USE_ASYNC_IOBDMA) { |
| 287 | /* Get the number of skbuffs in use by the hardware */ | 290 | /* Get the number of skbuffs in use by the hardware */ |
| 288 | CVMX_SYNCIOBDMA; | 291 | CVMX_SYNCIOBDMA; |
| 289 | in_use = cvmx_scratch_read64(CVMX_SCR_SCRATCH); | 292 | skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH); |
| 290 | buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); | 293 | buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); |
| 291 | } else { | 294 | } else { |
| 292 | /* Get the number of skbuffs in use by the hardware */ | 295 | /* Get the number of skbuffs in use by the hardware */ |
| 293 | in_use = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, 1); | 296 | skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, |
| 297 | MAX_SKB_TO_FREE); | ||
| 294 | buffers_to_free = | 298 | buffers_to_free = |
| 295 | cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); | 299 | cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); |
| 296 | } | 300 | } |
| 297 | 301 | ||
| 298 | /* | 302 | /* |
| 303 | * We try to claim MAX_SKB_TO_FREE buffers. If there were not | ||
| 304 | * that many available, we have to un-claim (undo) any that | ||
| 305 | * were in excess. If skb_to_free is positive we will free | ||
| 306 | * that many buffers. | ||
| 307 | */ | ||
| 308 | undo = skb_to_free > 0 ? | ||
| 309 | MAX_SKB_TO_FREE : skb_to_free + MAX_SKB_TO_FREE; | ||
| 310 | if (undo > 0) | ||
| 311 | cvmx_fau_atomic_add32(priv->fau+qos*4, -undo); | ||
| 312 | skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? | ||
| 313 | MAX_SKB_TO_FREE : -skb_to_free; | ||
| 314 | |||
| 315 | /* | ||
| 299 | * If we're sending faster than the receive can free them then | 316 | * If we're sending faster than the receive can free them then |
| 300 | * don't do the HW free. | 317 | * don't do the HW free. |
| 301 | */ | 318 | */ |
| @@ -330,38 +347,31 @@ dont_put_skbuff_in_hw: | |||
| 330 | cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); | 347 | cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); |
| 331 | } | 348 | } |
| 332 | 349 | ||
| 350 | queue_it_up = 0; | ||
| 333 | if (unlikely(dropped)) { | 351 | if (unlikely(dropped)) { |
| 334 | dev_kfree_skb_any(skb); | 352 | dev_kfree_skb_any(skb); |
| 335 | cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); | ||
| 336 | priv->stats.tx_dropped++; | 353 | priv->stats.tx_dropped++; |
| 337 | } else { | 354 | } else { |
| 338 | if (USE_SKBUFFS_IN_HW) { | 355 | if (USE_SKBUFFS_IN_HW) { |
| 339 | /* Put this packet on the queue to be freed later */ | 356 | /* Put this packet on the queue to be freed later */ |
| 340 | if (pko_command.s.dontfree) | 357 | if (pko_command.s.dontfree) |
| 341 | skb_queue_tail(&priv->tx_free_list[qos], skb); | 358 | queue_it_up = 1; |
| 342 | else { | 359 | else |
| 343 | cvmx_fau_atomic_add32 | 360 | cvmx_fau_atomic_add32 |
| 344 | (FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); | 361 | (FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); |
| 345 | cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); | ||
| 346 | } | ||
| 347 | } else { | 362 | } else { |
| 348 | /* Put this packet on the queue to be freed later */ | 363 | /* Put this packet on the queue to be freed later */ |
| 349 | skb_queue_tail(&priv->tx_free_list[qos], skb); | 364 | queue_it_up = 1; |
| 350 | } | 365 | } |
| 351 | } | 366 | } |
| 352 | 367 | ||
| 353 | /* Free skbuffs not in use by the hardware, possibly two at a time */ | 368 | if (queue_it_up) { |
| 354 | if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) { | ||
| 355 | spin_lock(&priv->tx_free_list[qos].lock); | 369 | spin_lock(&priv->tx_free_list[qos].lock); |
| 356 | /* | 370 | __skb_queue_tail(&priv->tx_free_list[qos], skb); |
| 357 | * Check again now that we have the lock. It might | 371 | cvm_oct_free_tx_skbs(priv, skb_to_free, qos, 0); |
| 358 | * have changed. | ||
| 359 | */ | ||
| 360 | if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) | ||
| 361 | dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); | ||
| 362 | if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) | ||
| 363 | dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); | ||
| 364 | spin_unlock(&priv->tx_free_list[qos].lock); | 372 | spin_unlock(&priv->tx_free_list[qos].lock); |
| 373 | } else { | ||
| 374 | cvm_oct_free_tx_skbs(priv, skb_to_free, qos, 1); | ||
| 365 | } | 375 | } |
| 366 | 376 | ||
| 367 | return 0; | 377 | return 0; |
diff --git a/drivers/staging/octeon/ethernet-tx.h b/drivers/staging/octeon/ethernet-tx.h index 5106236fe981..c0bebf750bc0 100644 --- a/drivers/staging/octeon/ethernet-tx.h +++ b/drivers/staging/octeon/ethernet-tx.h | |||
| @@ -30,3 +30,28 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev); | |||
| 30 | int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, | 30 | int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, |
| 31 | int do_free, int qos); | 31 | int do_free, int qos); |
| 32 | void cvm_oct_tx_shutdown(struct net_device *dev); | 32 | void cvm_oct_tx_shutdown(struct net_device *dev); |
| 33 | |||
| 34 | /** | ||
| 35 | * Free dead transmit skbs. | ||
| 36 | * | ||
| 37 | * @priv: The driver data | ||
| 38 | * @skb_to_free: The number of SKBs to free (free none if negative). | ||
| 39 | * @qos: The queue to free from. | ||
| 40 | * @take_lock: If true, acquire the skb list lock. | ||
| 41 | */ | ||
| 42 | static inline void cvm_oct_free_tx_skbs(struct octeon_ethernet *priv, | ||
| 43 | int skb_to_free, | ||
| 44 | int qos, int take_lock) | ||
| 45 | { | ||
| 46 | /* Free skbuffs not in use by the hardware. */ | ||
| 47 | if (skb_to_free > 0) { | ||
| 48 | if (take_lock) | ||
| 49 | spin_lock(&priv->tx_free_list[qos].lock); | ||
| 50 | while (skb_to_free > 0) { | ||
| 51 | dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); | ||
| 52 | skb_to_free--; | ||
| 53 | } | ||
| 54 | if (take_lock) | ||
| 55 | spin_unlock(&priv->tx_free_list[qos].lock); | ||
| 56 | } | ||
| 57 | } | ||
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index f08eb32e04fc..0c2e7cc40f35 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c | |||
| @@ -33,14 +33,13 @@ | |||
| 33 | 33 | ||
| 34 | #include "ethernet-defines.h" | 34 | #include "ethernet-defines.h" |
| 35 | #include "octeon-ethernet.h" | 35 | #include "octeon-ethernet.h" |
| 36 | #include "ethernet-common.h" | ||
| 37 | #include "ethernet-util.h" | 36 | #include "ethernet-util.h" |
| 38 | 37 | ||
| 39 | #include "cvmx-helper.h" | 38 | #include "cvmx-helper.h" |
| 40 | 39 | ||
| 41 | #include "cvmx-gmxx-defs.h" | 40 | #include "cvmx-gmxx-defs.h" |
| 42 | 41 | ||
| 43 | static int cvm_oct_xaui_open(struct net_device *dev) | 42 | int cvm_oct_xaui_open(struct net_device *dev) |
| 44 | { | 43 | { |
| 45 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 44 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 46 | struct octeon_ethernet *priv = netdev_priv(dev); | 45 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -60,7 +59,7 @@ static int cvm_oct_xaui_open(struct net_device *dev) | |||
| 60 | return 0; | 59 | return 0; |
| 61 | } | 60 | } |
| 62 | 61 | ||
| 63 | static int cvm_oct_xaui_stop(struct net_device *dev) | 62 | int cvm_oct_xaui_stop(struct net_device *dev) |
| 64 | { | 63 | { |
| 65 | union cvmx_gmxx_prtx_cfg gmx_cfg; | 64 | union cvmx_gmxx_prtx_cfg gmx_cfg; |
| 66 | struct octeon_ethernet *priv = netdev_priv(dev); | 65 | struct octeon_ethernet *priv = netdev_priv(dev); |
| @@ -112,9 +111,7 @@ int cvm_oct_xaui_init(struct net_device *dev) | |||
| 112 | { | 111 | { |
| 113 | struct octeon_ethernet *priv = netdev_priv(dev); | 112 | struct octeon_ethernet *priv = netdev_priv(dev); |
| 114 | cvm_oct_common_init(dev); | 113 | cvm_oct_common_init(dev); |
| 115 | dev->open = cvm_oct_xaui_open; | 114 | dev->netdev_ops->ndo_stop(dev); |
| 116 | dev->stop = cvm_oct_xaui_stop; | ||
| 117 | dev->stop(dev); | ||
| 118 | if (!octeon_is_simulation()) | 115 | if (!octeon_is_simulation()) |
| 119 | priv->poll = cvm_oct_xaui_poll; | 116 | priv->poll = cvm_oct_xaui_poll; |
| 120 | 117 | ||
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index e8ef9e0b791f..b8479517dce2 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c | |||
| @@ -37,13 +37,14 @@ | |||
| 37 | #include <asm/octeon/octeon.h> | 37 | #include <asm/octeon/octeon.h> |
| 38 | 38 | ||
| 39 | #include "ethernet-defines.h" | 39 | #include "ethernet-defines.h" |
| 40 | #include "octeon-ethernet.h" | ||
| 40 | #include "ethernet-mem.h" | 41 | #include "ethernet-mem.h" |
| 41 | #include "ethernet-rx.h" | 42 | #include "ethernet-rx.h" |
| 42 | #include "ethernet-tx.h" | 43 | #include "ethernet-tx.h" |
| 44 | #include "ethernet-mdio.h" | ||
| 43 | #include "ethernet-util.h" | 45 | #include "ethernet-util.h" |
| 44 | #include "ethernet-proc.h" | 46 | #include "ethernet-proc.h" |
| 45 | #include "ethernet-common.h" | 47 | |
| 46 | #include "octeon-ethernet.h" | ||
| 47 | 48 | ||
| 48 | #include "cvmx-pip.h" | 49 | #include "cvmx-pip.h" |
| 49 | #include "cvmx-pko.h" | 50 | #include "cvmx-pko.h" |
| @@ -51,6 +52,7 @@ | |||
| 51 | #include "cvmx-ipd.h" | 52 | #include "cvmx-ipd.h" |
| 52 | #include "cvmx-helper.h" | 53 | #include "cvmx-helper.h" |
| 53 | 54 | ||
| 55 | #include "cvmx-gmxx-defs.h" | ||
| 54 | #include "cvmx-smix-defs.h" | 56 | #include "cvmx-smix-defs.h" |
| 55 | 57 | ||
| 56 | #if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \ | 58 | #if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \ |
| @@ -129,53 +131,55 @@ extern struct semaphore mdio_sem; | |||
| 129 | */ | 131 | */ |
| 130 | static void cvm_do_timer(unsigned long arg) | 132 | static void cvm_do_timer(unsigned long arg) |
| 131 | { | 133 | { |
| 134 | int32_t skb_to_free, undo; | ||
| 135 | int queues_per_port; | ||
| 136 | int qos; | ||
| 137 | struct octeon_ethernet *priv; | ||
| 132 | static int port; | 138 | static int port; |
| 133 | if (port < CVMX_PIP_NUM_INPUT_PORTS) { | ||
| 134 | if (cvm_oct_device[port]) { | ||
| 135 | int queues_per_port; | ||
| 136 | int qos; | ||
| 137 | struct octeon_ethernet *priv = | ||
| 138 | netdev_priv(cvm_oct_device[port]); | ||
| 139 | if (priv->poll) { | ||
| 140 | /* skip polling if we don't get the lock */ | ||
| 141 | if (!down_trylock(&mdio_sem)) { | ||
| 142 | priv->poll(cvm_oct_device[port]); | ||
| 143 | up(&mdio_sem); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | 139 | ||
| 147 | queues_per_port = cvmx_pko_get_num_queues(port); | 140 | if (port >= CVMX_PIP_NUM_INPUT_PORTS) { |
| 148 | /* Drain any pending packets in the free list */ | 141 | /* |
| 149 | for (qos = 0; qos < queues_per_port; qos++) { | 142 | * All ports have been polled. Start the next |
| 150 | if (skb_queue_len(&priv->tx_free_list[qos])) { | 143 | * iteration through the ports in one second. |
| 151 | spin_lock(&priv->tx_free_list[qos]. | 144 | */ |
| 152 | lock); | ||
| 153 | while (skb_queue_len | ||
| 154 | (&priv->tx_free_list[qos]) > | ||
| 155 | cvmx_fau_fetch_and_add32(priv-> | ||
| 156 | fau + | ||
| 157 | qos * 4, | ||
| 158 | 0)) | ||
| 159 | dev_kfree_skb(__skb_dequeue | ||
| 160 | (&priv-> | ||
| 161 | tx_free_list | ||
| 162 | [qos])); | ||
| 163 | spin_unlock(&priv->tx_free_list[qos]. | ||
| 164 | lock); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | cvm_oct_device[port]->get_stats(cvm_oct_device[port]); | ||
| 168 | } | ||
| 169 | port++; | ||
| 170 | /* Poll the next port in a 50th of a second. | ||
| 171 | This spreads the polling of ports out a little bit */ | ||
| 172 | mod_timer(&cvm_oct_poll_timer, jiffies + HZ / 50); | ||
| 173 | } else { | ||
| 174 | port = 0; | 145 | port = 0; |
| 175 | /* All ports have been polled. Start the next iteration through | ||
| 176 | the ports in one second */ | ||
| 177 | mod_timer(&cvm_oct_poll_timer, jiffies + HZ); | 146 | mod_timer(&cvm_oct_poll_timer, jiffies + HZ); |
| 147 | return; | ||
| 148 | } | ||
| 149 | if (!cvm_oct_device[port]) | ||
| 150 | goto out; | ||
| 151 | |||
| 152 | priv = netdev_priv(cvm_oct_device[port]); | ||
| 153 | if (priv->poll) { | ||
| 154 | /* skip polling if we don't get the lock */ | ||
| 155 | if (!down_trylock(&mdio_sem)) { | ||
| 156 | priv->poll(cvm_oct_device[port]); | ||
| 157 | up(&mdio_sem); | ||
| 158 | } | ||
| 178 | } | 159 | } |
| 160 | |||
| 161 | queues_per_port = cvmx_pko_get_num_queues(port); | ||
| 162 | /* Drain any pending packets in the free list */ | ||
| 163 | for (qos = 0; qos < queues_per_port; qos++) { | ||
| 164 | if (skb_queue_len(&priv->tx_free_list[qos]) == 0) | ||
| 165 | continue; | ||
| 166 | skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, | ||
| 167 | MAX_SKB_TO_FREE); | ||
| 168 | undo = skb_to_free > 0 ? | ||
| 169 | MAX_SKB_TO_FREE : skb_to_free + MAX_SKB_TO_FREE; | ||
| 170 | if (undo > 0) | ||
| 171 | cvmx_fau_atomic_add32(priv->fau+qos*4, -undo); | ||
| 172 | skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? | ||
| 173 | MAX_SKB_TO_FREE : -skb_to_free; | ||
| 174 | cvm_oct_free_tx_skbs(priv, skb_to_free, qos, 1); | ||
| 175 | } | ||
| 176 | cvm_oct_device[port]->netdev_ops->ndo_get_stats(cvm_oct_device[port]); | ||
| 177 | |||
| 178 | out: | ||
| 179 | port++; | ||
| 180 | /* Poll the next port in a 50th of a second. | ||
| 181 | This spreads the polling of ports out a little bit */ | ||
| 182 | mod_timer(&cvm_oct_poll_timer, jiffies + HZ / 50); | ||
| 179 | } | 183 | } |
| 180 | 184 | ||
| 181 | /** | 185 | /** |
| @@ -246,6 +250,362 @@ int cvm_oct_free_work(void *work_queue_entry) | |||
| 246 | EXPORT_SYMBOL(cvm_oct_free_work); | 250 | EXPORT_SYMBOL(cvm_oct_free_work); |
| 247 | 251 | ||
| 248 | /** | 252 | /** |
| 253 | * Get the low level ethernet statistics | ||
| 254 | * | ||
| 255 | * @dev: Device to get the statistics from | ||
| 256 | * Returns Pointer to the statistics | ||
| 257 | */ | ||
| 258 | static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) | ||
| 259 | { | ||
| 260 | cvmx_pip_port_status_t rx_status; | ||
| 261 | cvmx_pko_port_status_t tx_status; | ||
| 262 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 263 | |||
| 264 | if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) { | ||
| 265 | if (octeon_is_simulation()) { | ||
| 266 | /* The simulator doesn't support statistics */ | ||
| 267 | memset(&rx_status, 0, sizeof(rx_status)); | ||
| 268 | memset(&tx_status, 0, sizeof(tx_status)); | ||
| 269 | } else { | ||
| 270 | cvmx_pip_get_port_status(priv->port, 1, &rx_status); | ||
| 271 | cvmx_pko_get_port_status(priv->port, 1, &tx_status); | ||
| 272 | } | ||
| 273 | |||
| 274 | priv->stats.rx_packets += rx_status.inb_packets; | ||
| 275 | priv->stats.tx_packets += tx_status.packets; | ||
| 276 | priv->stats.rx_bytes += rx_status.inb_octets; | ||
| 277 | priv->stats.tx_bytes += tx_status.octets; | ||
| 278 | priv->stats.multicast += rx_status.multicast_packets; | ||
| 279 | priv->stats.rx_crc_errors += rx_status.inb_errors; | ||
| 280 | priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets; | ||
| 281 | |||
| 282 | /* | ||
| 283 | * The drop counter must be incremented atomically | ||
| 284 | * since the RX tasklet also increments it. | ||
| 285 | */ | ||
| 286 | #ifdef CONFIG_64BIT | ||
| 287 | atomic64_add(rx_status.dropped_packets, | ||
| 288 | (atomic64_t *)&priv->stats.rx_dropped); | ||
| 289 | #else | ||
| 290 | atomic_add(rx_status.dropped_packets, | ||
| 291 | (atomic_t *)&priv->stats.rx_dropped); | ||
| 292 | #endif | ||
| 293 | } | ||
| 294 | |||
| 295 | return &priv->stats; | ||
| 296 | } | ||
| 297 | |||
| 298 | /** | ||
| 299 | * Change the link MTU. Unimplemented | ||
| 300 | * | ||
| 301 | * @dev: Device to change | ||
| 302 | * @new_mtu: The new MTU | ||
| 303 | * | ||
| 304 | * Returns Zero on success | ||
| 305 | */ | ||
| 306 | static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) | ||
| 307 | { | ||
| 308 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 309 | int interface = INTERFACE(priv->port); | ||
| 310 | int index = INDEX(priv->port); | ||
| 311 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | ||
| 312 | int vlan_bytes = 4; | ||
| 313 | #else | ||
| 314 | int vlan_bytes = 0; | ||
| 315 | #endif | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Limit the MTU to make sure the ethernet packets are between | ||
| 319 | * 64 bytes and 65535 bytes. | ||
| 320 | */ | ||
| 321 | if ((new_mtu + 14 + 4 + vlan_bytes < 64) | ||
| 322 | || (new_mtu + 14 + 4 + vlan_bytes > 65392)) { | ||
| 323 | pr_err("MTU must be between %d and %d.\n", | ||
| 324 | 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); | ||
| 325 | return -EINVAL; | ||
| 326 | } | ||
| 327 | dev->mtu = new_mtu; | ||
| 328 | |||
| 329 | if ((interface < 2) | ||
| 330 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 331 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 332 | /* Add ethernet header and FCS, and VLAN if configured. */ | ||
| 333 | int max_packet = new_mtu + 14 + 4 + vlan_bytes; | ||
| 334 | |||
| 335 | if (OCTEON_IS_MODEL(OCTEON_CN3XXX) | ||
| 336 | || OCTEON_IS_MODEL(OCTEON_CN58XX)) { | ||
| 337 | /* Signal errors on packets larger than the MTU */ | ||
| 338 | cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), | ||
| 339 | max_packet); | ||
| 340 | } else { | ||
| 341 | /* | ||
| 342 | * Set the hardware to truncate packets larger | ||
| 343 | * than the MTU and smaller the 64 bytes. | ||
| 344 | */ | ||
| 345 | union cvmx_pip_frm_len_chkx frm_len_chk; | ||
| 346 | frm_len_chk.u64 = 0; | ||
| 347 | frm_len_chk.s.minlen = 64; | ||
| 348 | frm_len_chk.s.maxlen = max_packet; | ||
| 349 | cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), | ||
| 350 | frm_len_chk.u64); | ||
| 351 | } | ||
| 352 | /* | ||
| 353 | * Set the hardware to truncate packets larger than | ||
| 354 | * the MTU. The jabber register must be set to a | ||
| 355 | * multiple of 8 bytes, so round up. | ||
| 356 | */ | ||
| 357 | cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), | ||
| 358 | (max_packet + 7) & ~7u); | ||
| 359 | } | ||
| 360 | return 0; | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Set the multicast list. Currently unimplemented. | ||
| 365 | * | ||
| 366 | * @dev: Device to work on | ||
| 367 | */ | ||
| 368 | static void cvm_oct_common_set_multicast_list(struct net_device *dev) | ||
| 369 | { | ||
| 370 | union cvmx_gmxx_prtx_cfg gmx_cfg; | ||
| 371 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 372 | int interface = INTERFACE(priv->port); | ||
| 373 | int index = INDEX(priv->port); | ||
| 374 | |||
| 375 | if ((interface < 2) | ||
| 376 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 377 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 378 | union cvmx_gmxx_rxx_adr_ctl control; | ||
| 379 | control.u64 = 0; | ||
| 380 | control.s.bcst = 1; /* Allow broadcast MAC addresses */ | ||
| 381 | |||
| 382 | if (dev->mc_list || (dev->flags & IFF_ALLMULTI) || | ||
| 383 | (dev->flags & IFF_PROMISC)) | ||
| 384 | /* Force accept multicast packets */ | ||
| 385 | control.s.mcst = 2; | ||
| 386 | else | ||
| 387 | /* Force reject multicat packets */ | ||
| 388 | control.s.mcst = 1; | ||
| 389 | |||
| 390 | if (dev->flags & IFF_PROMISC) | ||
| 391 | /* | ||
| 392 | * Reject matches if promisc. Since CAM is | ||
| 393 | * shut off, should accept everything. | ||
| 394 | */ | ||
| 395 | control.s.cam_mode = 0; | ||
| 396 | else | ||
| 397 | /* Filter packets based on the CAM */ | ||
| 398 | control.s.cam_mode = 1; | ||
| 399 | |||
| 400 | gmx_cfg.u64 = | ||
| 401 | cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); | ||
| 402 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 403 | gmx_cfg.u64 & ~1ull); | ||
| 404 | |||
| 405 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), | ||
| 406 | control.u64); | ||
| 407 | if (dev->flags & IFF_PROMISC) | ||
| 408 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN | ||
| 409 | (index, interface), 0); | ||
| 410 | else | ||
| 411 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN | ||
| 412 | (index, interface), 1); | ||
| 413 | |||
| 414 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 415 | gmx_cfg.u64); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * Set the hardware MAC address for a device | ||
| 421 | * | ||
| 422 | * @dev: Device to change the MAC address for | ||
| 423 | * @addr: Address structure to change it too. MAC address is addr + 2. | ||
| 424 | * Returns Zero on success | ||
| 425 | */ | ||
| 426 | static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) | ||
| 427 | { | ||
| 428 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 429 | union cvmx_gmxx_prtx_cfg gmx_cfg; | ||
| 430 | int interface = INTERFACE(priv->port); | ||
| 431 | int index = INDEX(priv->port); | ||
| 432 | |||
| 433 | memcpy(dev->dev_addr, addr + 2, 6); | ||
| 434 | |||
| 435 | if ((interface < 2) | ||
| 436 | && (cvmx_helper_interface_get_mode(interface) != | ||
| 437 | CVMX_HELPER_INTERFACE_MODE_SPI)) { | ||
| 438 | int i; | ||
| 439 | uint8_t *ptr = addr; | ||
| 440 | uint64_t mac = 0; | ||
| 441 | for (i = 0; i < 6; i++) | ||
| 442 | mac = (mac << 8) | (uint64_t) (ptr[i + 2]); | ||
| 443 | |||
| 444 | gmx_cfg.u64 = | ||
| 445 | cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); | ||
| 446 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 447 | gmx_cfg.u64 & ~1ull); | ||
| 448 | |||
| 449 | cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); | ||
| 450 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), | ||
| 451 | ptr[2]); | ||
| 452 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), | ||
| 453 | ptr[3]); | ||
| 454 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), | ||
| 455 | ptr[4]); | ||
| 456 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), | ||
| 457 | ptr[5]); | ||
| 458 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), | ||
| 459 | ptr[6]); | ||
| 460 | cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), | ||
| 461 | ptr[7]); | ||
| 462 | cvm_oct_common_set_multicast_list(dev); | ||
| 463 | cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), | ||
| 464 | gmx_cfg.u64); | ||
| 465 | } | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | /** | ||
| 470 | * Per network device initialization | ||
| 471 | * | ||
| 472 | * @dev: Device to initialize | ||
| 473 | * Returns Zero on success | ||
| 474 | */ | ||
| 475 | int cvm_oct_common_init(struct net_device *dev) | ||
| 476 | { | ||
| 477 | static int count; | ||
| 478 | char mac[8] = { 0x00, 0x00, | ||
| 479 | octeon_bootinfo->mac_addr_base[0], | ||
| 480 | octeon_bootinfo->mac_addr_base[1], | ||
| 481 | octeon_bootinfo->mac_addr_base[2], | ||
| 482 | octeon_bootinfo->mac_addr_base[3], | ||
| 483 | octeon_bootinfo->mac_addr_base[4], | ||
| 484 | octeon_bootinfo->mac_addr_base[5] + count | ||
| 485 | }; | ||
| 486 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
| 487 | |||
| 488 | /* | ||
| 489 | * Force the interface to use the POW send if always_use_pow | ||
| 490 | * was specified or it is in the pow send list. | ||
| 491 | */ | ||
| 492 | if ((pow_send_group != -1) | ||
| 493 | && (always_use_pow || strstr(pow_send_list, dev->name))) | ||
| 494 | priv->queue = -1; | ||
| 495 | |||
| 496 | if (priv->queue != -1 && USE_HW_TCPUDP_CHECKSUM) | ||
| 497 | dev->features |= NETIF_F_IP_CSUM; | ||
| 498 | |||
| 499 | count++; | ||
| 500 | |||
| 501 | /* We do our own locking, Linux doesn't need to */ | ||
| 502 | dev->features |= NETIF_F_LLTX; | ||
| 503 | SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); | ||
| 504 | |||
| 505 | cvm_oct_mdio_setup_device(dev); | ||
| 506 | dev->netdev_ops->ndo_set_mac_address(dev, mac); | ||
| 507 | dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); | ||
| 508 | |||
| 509 | /* | ||
| 510 | * Zero out stats for port so we won't mistakenly show | ||
| 511 | * counters from the bootloader. | ||
| 512 | */ | ||
| 513 | memset(dev->netdev_ops->ndo_get_stats(dev), 0, | ||
| 514 | sizeof(struct net_device_stats)); | ||
| 515 | |||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | void cvm_oct_common_uninit(struct net_device *dev) | ||
| 520 | { | ||
| 521 | /* Currently nothing to do */ | ||
| 522 | } | ||
| 523 | |||
| 524 | static const struct net_device_ops cvm_oct_npi_netdev_ops = { | ||
| 525 | .ndo_init = cvm_oct_common_init, | ||
| 526 | .ndo_uninit = cvm_oct_common_uninit, | ||
| 527 | .ndo_start_xmit = cvm_oct_xmit, | ||
| 528 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 529 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 530 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 531 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 532 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 533 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 534 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 535 | #endif | ||
| 536 | }; | ||
| 537 | static const struct net_device_ops cvm_oct_xaui_netdev_ops = { | ||
| 538 | .ndo_init = cvm_oct_xaui_init, | ||
| 539 | .ndo_uninit = cvm_oct_xaui_uninit, | ||
| 540 | .ndo_open = cvm_oct_xaui_open, | ||
| 541 | .ndo_stop = cvm_oct_xaui_stop, | ||
| 542 | .ndo_start_xmit = cvm_oct_xmit, | ||
| 543 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 544 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 545 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 546 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 547 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 548 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 549 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 550 | #endif | ||
| 551 | }; | ||
| 552 | static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { | ||
| 553 | .ndo_init = cvm_oct_sgmii_init, | ||
| 554 | .ndo_uninit = cvm_oct_sgmii_uninit, | ||
| 555 | .ndo_open = cvm_oct_sgmii_open, | ||
| 556 | .ndo_stop = cvm_oct_sgmii_stop, | ||
| 557 | .ndo_start_xmit = cvm_oct_xmit, | ||
| 558 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 559 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 560 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 561 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 562 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 563 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 564 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 565 | #endif | ||
| 566 | }; | ||
| 567 | static const struct net_device_ops cvm_oct_spi_netdev_ops = { | ||
| 568 | .ndo_init = cvm_oct_spi_init, | ||
| 569 | .ndo_uninit = cvm_oct_spi_uninit, | ||
| 570 | .ndo_start_xmit = cvm_oct_xmit, | ||
| 571 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 572 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 573 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 574 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 575 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 576 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 577 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 578 | #endif | ||
| 579 | }; | ||
| 580 | static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { | ||
| 581 | .ndo_init = cvm_oct_rgmii_init, | ||
| 582 | .ndo_uninit = cvm_oct_rgmii_uninit, | ||
| 583 | .ndo_open = cvm_oct_rgmii_open, | ||
| 584 | .ndo_stop = cvm_oct_rgmii_stop, | ||
| 585 | .ndo_start_xmit = cvm_oct_xmit, | ||
| 586 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 587 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 588 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 589 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 590 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 591 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 592 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 593 | #endif | ||
| 594 | }; | ||
| 595 | static const struct net_device_ops cvm_oct_pow_netdev_ops = { | ||
| 596 | .ndo_init = cvm_oct_common_init, | ||
| 597 | .ndo_start_xmit = cvm_oct_xmit_pow, | ||
| 598 | .ndo_set_multicast_list = cvm_oct_common_set_multicast_list, | ||
| 599 | .ndo_set_mac_address = cvm_oct_common_set_mac_address, | ||
| 600 | .ndo_do_ioctl = cvm_oct_ioctl, | ||
| 601 | .ndo_change_mtu = cvm_oct_common_change_mtu, | ||
| 602 | .ndo_get_stats = cvm_oct_common_get_stats, | ||
| 603 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 604 | .ndo_poll_controller = cvm_oct_poll_controller, | ||
| 605 | #endif | ||
| 606 | }; | ||
| 607 | |||
| 608 | /** | ||
| 249 | * Module/ driver initialization. Creates the linux network | 609 | * Module/ driver initialization. Creates the linux network |
| 250 | * devices. | 610 | * devices. |
| 251 | * | 611 | * |
| @@ -303,7 +663,7 @@ static int __init cvm_oct_init_module(void) | |||
| 303 | struct octeon_ethernet *priv = netdev_priv(dev); | 663 | struct octeon_ethernet *priv = netdev_priv(dev); |
| 304 | memset(priv, 0, sizeof(struct octeon_ethernet)); | 664 | memset(priv, 0, sizeof(struct octeon_ethernet)); |
| 305 | 665 | ||
| 306 | dev->init = cvm_oct_common_init; | 666 | dev->netdev_ops = &cvm_oct_pow_netdev_ops; |
| 307 | priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; | 667 | priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; |
| 308 | priv->port = CVMX_PIP_NUM_INPUT_PORTS; | 668 | priv->port = CVMX_PIP_NUM_INPUT_PORTS; |
| 309 | priv->queue = -1; | 669 | priv->queue = -1; |
| @@ -372,44 +732,38 @@ static int __init cvm_oct_init_module(void) | |||
| 372 | break; | 732 | break; |
| 373 | 733 | ||
| 374 | case CVMX_HELPER_INTERFACE_MODE_NPI: | 734 | case CVMX_HELPER_INTERFACE_MODE_NPI: |
| 375 | dev->init = cvm_oct_common_init; | 735 | dev->netdev_ops = &cvm_oct_npi_netdev_ops; |
| 376 | dev->uninit = cvm_oct_common_uninit; | ||
| 377 | strcpy(dev->name, "npi%d"); | 736 | strcpy(dev->name, "npi%d"); |
| 378 | break; | 737 | break; |
| 379 | 738 | ||
| 380 | case CVMX_HELPER_INTERFACE_MODE_XAUI: | 739 | case CVMX_HELPER_INTERFACE_MODE_XAUI: |
| 381 | dev->init = cvm_oct_xaui_init; | 740 | dev->netdev_ops = &cvm_oct_xaui_netdev_ops; |
| 382 | dev->uninit = cvm_oct_xaui_uninit; | ||
| 383 | strcpy(dev->name, "xaui%d"); | 741 | strcpy(dev->name, "xaui%d"); |
| 384 | break; | 742 | break; |
| 385 | 743 | ||
| 386 | case CVMX_HELPER_INTERFACE_MODE_LOOP: | 744 | case CVMX_HELPER_INTERFACE_MODE_LOOP: |
| 387 | dev->init = cvm_oct_common_init; | 745 | dev->netdev_ops = &cvm_oct_npi_netdev_ops; |
| 388 | dev->uninit = cvm_oct_common_uninit; | ||
| 389 | strcpy(dev->name, "loop%d"); | 746 | strcpy(dev->name, "loop%d"); |
| 390 | break; | 747 | break; |
| 391 | 748 | ||
| 392 | case CVMX_HELPER_INTERFACE_MODE_SGMII: | 749 | case CVMX_HELPER_INTERFACE_MODE_SGMII: |
| 393 | dev->init = cvm_oct_sgmii_init; | 750 | dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; |
| 394 | dev->uninit = cvm_oct_sgmii_uninit; | ||
| 395 | strcpy(dev->name, "eth%d"); | 751 | strcpy(dev->name, "eth%d"); |
| 396 | break; | 752 | break; |
| 397 | 753 | ||
| 398 | case CVMX_HELPER_INTERFACE_MODE_SPI: | 754 | case CVMX_HELPER_INTERFACE_MODE_SPI: |
| 399 | dev->init = cvm_oct_spi_init; | 755 | dev->netdev_ops = &cvm_oct_spi_netdev_ops; |
| 400 | dev->uninit = cvm_oct_spi_uninit; | ||
| 401 | strcpy(dev->name, "spi%d"); | 756 | strcpy(dev->name, "spi%d"); |
| 402 | break; | 757 | break; |
| 403 | 758 | ||
| 404 | case CVMX_HELPER_INTERFACE_MODE_RGMII: | 759 | case CVMX_HELPER_INTERFACE_MODE_RGMII: |
| 405 | case CVMX_HELPER_INTERFACE_MODE_GMII: | 760 | case CVMX_HELPER_INTERFACE_MODE_GMII: |
| 406 | dev->init = cvm_oct_rgmii_init; | 761 | dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; |
| 407 | dev->uninit = cvm_oct_rgmii_uninit; | ||
| 408 | strcpy(dev->name, "eth%d"); | 762 | strcpy(dev->name, "eth%d"); |
| 409 | break; | 763 | break; |
| 410 | } | 764 | } |
| 411 | 765 | ||
| 412 | if (!dev->init) { | 766 | if (!dev->netdev_ops) { |
| 413 | kfree(dev); | 767 | kfree(dev); |
| 414 | } else if (register_netdev(dev) < 0) { | 768 | } else if (register_netdev(dev) < 0) { |
| 415 | pr_err("Failed to register ethernet device " | 769 | pr_err("Failed to register ethernet device " |
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index b3199076ef5e..3aef9878fc0a 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h | |||
| @@ -111,12 +111,23 @@ static inline int cvm_oct_transmit(struct net_device *dev, | |||
| 111 | 111 | ||
| 112 | extern int cvm_oct_rgmii_init(struct net_device *dev); | 112 | extern int cvm_oct_rgmii_init(struct net_device *dev); |
| 113 | extern void cvm_oct_rgmii_uninit(struct net_device *dev); | 113 | extern void cvm_oct_rgmii_uninit(struct net_device *dev); |
| 114 | extern int cvm_oct_rgmii_open(struct net_device *dev); | ||
| 115 | extern int cvm_oct_rgmii_stop(struct net_device *dev); | ||
| 116 | |||
| 114 | extern int cvm_oct_sgmii_init(struct net_device *dev); | 117 | extern int cvm_oct_sgmii_init(struct net_device *dev); |
| 115 | extern void cvm_oct_sgmii_uninit(struct net_device *dev); | 118 | extern void cvm_oct_sgmii_uninit(struct net_device *dev); |
| 119 | extern int cvm_oct_sgmii_open(struct net_device *dev); | ||
| 120 | extern int cvm_oct_sgmii_stop(struct net_device *dev); | ||
| 121 | |||
| 116 | extern int cvm_oct_spi_init(struct net_device *dev); | 122 | extern int cvm_oct_spi_init(struct net_device *dev); |
| 117 | extern void cvm_oct_spi_uninit(struct net_device *dev); | 123 | extern void cvm_oct_spi_uninit(struct net_device *dev); |
| 118 | extern int cvm_oct_xaui_init(struct net_device *dev); | 124 | extern int cvm_oct_xaui_init(struct net_device *dev); |
| 119 | extern void cvm_oct_xaui_uninit(struct net_device *dev); | 125 | extern void cvm_oct_xaui_uninit(struct net_device *dev); |
| 126 | extern int cvm_oct_xaui_open(struct net_device *dev); | ||
| 127 | extern int cvm_oct_xaui_stop(struct net_device *dev); | ||
| 128 | |||
| 129 | extern int cvm_oct_common_init(struct net_device *dev); | ||
| 130 | extern void cvm_oct_common_uninit(struct net_device *dev); | ||
| 120 | 131 | ||
| 121 | extern int always_use_pow; | 132 | extern int always_use_pow; |
| 122 | extern int pow_send_group; | 133 | extern int pow_send_group; |
diff --git a/drivers/staging/rspiusb/rspiusb.c b/drivers/staging/rspiusb/rspiusb.c index 1cdfe69585ea..2f8155c1968b 100644 --- a/drivers/staging/rspiusb/rspiusb.c +++ b/drivers/staging/rspiusb/rspiusb.c | |||
| @@ -444,8 +444,7 @@ static void piusb_write_bulk_callback(struct urb *urb) | |||
| 444 | __func__, status); | 444 | __func__, status); |
| 445 | 445 | ||
| 446 | pdx->pendingWrite = 0; | 446 | pdx->pendingWrite = 0; |
| 447 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | 447 | kfree(urb->transfer_buffer); |
| 448 | urb->transfer_buffer, urb->transfer_dma); | ||
| 449 | } | 448 | } |
| 450 | 449 | ||
| 451 | int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, | 450 | int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, |
| @@ -457,9 +456,7 @@ int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, | |||
| 457 | 456 | ||
| 458 | urb = usb_alloc_urb(0, GFP_KERNEL); | 457 | urb = usb_alloc_urb(0, GFP_KERNEL); |
| 459 | if (urb != NULL) { | 458 | if (urb != NULL) { |
| 460 | kbuf = | 459 | kbuf = kmalloc(len, GFP_KERNEL); |
| 461 | usb_buffer_alloc(pdx->udev, len, GFP_KERNEL, | ||
| 462 | &urb->transfer_dma); | ||
| 463 | if (!kbuf) { | 460 | if (!kbuf) { |
| 464 | dev_err(&pdx->udev->dev, "buffer_alloc failed\n"); | 461 | dev_err(&pdx->udev->dev, "buffer_alloc failed\n"); |
| 465 | return -ENOMEM; | 462 | return -ENOMEM; |
| @@ -470,7 +467,6 @@ int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, | |||
| 470 | } | 467 | } |
| 471 | usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf, | 468 | usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf, |
| 472 | len, piusb_write_bulk_callback, pdx); | 469 | len, piusb_write_bulk_callback, pdx); |
| 473 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 474 | err = usb_submit_urb(urb, GFP_KERNEL); | 470 | err = usb_submit_urb(urb, GFP_KERNEL); |
| 475 | if (err) { | 471 | if (err) { |
| 476 | dev_err(&pdx->udev->dev, | 472 | dev_err(&pdx->udev->dev, |
| @@ -641,7 +637,7 @@ static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx) | |||
| 641 | numPagesRequired = | 637 | numPagesRequired = |
| 642 | ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; | 638 | ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; |
| 643 | dbg("Number of pages needed = %d", numPagesRequired); | 639 | dbg("Number of pages needed = %d", numPagesRequired); |
| 644 | maplist_p = vmalloc(numPagesRequired * sizeof(struct page)); | 640 | maplist_p = vmalloc(numPagesRequired * sizeof(struct page *)); |
| 645 | if (!maplist_p) { | 641 | if (!maplist_p) { |
| 646 | dbg("Can't Allocate Memory for maplist_p"); | 642 | dbg("Can't Allocate Memory for maplist_p"); |
| 647 | return -ENOMEM; | 643 | return -ENOMEM; |
| @@ -712,9 +708,7 @@ static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx) | |||
| 712 | usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i], | 708 | usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i], |
| 713 | pdx->udev, | 709 | pdx->udev, |
| 714 | epAddr, | 710 | epAddr, |
| 715 | (dma_addr_t *) sg_dma_address(&pdx-> | 711 | NULL, // non-DMA HC? buy a better hardware |
| 716 | sgl[frameInfo] | ||
| 717 | [i]), | ||
| 718 | sg_dma_len(&pdx->sgl[frameInfo][i]), | 712 | sg_dma_len(&pdx->sgl[frameInfo][i]), |
| 719 | piusb_readPIXEL_callback, (void *)pdx); | 713 | piusb_readPIXEL_callback, (void *)pdx); |
| 720 | pdx->PixelUrb[frameInfo][i]->transfer_dma = | 714 | pdx->PixelUrb[frameInfo][i]->transfer_dma = |
diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h index 5e5b3f2b7eb1..29e3b53e52a1 100644 --- a/drivers/staging/rt2870/rt2870.h +++ b/drivers/staging/rt2870/rt2870.h | |||
| @@ -89,6 +89,7 @@ | |||
| 89 | {USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */ \ | 89 | {USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */ \ |
| 90 | {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */ \ | 90 | {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */ \ |
| 91 | {USB_DEVICE(0x0DF6,0x0039)}, /* Sitecom */ \ | 91 | {USB_DEVICE(0x0DF6,0x0039)}, /* Sitecom */ \ |
| 92 | {USB_DEVICE(0x0DF6,0x003F)}, /* Sitecom WL-608 */ \ | ||
| 92 | {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */ \ | 93 | {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */ \ |
| 93 | {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */ \ | 94 | {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */ \ |
| 94 | {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */ \ | 95 | {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */ \ |
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c index 93af37e2d31a..54b4b718f84a 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c | |||
| @@ -461,19 +461,19 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee, | |||
| 461 | struct iw_request_info *info, | 461 | struct iw_request_info *info, |
| 462 | union iwreq_data *wrqu, char *extra) | 462 | union iwreq_data *wrqu, char *extra) |
| 463 | { | 463 | { |
| 464 | strcpy(wrqu->name, "802.11"); | 464 | strlcpy(wrqu->name, "802.11", IFNAMSIZ); |
| 465 | if(ieee->modulation & IEEE80211_CCK_MODULATION){ | 465 | if(ieee->modulation & IEEE80211_CCK_MODULATION){ |
| 466 | strcat(wrqu->name, "b"); | 466 | strlcat(wrqu->name, "b", IFNAMSIZ); |
| 467 | if(ieee->modulation & IEEE80211_OFDM_MODULATION) | 467 | if(ieee->modulation & IEEE80211_OFDM_MODULATION) |
| 468 | strcat(wrqu->name, "/g"); | 468 | strlcat(wrqu->name, "/g", IFNAMSIZ); |
| 469 | }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) | 469 | }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) |
| 470 | strcat(wrqu->name, "g"); | 470 | strlcat(wrqu->name, "g", IFNAMSIZ); |
| 471 | 471 | ||
| 472 | if((ieee->state == IEEE80211_LINKED) || | 472 | if((ieee->state == IEEE80211_LINKED) || |
| 473 | (ieee->state == IEEE80211_LINKED_SCANNING)) | 473 | (ieee->state == IEEE80211_LINKED_SCANNING)) |
| 474 | strcat(wrqu->name," linked"); | 474 | strlcat(wrqu->name," link", IFNAMSIZ); |
| 475 | else if(ieee->state != IEEE80211_NOLINK) | 475 | else if(ieee->state != IEEE80211_NOLINK) |
| 476 | strcat(wrqu->name," link.."); | 476 | strlcat(wrqu->name," .....", IFNAMSIZ); |
| 477 | 477 | ||
| 478 | 478 | ||
| 479 | return 0; | 479 | return 0; |
diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig index 4b5552c5926e..770f41280f21 100644 --- a/drivers/staging/rtl8192su/Kconfig +++ b/drivers/staging/rtl8192su/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config RTL8192SU | 1 | config RTL8192SU |
| 2 | tristate "RealTek RTL8192SU Wireless LAN NIC driver" | 2 | tristate "RealTek RTL8192SU Wireless LAN NIC driver" |
| 3 | depends on PCI | 3 | depends on PCI |
| 4 | depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS | 4 | depends on WIRELESS_EXT |
| 5 | default N | 5 | default N |
| 6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c index f408b4583b82..759032db4a34 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c | |||
| @@ -118,7 +118,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
| 118 | #else | 118 | #else |
| 119 | ieee = (struct ieee80211_device *)dev->priv; | 119 | ieee = (struct ieee80211_device *)dev->priv; |
| 120 | #endif | 120 | #endif |
| 121 | dev->hard_start_xmit = ieee80211_xmit; | ||
| 122 | 121 | ||
| 123 | memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv); | 122 | memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv); |
| 124 | ieee->dev = dev; | 123 | ieee->dev = dev; |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac_wx.c index 1f50c46dcb90..191dc3fbbe32 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac_wx.c | |||
| @@ -548,21 +548,21 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee, | |||
| 548 | struct iw_request_info *info, | 548 | struct iw_request_info *info, |
| 549 | union iwreq_data *wrqu, char *extra) | 549 | union iwreq_data *wrqu, char *extra) |
| 550 | { | 550 | { |
| 551 | strcpy(wrqu->name, "802.11"); | 551 | strlcpy(wrqu->name, "802.11", IFNAMSIZ); |
| 552 | if(ieee->modulation & IEEE80211_CCK_MODULATION){ | 552 | if(ieee->modulation & IEEE80211_CCK_MODULATION){ |
| 553 | strcat(wrqu->name, "b"); | 553 | strlcat(wrqu->name, "b", IFNAMSIZ); |
| 554 | if(ieee->modulation & IEEE80211_OFDM_MODULATION) | 554 | if(ieee->modulation & IEEE80211_OFDM_MODULATION) |
| 555 | strcat(wrqu->name, "/g"); | 555 | strlcat(wrqu->name, "/g", IFNAMSIZ); |
| 556 | }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) | 556 | }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) |
| 557 | strcat(wrqu->name, "g"); | 557 | strlcat(wrqu->name, "g", IFNAMSIZ); |
| 558 | if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) | 558 | if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) |
| 559 | strcat(wrqu->name, "/n"); | 559 | strlcat(wrqu->name, "/n", IFNAMSIZ); |
| 560 | 560 | ||
| 561 | if((ieee->state == IEEE80211_LINKED) || | 561 | if((ieee->state == IEEE80211_LINKED) || |
| 562 | (ieee->state == IEEE80211_LINKED_SCANNING)) | 562 | (ieee->state == IEEE80211_LINKED_SCANNING)) |
| 563 | strcat(wrqu->name," linked"); | 563 | strlcat(wrqu->name, " link", IFNAMSIZ); |
| 564 | else if(ieee->state != IEEE80211_NOLINK) | 564 | else if(ieee->state != IEEE80211_NOLINK) |
| 565 | strcat(wrqu->name," link.."); | 565 | strlcat(wrqu->name, " .....", IFNAMSIZ); |
| 566 | 566 | ||
| 567 | 567 | ||
| 568 | return 0; | 568 | return 0; |
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index f1423d714496..4ab250743e81 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c | |||
| @@ -12132,6 +12132,19 @@ static void HalUsbSetQueuePipeMapping8192SUsb(struct usb_interface *intf, struct | |||
| 12132 | } | 12132 | } |
| 12133 | #endif | 12133 | #endif |
| 12134 | 12134 | ||
| 12135 | static const struct net_device_ops rtl8192_netdev_ops = { | ||
| 12136 | .ndo_open = rtl8192_open, | ||
| 12137 | .ndo_stop = rtl8192_close, | ||
| 12138 | .ndo_get_stats = rtl8192_stats, | ||
| 12139 | .ndo_tx_timeout = tx_timeout, | ||
| 12140 | .ndo_do_ioctl = rtl8192_ioctl, | ||
| 12141 | .ndo_set_multicast_list = r8192_set_multicast, | ||
| 12142 | .ndo_set_mac_address = r8192_set_mac_adr, | ||
| 12143 | .ndo_validate_addr = eth_validate_addr, | ||
| 12144 | .ndo_change_mtu = eth_change_mtu, | ||
| 12145 | .ndo_start_xmit = ieee80211_xmit, | ||
| 12146 | }; | ||
| 12147 | |||
| 12135 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 12148 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
| 12136 | static int __devinit rtl8192_usb_probe(struct usb_interface *intf, | 12149 | static int __devinit rtl8192_usb_probe(struct usb_interface *intf, |
| 12137 | const struct usb_device_id *id) | 12150 | const struct usb_device_id *id) |
| @@ -12186,15 +12199,7 @@ static void * __devinit rtl8192_usb_probe(struct usb_device *udev, | |||
| 12186 | priv->ops = &rtl8192u_ops; | 12199 | priv->ops = &rtl8192u_ops; |
| 12187 | #endif | 12200 | #endif |
| 12188 | 12201 | ||
| 12189 | dev->open = rtl8192_open; | 12202 | dev->netdev_ops = &rtl8192_netdev_ops; |
| 12190 | dev->stop = rtl8192_close; | ||
| 12191 | //dev->hard_start_xmit = rtl8192_8023_hard_start_xmit; | ||
| 12192 | dev->tx_timeout = tx_timeout; | ||
| 12193 | //dev->wireless_handlers = &r8192_wx_handlers_def; | ||
| 12194 | dev->do_ioctl = rtl8192_ioctl; | ||
| 12195 | dev->set_multicast_list = r8192_set_multicast; | ||
| 12196 | dev->set_mac_address = r8192_set_mac_adr; | ||
| 12197 | dev->get_stats = rtl8192_stats; | ||
| 12198 | 12203 | ||
| 12199 | //DMESG("Oops: i'm coming\n"); | 12204 | //DMESG("Oops: i'm coming\n"); |
| 12200 | #if WIRELESS_EXT >= 12 | 12205 | #if WIRELESS_EXT >= 12 |
diff --git a/drivers/staging/rtl8192su/r8192U_pm.c b/drivers/staging/rtl8192su/r8192U_pm.c index 92c95aa36638..b1531a8d0cde 100644 --- a/drivers/staging/rtl8192su/r8192U_pm.c +++ b/drivers/staging/rtl8192su/r8192U_pm.c | |||
| @@ -35,7 +35,9 @@ int rtl8192U_suspend(struct usb_interface *intf, pm_message_t state) | |||
| 35 | return 0; | 35 | return 0; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | dev->stop(dev); | 38 | if (dev->netdev_ops->ndo_stop) |
| 39 | dev->netdev_ops->ndo_stop(dev); | ||
| 40 | |||
| 39 | mdelay(10); | 41 | mdelay(10); |
| 40 | 42 | ||
| 41 | netif_device_detach(dev); | 43 | netif_device_detach(dev); |
| @@ -61,7 +63,9 @@ int rtl8192U_resume (struct usb_interface *intf) | |||
| 61 | } | 63 | } |
| 62 | 64 | ||
| 63 | netif_device_attach(dev); | 65 | netif_device_attach(dev); |
| 64 | dev->open(dev); | 66 | |
| 67 | if (dev->netdev_ops->ndo_open) | ||
| 68 | dev->netdev_ops->ndo_open(dev); | ||
| 65 | } | 69 | } |
| 66 | 70 | ||
| 67 | return 0; | 71 | return 0; |
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 90b29b564631..a9bd4106beb7 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c | |||
| @@ -866,7 +866,7 @@ static void qt_release(struct usb_serial *serial) | |||
| 866 | 866 | ||
| 867 | } | 867 | } |
| 868 | 868 | ||
| 869 | int qt_open(struct tty_struct *tty, | 869 | static int qt_open(struct tty_struct *tty, |
| 870 | struct usb_serial_port *port, struct file *filp) | 870 | struct usb_serial_port *port, struct file *filp) |
| 871 | { | 871 | { |
| 872 | struct usb_serial *serial; | 872 | struct usb_serial *serial; |
| @@ -1041,17 +1041,19 @@ static void qt_block_until_empty(struct tty_struct *tty, | |||
| 1041 | } | 1041 | } |
| 1042 | } | 1042 | } |
| 1043 | 1043 | ||
| 1044 | static void qt_close(struct tty_struct *tty, struct usb_serial_port *port, | 1044 | static void qt_close( struct usb_serial_port *port) |
| 1045 | struct file *filp) | ||
| 1046 | { | 1045 | { |
| 1047 | struct usb_serial *serial = port->serial; | 1046 | struct usb_serial *serial = port->serial; |
| 1048 | struct quatech_port *qt_port; | 1047 | struct quatech_port *qt_port; |
| 1049 | struct quatech_port *port0; | 1048 | struct quatech_port *port0; |
| 1049 | struct tty_struct *tty; | ||
| 1050 | int status; | 1050 | int status; |
| 1051 | unsigned int index; | 1051 | unsigned int index; |
| 1052 | status = 0; | 1052 | status = 0; |
| 1053 | 1053 | ||
| 1054 | dbg("%s - port %d\n", __func__, port->number); | 1054 | dbg("%s - port %d\n", __func__, port->number); |
| 1055 | |||
| 1056 | tty = tty_port_tty_get(&port->port); | ||
| 1055 | index = tty->index - serial->minor; | 1057 | index = tty->index - serial->minor; |
| 1056 | 1058 | ||
| 1057 | qt_port = qt_get_port_private(port); | 1059 | qt_port = qt_get_port_private(port); |
diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c index cfdaac9b747e..a137c78fac09 100644 --- a/drivers/staging/stlc45xx/stlc45xx.c +++ b/drivers/staging/stlc45xx/stlc45xx.c | |||
| @@ -2235,24 +2235,6 @@ static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw, | |||
| 2235 | stlc45xx_debug(DEBUG_FUNC, "%s", __func__); | 2235 | stlc45xx_debug(DEBUG_FUNC, "%s", __func__); |
| 2236 | } | 2236 | } |
| 2237 | 2237 | ||
| 2238 | static int stlc45xx_op_config_interface(struct ieee80211_hw *hw, | ||
| 2239 | struct ieee80211_vif *vif, | ||
| 2240 | struct ieee80211_if_conf *conf) | ||
| 2241 | { | ||
| 2242 | struct stlc45xx *stlc = hw->priv; | ||
| 2243 | |||
| 2244 | stlc45xx_debug(DEBUG_FUNC, "%s", __func__); | ||
| 2245 | |||
| 2246 | mutex_lock(&stlc->mutex); | ||
| 2247 | |||
| 2248 | memcpy(stlc->bssid, conf->bssid, ETH_ALEN); | ||
| 2249 | stlc45xx_tx_setup(stlc); | ||
| 2250 | |||
| 2251 | mutex_unlock(&stlc->mutex); | ||
| 2252 | |||
| 2253 | return 0; | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed) | 2238 | static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed) |
| 2257 | { | 2239 | { |
| 2258 | struct stlc45xx *stlc = hw->priv; | 2240 | struct stlc45xx *stlc = hw->priv; |
| @@ -2295,6 +2277,14 @@ static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2295 | { | 2277 | { |
| 2296 | struct stlc45xx *stlc = hw->priv; | 2278 | struct stlc45xx *stlc = hw->priv; |
| 2297 | 2279 | ||
| 2280 | stlc45xx_debug(DEBUG_FUNC, "%s", __func__); | ||
| 2281 | mutex_lock(&stlc->mutex); | ||
| 2282 | |||
| 2283 | memcpy(stlc->bssid, info->bssid, ETH_ALEN); | ||
| 2284 | stlc45xx_tx_setup(stlc); | ||
| 2285 | |||
| 2286 | mutex_unlock(&stlc->mutex); | ||
| 2287 | |||
| 2298 | if (changed & BSS_CHANGED_ASSOC) { | 2288 | if (changed & BSS_CHANGED_ASSOC) { |
| 2299 | stlc->associated = info->assoc; | 2289 | stlc->associated = info->assoc; |
| 2300 | if (info->assoc) | 2290 | if (info->assoc) |
| @@ -2357,7 +2347,6 @@ static const struct ieee80211_ops stlc45xx_ops = { | |||
| 2357 | .add_interface = stlc45xx_op_add_interface, | 2347 | .add_interface = stlc45xx_op_add_interface, |
| 2358 | .remove_interface = stlc45xx_op_remove_interface, | 2348 | .remove_interface = stlc45xx_op_remove_interface, |
| 2359 | .config = stlc45xx_op_config, | 2349 | .config = stlc45xx_op_config, |
| 2360 | .config_interface = stlc45xx_op_config_interface, | ||
| 2361 | .configure_filter = stlc45xx_op_configure_filter, | 2350 | .configure_filter = stlc45xx_op_configure_filter, |
| 2362 | .tx = stlc45xx_op_tx, | 2351 | .tx = stlc45xx_op_tx, |
| 2363 | .bss_info_changed = stlc45xx_op_bss_info_changed, | 2352 | .bss_info_changed = stlc45xx_op_bss_info_changed, |
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 22f93dd0ba03..251220dc8851 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/smp_lock.h> | ||
| 21 | #include <linux/file.h> | 22 | #include <linux/file.h> |
| 22 | #include <linux/tcp.h> | 23 | #include <linux/tcp.h> |
| 23 | #include <linux/in.h> | 24 | #include <linux/in.h> |
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index a10ed27acbc2..f43ca416e4a8 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c | |||
| @@ -344,7 +344,7 @@ static CHIP_INFO chip_info_table[]= { | |||
| 344 | }; | 344 | }; |
| 345 | 345 | ||
| 346 | static struct pci_device_id device_id_table[] __devinitdata = { | 346 | static struct pci_device_id device_id_table[] __devinitdata = { |
| 347 | { 0x1106, 0x3253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[0]}, | 347 | { 0x1106, 0x3253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long)&chip_info_table[0]}, |
| 348 | { 0, } | 348 | { 0, } |
| 349 | }; | 349 | }; |
| 350 | #endif | 350 | #endif |
| @@ -369,7 +369,7 @@ static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | |||
| 369 | 369 | ||
| 370 | #ifdef CONFIG_PM | 370 | #ifdef CONFIG_PM |
| 371 | static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); | 371 | static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); |
| 372 | static int viawget_suspend(struct pci_dev *pcid, u32 state); | 372 | static int viawget_suspend(struct pci_dev *pcid, pm_message_t state); |
| 373 | static int viawget_resume(struct pci_dev *pcid); | 373 | static int viawget_resume(struct pci_dev *pcid); |
| 374 | struct notifier_block device_notifier = { | 374 | struct notifier_block device_notifier = { |
| 375 | notifier_call: device_notify_reboot, | 375 | notifier_call: device_notify_reboot, |
| @@ -3941,7 +3941,7 @@ device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) | |||
| 3941 | while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { | 3941 | while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { |
| 3942 | if(pci_dev_driver(pdev) == &device_driver) { | 3942 | if(pci_dev_driver(pdev) == &device_driver) { |
| 3943 | if (pci_get_drvdata(pdev)) | 3943 | if (pci_get_drvdata(pdev)) |
| 3944 | viawget_suspend(pdev, 3); | 3944 | viawget_suspend(pdev, PMSG_HIBERNATE); |
| 3945 | } | 3945 | } |
| 3946 | } | 3946 | } |
| 3947 | } | 3947 | } |
| @@ -3949,7 +3949,7 @@ device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) | |||
| 3949 | } | 3949 | } |
| 3950 | 3950 | ||
| 3951 | static int | 3951 | static int |
| 3952 | viawget_suspend(struct pci_dev *pcid, u32 state) | 3952 | viawget_suspend(struct pci_dev *pcid, pm_message_t state) |
| 3953 | { | 3953 | { |
| 3954 | int power_status; // to silence the compiler | 3954 | int power_status; // to silence the compiler |
| 3955 | 3955 | ||
| @@ -3971,7 +3971,7 @@ viawget_suspend(struct pci_dev *pcid, u32 state) | |||
| 3971 | memset(pMgmt->abyCurrBSSID, 0, 6); | 3971 | memset(pMgmt->abyCurrBSSID, 0, 6); |
| 3972 | pMgmt->eCurrState = WMAC_STATE_IDLE; | 3972 | pMgmt->eCurrState = WMAC_STATE_IDLE; |
| 3973 | pci_disable_device(pcid); | 3973 | pci_disable_device(pcid); |
| 3974 | power_status = pci_set_power_state(pcid, state); | 3974 | power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state)); |
| 3975 | spin_unlock_irq(&pDevice->lock); | 3975 | spin_unlock_irq(&pDevice->lock); |
| 3976 | return 0; | 3976 | return 0; |
| 3977 | } | 3977 | } |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index a913efc69669..40de151f2789 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
| @@ -257,6 +257,7 @@ | |||
| 257 | #include <linux/fs.h> /* everything... */ | 257 | #include <linux/fs.h> /* everything... */ |
| 258 | #include <linux/errno.h> /* error codes */ | 258 | #include <linux/errno.h> /* error codes */ |
| 259 | #include <linux/slab.h> | 259 | #include <linux/slab.h> |
| 260 | #include <linux/smp_lock.h> | ||
| 260 | #include <linux/mm.h> | 261 | #include <linux/mm.h> |
| 261 | #include <linux/ioport.h> | 262 | #include <linux/ioport.h> |
| 262 | #include <linux/interrupt.h> | 263 | #include <linux/interrupt.h> |
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index b52cc830c0b4..f3873f650bb4 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
| 24 | #include <linux/phonedev.h> | 24 | #include <linux/phonedev.h> |
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/smp_lock.h> | ||
| 27 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
| 28 | #include <asm/system.h> | 27 | #include <asm/system.h> |
| 29 | 28 | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 38bfdb0f6660..5b15d9d8896b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -387,6 +387,7 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
| 387 | struct acm_ru *rcv; | 387 | struct acm_ru *rcv; |
| 388 | unsigned long flags; | 388 | unsigned long flags; |
| 389 | unsigned char throttled; | 389 | unsigned char throttled; |
| 390 | struct usb_host_endpoint *ep; | ||
| 390 | 391 | ||
| 391 | dbg("Entering acm_rx_tasklet"); | 392 | dbg("Entering acm_rx_tasklet"); |
| 392 | 393 | ||
| @@ -462,11 +463,20 @@ urbs: | |||
| 462 | 463 | ||
| 463 | rcv->buffer = buf; | 464 | rcv->buffer = buf; |
| 464 | 465 | ||
| 465 | usb_fill_bulk_urb(rcv->urb, acm->dev, | 466 | ep = (usb_pipein(acm->rx_endpoint) ? acm->dev->ep_in : acm->dev->ep_out) |
| 466 | acm->rx_endpoint, | 467 | [usb_pipeendpoint(acm->rx_endpoint)]; |
| 467 | buf->base, | 468 | if (usb_endpoint_xfer_int(&ep->desc)) |
| 468 | acm->readsize, | 469 | usb_fill_int_urb(rcv->urb, acm->dev, |
| 469 | acm_read_bulk, rcv); | 470 | acm->rx_endpoint, |
| 471 | buf->base, | ||
| 472 | acm->readsize, | ||
| 473 | acm_read_bulk, rcv, ep->desc.bInterval); | ||
| 474 | else | ||
| 475 | usb_fill_bulk_urb(rcv->urb, acm->dev, | ||
| 476 | acm->rx_endpoint, | ||
| 477 | buf->base, | ||
| 478 | acm->readsize, | ||
| 479 | acm_read_bulk, rcv); | ||
| 470 | rcv->urb->transfer_dma = buf->dma; | 480 | rcv->urb->transfer_dma = buf->dma; |
| 471 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 481 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 472 | 482 | ||
| @@ -550,7 +560,7 @@ static void acm_waker(struct work_struct *waker) | |||
| 550 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) | 560 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
| 551 | { | 561 | { |
| 552 | struct acm *acm; | 562 | struct acm *acm; |
| 553 | int rv = -EINVAL; | 563 | int rv = -ENODEV; |
| 554 | int i; | 564 | int i; |
| 555 | dbg("Entering acm_tty_open."); | 565 | dbg("Entering acm_tty_open."); |
| 556 | 566 | ||
| @@ -677,7 +687,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
| 677 | 687 | ||
| 678 | /* Perform the closing process and see if we need to do the hardware | 688 | /* Perform the closing process and see if we need to do the hardware |
| 679 | shutdown */ | 689 | shutdown */ |
| 680 | if (tty_port_close_start(&acm->port, tty, filp) == 0) | 690 | if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0) |
| 681 | return; | 691 | return; |
| 682 | acm_port_down(acm, 0); | 692 | acm_port_down(acm, 0); |
| 683 | tty_port_close_end(&acm->port, tty); | 693 | tty_port_close_end(&acm->port, tty); |
| @@ -1227,9 +1237,14 @@ made_compressed_probe: | |||
| 1227 | goto alloc_fail7; | 1237 | goto alloc_fail7; |
| 1228 | } | 1238 | } |
| 1229 | 1239 | ||
| 1230 | usb_fill_bulk_urb(snd->urb, usb_dev, | 1240 | if (usb_endpoint_xfer_int(epwrite)) |
| 1231 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 1241 | usb_fill_int_urb(snd->urb, usb_dev, |
| 1232 | NULL, acm->writesize, acm_write_bulk, snd); | 1242 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
| 1243 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); | ||
| 1244 | else | ||
| 1245 | usb_fill_bulk_urb(snd->urb, usb_dev, | ||
| 1246 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | ||
| 1247 | NULL, acm->writesize, acm_write_bulk, snd); | ||
| 1233 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1248 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 1234 | snd->instance = acm; | 1249 | snd->instance = acm; |
| 1235 | } | 1250 | } |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 0fe434505ac4..ba589d4ca8bc 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/smp_lock.h> | ||
| 19 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| 20 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 21 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 3703789d0d2a..b09a527f7341 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
| @@ -751,7 +751,7 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
| 751 | { | 751 | { |
| 752 | struct device *dev = &data->usb_dev->dev; | 752 | struct device *dev = &data->usb_dev->dev; |
| 753 | char *buffer; | 753 | char *buffer; |
| 754 | int rv; | 754 | int rv = 0; |
| 755 | 755 | ||
| 756 | buffer = kmalloc(0x18, GFP_KERNEL); | 756 | buffer = kmalloc(0x18, GFP_KERNEL); |
| 757 | if (!buffer) | 757 | if (!buffer) |
| @@ -763,7 +763,7 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
| 763 | 0, 0, buffer, 0x18, USBTMC_TIMEOUT); | 763 | 0, 0, buffer, 0x18, USBTMC_TIMEOUT); |
| 764 | if (rv < 0) { | 764 | if (rv < 0) { |
| 765 | dev_err(dev, "usb_control_msg returned %d\n", rv); | 765 | dev_err(dev, "usb_control_msg returned %d\n", rv); |
| 766 | return rv; | 766 | goto err_out; |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); | 769 | dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); |
| @@ -773,7 +773,8 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
| 773 | dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); | 773 | dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); |
| 774 | if (buffer[0] != USBTMC_STATUS_SUCCESS) { | 774 | if (buffer[0] != USBTMC_STATUS_SUCCESS) { |
| 775 | dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); | 775 | dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); |
| 776 | return -EPERM; | 776 | rv = -EPERM; |
| 777 | goto err_out; | ||
| 777 | } | 778 | } |
| 778 | 779 | ||
| 779 | data->capabilities.interface_capabilities = buffer[4]; | 780 | data->capabilities.interface_capabilities = buffer[4]; |
| @@ -781,8 +782,9 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
| 781 | data->capabilities.usb488_interface_capabilities = buffer[14]; | 782 | data->capabilities.usb488_interface_capabilities = buffer[14]; |
| 782 | data->capabilities.usb488_device_capabilities = buffer[15]; | 783 | data->capabilities.usb488_device_capabilities = buffer[15]; |
| 783 | 784 | ||
| 785 | err_out: | ||
| 784 | kfree(buffer); | 786 | kfree(buffer); |
| 785 | return 0; | 787 | return rv; |
| 786 | } | 788 | } |
| 787 | 789 | ||
| 788 | #define capability_attribute(name) \ | 790 | #define capability_attribute(name) \ |
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 69280c35b5cb..ad925946f869 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig | |||
| @@ -28,7 +28,7 @@ comment "Miscellaneous USB options" | |||
| 28 | depends on USB | 28 | depends on USB |
| 29 | 29 | ||
| 30 | config USB_DEVICEFS | 30 | config USB_DEVICEFS |
| 31 | bool "USB device filesystem (DEPRECATED)" if EMBEDDED | 31 | bool "USB device filesystem (DEPRECATED)" |
| 32 | depends on USB | 32 | depends on USB |
| 33 | ---help--- | 33 | ---help--- |
| 34 | If you say Y here (and to "/proc file system support" in the "File | 34 | If you say Y here (and to "/proc file system support" in the "File |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 73c108d117b4..96f11715cd26 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
| @@ -136,17 +136,19 @@ static const struct class_info clas_info[] = | |||
| 136 | {USB_CLASS_AUDIO, "audio"}, | 136 | {USB_CLASS_AUDIO, "audio"}, |
| 137 | {USB_CLASS_COMM, "comm."}, | 137 | {USB_CLASS_COMM, "comm."}, |
| 138 | {USB_CLASS_HID, "HID"}, | 138 | {USB_CLASS_HID, "HID"}, |
| 139 | {USB_CLASS_HUB, "hub"}, | ||
| 140 | {USB_CLASS_PHYSICAL, "PID"}, | 139 | {USB_CLASS_PHYSICAL, "PID"}, |
| 140 | {USB_CLASS_STILL_IMAGE, "still"}, | ||
| 141 | {USB_CLASS_PRINTER, "print"}, | 141 | {USB_CLASS_PRINTER, "print"}, |
| 142 | {USB_CLASS_MASS_STORAGE, "stor."}, | 142 | {USB_CLASS_MASS_STORAGE, "stor."}, |
| 143 | {USB_CLASS_HUB, "hub"}, | ||
| 143 | {USB_CLASS_CDC_DATA, "data"}, | 144 | {USB_CLASS_CDC_DATA, "data"}, |
| 144 | {USB_CLASS_APP_SPEC, "app."}, | ||
| 145 | {USB_CLASS_VENDOR_SPEC, "vend."}, | ||
| 146 | {USB_CLASS_STILL_IMAGE, "still"}, | ||
| 147 | {USB_CLASS_CSCID, "scard"}, | 145 | {USB_CLASS_CSCID, "scard"}, |
| 148 | {USB_CLASS_CONTENT_SEC, "c-sec"}, | 146 | {USB_CLASS_CONTENT_SEC, "c-sec"}, |
| 149 | {USB_CLASS_VIDEO, "video"}, | 147 | {USB_CLASS_VIDEO, "video"}, |
| 148 | {USB_CLASS_WIRELESS_CONTROLLER, "wlcon"}, | ||
| 149 | {USB_CLASS_MISC, "misc"}, | ||
| 150 | {USB_CLASS_APP_SPEC, "app."}, | ||
| 151 | {USB_CLASS_VENDOR_SPEC, "vend."}, | ||
| 150 | {-1, "unk."} /* leave as last */ | 152 | {-1, "unk."} /* leave as last */ |
| 151 | }; | 153 | }; |
| 152 | 154 | ||
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 308609039c73..38b8bce782d6 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -325,21 +325,34 @@ static void async_completed(struct urb *urb) | |||
| 325 | struct async *as = urb->context; | 325 | struct async *as = urb->context; |
| 326 | struct dev_state *ps = as->ps; | 326 | struct dev_state *ps = as->ps; |
| 327 | struct siginfo sinfo; | 327 | struct siginfo sinfo; |
| 328 | struct pid *pid = NULL; | ||
| 329 | uid_t uid = 0; | ||
| 330 | uid_t euid = 0; | ||
| 331 | u32 secid = 0; | ||
| 332 | int signr; | ||
| 328 | 333 | ||
| 329 | spin_lock(&ps->lock); | 334 | spin_lock(&ps->lock); |
| 330 | list_move_tail(&as->asynclist, &ps->async_completed); | 335 | list_move_tail(&as->asynclist, &ps->async_completed); |
| 331 | spin_unlock(&ps->lock); | ||
| 332 | as->status = urb->status; | 336 | as->status = urb->status; |
| 333 | if (as->signr) { | 337 | signr = as->signr; |
| 338 | if (signr) { | ||
| 334 | sinfo.si_signo = as->signr; | 339 | sinfo.si_signo = as->signr; |
| 335 | sinfo.si_errno = as->status; | 340 | sinfo.si_errno = as->status; |
| 336 | sinfo.si_code = SI_ASYNCIO; | 341 | sinfo.si_code = SI_ASYNCIO; |
| 337 | sinfo.si_addr = as->userurb; | 342 | sinfo.si_addr = as->userurb; |
| 338 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, | 343 | pid = as->pid; |
| 339 | as->euid, as->secid); | 344 | uid = as->uid; |
| 345 | euid = as->euid; | ||
| 346 | secid = as->secid; | ||
| 340 | } | 347 | } |
| 341 | snoop(&urb->dev->dev, "urb complete\n"); | 348 | snoop(&urb->dev->dev, "urb complete\n"); |
| 342 | snoop_urb(urb, as->userurb); | 349 | snoop_urb(urb, as->userurb); |
| 350 | spin_unlock(&ps->lock); | ||
| 351 | |||
| 352 | if (signr) | ||
| 353 | kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, | ||
| 354 | euid, secid); | ||
| 355 | |||
| 343 | wake_up(&ps->wait); | 356 | wake_up(&ps->wait); |
| 344 | } | 357 | } |
| 345 | 358 | ||
| @@ -982,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 982 | USBDEVFS_URB_ZERO_PACKET | | 995 | USBDEVFS_URB_ZERO_PACKET | |
| 983 | USBDEVFS_URB_NO_INTERRUPT)) | 996 | USBDEVFS_URB_NO_INTERRUPT)) |
| 984 | return -EINVAL; | 997 | return -EINVAL; |
| 985 | if (!uurb->buffer) | 998 | if (uurb->buffer_length > 0 && !uurb->buffer) |
| 986 | return -EINVAL; | 999 | return -EINVAL; |
| 987 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && | 1000 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && |
| 988 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { | 1001 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { |
| @@ -1038,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1038 | is_in = 0; | 1051 | is_in = 0; |
| 1039 | uurb->endpoint &= ~USB_DIR_IN; | 1052 | uurb->endpoint &= ~USB_DIR_IN; |
| 1040 | } | 1053 | } |
| 1041 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
| 1042 | uurb->buffer, uurb->buffer_length)) { | ||
| 1043 | kfree(dr); | ||
| 1044 | return -EFAULT; | ||
| 1045 | } | ||
| 1046 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " | 1054 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " |
| 1047 | "bRrequestType=%02x wValue=%04x " | 1055 | "bRrequestType=%02x wValue=%04x " |
| 1048 | "wIndex=%04x wLength=%04x\n", | 1056 | "wIndex=%04x wLength=%04x\n", |
| @@ -1062,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1062 | uurb->number_of_packets = 0; | 1070 | uurb->number_of_packets = 0; |
| 1063 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1071 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
| 1064 | return -EINVAL; | 1072 | return -EINVAL; |
| 1065 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
| 1066 | uurb->buffer, uurb->buffer_length)) | ||
| 1067 | return -EFAULT; | ||
| 1068 | snoop(&ps->dev->dev, "bulk urb\n"); | 1073 | snoop(&ps->dev->dev, "bulk urb\n"); |
| 1069 | break; | 1074 | break; |
| 1070 | 1075 | ||
| @@ -1106,28 +1111,35 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1106 | return -EINVAL; | 1111 | return -EINVAL; |
| 1107 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1112 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
| 1108 | return -EINVAL; | 1113 | return -EINVAL; |
| 1109 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
| 1110 | uurb->buffer, uurb->buffer_length)) | ||
| 1111 | return -EFAULT; | ||
| 1112 | snoop(&ps->dev->dev, "interrupt urb\n"); | 1114 | snoop(&ps->dev->dev, "interrupt urb\n"); |
| 1113 | break; | 1115 | break; |
| 1114 | 1116 | ||
| 1115 | default: | 1117 | default: |
| 1116 | return -EINVAL; | 1118 | return -EINVAL; |
| 1117 | } | 1119 | } |
| 1118 | as = alloc_async(uurb->number_of_packets); | 1120 | if (uurb->buffer_length > 0 && |
| 1119 | if (!as) { | 1121 | !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
| 1122 | uurb->buffer, uurb->buffer_length)) { | ||
| 1120 | kfree(isopkt); | 1123 | kfree(isopkt); |
| 1121 | kfree(dr); | 1124 | kfree(dr); |
| 1122 | return -ENOMEM; | 1125 | return -EFAULT; |
| 1123 | } | 1126 | } |
| 1124 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); | 1127 | as = alloc_async(uurb->number_of_packets); |
| 1125 | if (!as->urb->transfer_buffer) { | 1128 | if (!as) { |
| 1126 | kfree(isopkt); | 1129 | kfree(isopkt); |
| 1127 | kfree(dr); | 1130 | kfree(dr); |
| 1128 | free_async(as); | ||
| 1129 | return -ENOMEM; | 1131 | return -ENOMEM; |
| 1130 | } | 1132 | } |
| 1133 | if (uurb->buffer_length > 0) { | ||
| 1134 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, | ||
| 1135 | GFP_KERNEL); | ||
| 1136 | if (!as->urb->transfer_buffer) { | ||
| 1137 | kfree(isopkt); | ||
| 1138 | kfree(dr); | ||
| 1139 | free_async(as); | ||
| 1140 | return -ENOMEM; | ||
| 1141 | } | ||
| 1142 | } | ||
| 1131 | as->urb->dev = ps->dev; | 1143 | as->urb->dev = ps->dev; |
| 1132 | as->urb->pipe = (uurb->type << 30) | | 1144 | as->urb->pipe = (uurb->type << 30) | |
| 1133 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | | 1145 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | |
| @@ -1169,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1169 | kfree(isopkt); | 1181 | kfree(isopkt); |
| 1170 | as->ps = ps; | 1182 | as->ps = ps; |
| 1171 | as->userurb = arg; | 1183 | as->userurb = arg; |
| 1172 | if (uurb->endpoint & USB_DIR_IN) | 1184 | if (is_in && uurb->buffer_length > 0) |
| 1173 | as->userbuffer = uurb->buffer; | 1185 | as->userbuffer = uurb->buffer; |
| 1174 | else | 1186 | else |
| 1175 | as->userbuffer = NULL; | 1187 | as->userbuffer = NULL; |
| @@ -1179,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
| 1179 | as->uid = cred->uid; | 1191 | as->uid = cred->uid; |
| 1180 | as->euid = cred->euid; | 1192 | as->euid = cred->euid; |
| 1181 | security_task_getsecid(current, &as->secid); | 1193 | security_task_getsecid(current, &as->secid); |
| 1182 | if (!is_in) { | 1194 | if (!is_in && uurb->buffer_length > 0) { |
| 1183 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | 1195 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
| 1184 | as->urb->transfer_buffer_length)) { | 1196 | uurb->buffer_length)) { |
| 1185 | free_async(as); | 1197 | free_async(as); |
| 1186 | return -EFAULT; | 1198 | return -EFAULT; |
| 1187 | } | 1199 | } |
| @@ -1231,22 +1243,22 @@ static int processcompl(struct async *as, void __user * __user *arg) | |||
| 1231 | if (as->userbuffer) | 1243 | if (as->userbuffer) |
| 1232 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, | 1244 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, |
| 1233 | urb->transfer_buffer_length)) | 1245 | urb->transfer_buffer_length)) |
| 1234 | return -EFAULT; | 1246 | goto err_out; |
| 1235 | if (put_user(as->status, &userurb->status)) | 1247 | if (put_user(as->status, &userurb->status)) |
| 1236 | return -EFAULT; | 1248 | goto err_out; |
| 1237 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1249 | if (put_user(urb->actual_length, &userurb->actual_length)) |
| 1238 | return -EFAULT; | 1250 | goto err_out; |
| 1239 | if (put_user(urb->error_count, &userurb->error_count)) | 1251 | if (put_user(urb->error_count, &userurb->error_count)) |
| 1240 | return -EFAULT; | 1252 | goto err_out; |
| 1241 | 1253 | ||
| 1242 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { | 1254 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
| 1243 | for (i = 0; i < urb->number_of_packets; i++) { | 1255 | for (i = 0; i < urb->number_of_packets; i++) { |
| 1244 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1256 | if (put_user(urb->iso_frame_desc[i].actual_length, |
| 1245 | &userurb->iso_frame_desc[i].actual_length)) | 1257 | &userurb->iso_frame_desc[i].actual_length)) |
| 1246 | return -EFAULT; | 1258 | goto err_out; |
| 1247 | if (put_user(urb->iso_frame_desc[i].status, | 1259 | if (put_user(urb->iso_frame_desc[i].status, |
| 1248 | &userurb->iso_frame_desc[i].status)) | 1260 | &userurb->iso_frame_desc[i].status)) |
| 1249 | return -EFAULT; | 1261 | goto err_out; |
| 1250 | } | 1262 | } |
| 1251 | } | 1263 | } |
| 1252 | 1264 | ||
| @@ -1255,6 +1267,10 @@ static int processcompl(struct async *as, void __user * __user *arg) | |||
| 1255 | if (put_user(addr, (void __user * __user *)arg)) | 1267 | if (put_user(addr, (void __user * __user *)arg)) |
| 1256 | return -EFAULT; | 1268 | return -EFAULT; |
| 1257 | return 0; | 1269 | return 0; |
| 1270 | |||
| 1271 | err_out: | ||
| 1272 | free_async(as); | ||
| 1273 | return -EFAULT; | ||
| 1258 | } | 1274 | } |
| 1259 | 1275 | ||
| 1260 | static struct async *reap_as(struct dev_state *ps) | 1276 | static struct async *reap_as(struct dev_state *ps) |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ce3f453f02ef..95ccfa0b9fc5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -648,7 +648,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
| 648 | struct urb *urb; | 648 | struct urb *urb; |
| 649 | int length; | 649 | int length; |
| 650 | unsigned long flags; | 650 | unsigned long flags; |
| 651 | char buffer[4]; /* Any root hubs with > 31 ports? */ | 651 | char buffer[6]; /* Any root hubs with > 31 ports? */ |
| 652 | 652 | ||
| 653 | if (unlikely(!hcd->rh_registered)) | 653 | if (unlikely(!hcd->rh_registered)) |
| 654 | return; | 654 | return; |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index d397ecfd5b17..ec5c67ea07b7 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -227,6 +227,10 @@ struct hc_driver { | |||
| 227 | /* has a port been handed over to a companion? */ | 227 | /* has a port been handed over to a companion? */ |
| 228 | int (*port_handed_over)(struct usb_hcd *, int); | 228 | int (*port_handed_over)(struct usb_hcd *, int); |
| 229 | 229 | ||
| 230 | /* CLEAR_TT_BUFFER completion callback */ | ||
| 231 | void (*clear_tt_buffer_complete)(struct usb_hcd *, | ||
| 232 | struct usb_host_endpoint *); | ||
| 233 | |||
| 230 | /* xHCI specific functions */ | 234 | /* xHCI specific functions */ |
| 231 | /* Called by usb_alloc_dev to alloc HC device structures */ | 235 | /* Called by usb_alloc_dev to alloc HC device structures */ |
| 232 | int (*alloc_dev)(struct usb_hcd *, struct usb_device *); | 236 | int (*alloc_dev)(struct usb_hcd *, struct usb_device *); |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2af3b4f06054..71f86c60d83c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) | |||
| 450 | * talking to TTs must queue control transfers (not just bulk and iso), so | 450 | * talking to TTs must queue control transfers (not just bulk and iso), so |
| 451 | * both can talk to the same hub concurrently. | 451 | * both can talk to the same hub concurrently. |
| 452 | */ | 452 | */ |
| 453 | static void hub_tt_kevent (struct work_struct *work) | 453 | static void hub_tt_work(struct work_struct *work) |
| 454 | { | 454 | { |
| 455 | struct usb_hub *hub = | 455 | struct usb_hub *hub = |
| 456 | container_of(work, struct usb_hub, tt.kevent); | 456 | container_of(work, struct usb_hub, tt.clear_work); |
| 457 | unsigned long flags; | 457 | unsigned long flags; |
| 458 | int limit = 100; | 458 | int limit = 100; |
| 459 | 459 | ||
| @@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work) | |||
| 462 | struct list_head *next; | 462 | struct list_head *next; |
| 463 | struct usb_tt_clear *clear; | 463 | struct usb_tt_clear *clear; |
| 464 | struct usb_device *hdev = hub->hdev; | 464 | struct usb_device *hdev = hub->hdev; |
| 465 | const struct hc_driver *drv; | ||
| 465 | int status; | 466 | int status; |
| 466 | 467 | ||
| 467 | next = hub->tt.clear_list.next; | 468 | next = hub->tt.clear_list.next; |
| @@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work) | |||
| 471 | /* drop lock so HCD can concurrently report other TT errors */ | 472 | /* drop lock so HCD can concurrently report other TT errors */ |
| 472 | spin_unlock_irqrestore (&hub->tt.lock, flags); | 473 | spin_unlock_irqrestore (&hub->tt.lock, flags); |
| 473 | status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); | 474 | status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); |
| 474 | spin_lock_irqsave (&hub->tt.lock, flags); | ||
| 475 | |||
| 476 | if (status) | 475 | if (status) |
| 477 | dev_err (&hdev->dev, | 476 | dev_err (&hdev->dev, |
| 478 | "clear tt %d (%04x) error %d\n", | 477 | "clear tt %d (%04x) error %d\n", |
| 479 | clear->tt, clear->devinfo, status); | 478 | clear->tt, clear->devinfo, status); |
| 479 | |||
| 480 | /* Tell the HCD, even if the operation failed */ | ||
| 481 | drv = clear->hcd->driver; | ||
| 482 | if (drv->clear_tt_buffer_complete) | ||
| 483 | (drv->clear_tt_buffer_complete)(clear->hcd, clear->ep); | ||
| 484 | |||
| 480 | kfree(clear); | 485 | kfree(clear); |
| 486 | spin_lock_irqsave(&hub->tt.lock, flags); | ||
| 481 | } | 487 | } |
| 482 | spin_unlock_irqrestore (&hub->tt.lock, flags); | 488 | spin_unlock_irqrestore (&hub->tt.lock, flags); |
| 483 | } | 489 | } |
| 484 | 490 | ||
| 485 | /** | 491 | /** |
| 486 | * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub | 492 | * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub |
| 487 | * @udev: the device whose split transaction failed | 493 | * @urb: an URB associated with the failed or incomplete split transaction |
| 488 | * @pipe: identifies the endpoint of the failed transaction | ||
| 489 | * | 494 | * |
| 490 | * High speed HCDs use this to tell the hub driver that some split control or | 495 | * High speed HCDs use this to tell the hub driver that some split control or |
| 491 | * bulk transaction failed in a way that requires clearing internal state of | 496 | * bulk transaction failed in a way that requires clearing internal state of |
| @@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work) | |||
| 495 | * It may not be possible for that hub to handle additional full (or low) | 500 | * It may not be possible for that hub to handle additional full (or low) |
| 496 | * speed transactions until that state is fully cleared out. | 501 | * speed transactions until that state is fully cleared out. |
| 497 | */ | 502 | */ |
| 498 | void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | 503 | int usb_hub_clear_tt_buffer(struct urb *urb) |
| 499 | { | 504 | { |
| 505 | struct usb_device *udev = urb->dev; | ||
| 506 | int pipe = urb->pipe; | ||
| 500 | struct usb_tt *tt = udev->tt; | 507 | struct usb_tt *tt = udev->tt; |
| 501 | unsigned long flags; | 508 | unsigned long flags; |
| 502 | struct usb_tt_clear *clear; | 509 | struct usb_tt_clear *clear; |
| @@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | |||
| 508 | if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { | 515 | if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { |
| 509 | dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); | 516 | dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); |
| 510 | /* FIXME recover somehow ... RESET_TT? */ | 517 | /* FIXME recover somehow ... RESET_TT? */ |
| 511 | return; | 518 | return -ENOMEM; |
| 512 | } | 519 | } |
| 513 | 520 | ||
| 514 | /* info that CLEAR_TT_BUFFER needs */ | 521 | /* info that CLEAR_TT_BUFFER needs */ |
| @@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | |||
| 520 | : (USB_ENDPOINT_XFER_BULK << 11); | 527 | : (USB_ENDPOINT_XFER_BULK << 11); |
| 521 | if (usb_pipein (pipe)) | 528 | if (usb_pipein (pipe)) |
| 522 | clear->devinfo |= 1 << 15; | 529 | clear->devinfo |= 1 << 15; |
| 523 | 530 | ||
| 531 | /* info for completion callback */ | ||
| 532 | clear->hcd = bus_to_hcd(udev->bus); | ||
| 533 | clear->ep = urb->ep; | ||
| 534 | |||
| 524 | /* tell keventd to clear state for this TT */ | 535 | /* tell keventd to clear state for this TT */ |
| 525 | spin_lock_irqsave (&tt->lock, flags); | 536 | spin_lock_irqsave (&tt->lock, flags); |
| 526 | list_add_tail (&clear->clear_list, &tt->clear_list); | 537 | list_add_tail (&clear->clear_list, &tt->clear_list); |
| 527 | schedule_work (&tt->kevent); | 538 | schedule_work(&tt->clear_work); |
| 528 | spin_unlock_irqrestore (&tt->lock, flags); | 539 | spin_unlock_irqrestore (&tt->lock, flags); |
| 540 | return 0; | ||
| 529 | } | 541 | } |
| 530 | EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer); | 542 | EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer); |
| 531 | 543 | ||
| 532 | /* If do_delay is false, return the number of milliseconds the caller | 544 | /* If do_delay is false, return the number of milliseconds the caller |
| 533 | * needs to delay. | 545 | * needs to delay. |
| @@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) | |||
| 818 | if (hub->has_indicators) | 830 | if (hub->has_indicators) |
| 819 | cancel_delayed_work_sync(&hub->leds); | 831 | cancel_delayed_work_sync(&hub->leds); |
| 820 | if (hub->tt.hub) | 832 | if (hub->tt.hub) |
| 821 | cancel_work_sync(&hub->tt.kevent); | 833 | cancel_work_sync(&hub->tt.clear_work); |
| 822 | } | 834 | } |
| 823 | 835 | ||
| 824 | /* caller has locked the hub device */ | 836 | /* caller has locked the hub device */ |
| @@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub, | |||
| 935 | 947 | ||
| 936 | spin_lock_init (&hub->tt.lock); | 948 | spin_lock_init (&hub->tt.lock); |
| 937 | INIT_LIST_HEAD (&hub->tt.clear_list); | 949 | INIT_LIST_HEAD (&hub->tt.clear_list); |
| 938 | INIT_WORK (&hub->tt.kevent, hub_tt_kevent); | 950 | INIT_WORK(&hub->tt.clear_work, hub_tt_work); |
| 939 | switch (hdev->descriptor.bDeviceProtocol) { | 951 | switch (hdev->descriptor.bDeviceProtocol) { |
| 940 | case 0: | 952 | case 0: |
| 941 | break; | 953 | break; |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 889c0f32a40b..de8081f065ed 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
| @@ -188,16 +188,18 @@ struct usb_tt { | |||
| 188 | /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ | 188 | /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ |
| 189 | spinlock_t lock; | 189 | spinlock_t lock; |
| 190 | struct list_head clear_list; /* of usb_tt_clear */ | 190 | struct list_head clear_list; /* of usb_tt_clear */ |
| 191 | struct work_struct kevent; | 191 | struct work_struct clear_work; |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | struct usb_tt_clear { | 194 | struct usb_tt_clear { |
| 195 | struct list_head clear_list; | 195 | struct list_head clear_list; |
| 196 | unsigned tt; | 196 | unsigned tt; |
| 197 | u16 devinfo; | 197 | u16 devinfo; |
| 198 | struct usb_hcd *hcd; | ||
| 199 | struct usb_host_endpoint *ep; | ||
| 198 | }; | 200 | }; |
| 199 | 201 | ||
| 200 | extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe); | 202 | extern int usb_hub_clear_tt_buffer(struct urb *urb); |
| 201 | extern void usb_ep0_reinit(struct usb_device *); | 203 | extern void usb_ep0_reinit(struct usb_device *); |
| 202 | 204 | ||
| 203 | #endif /* __LINUX_HUB_H */ | 205 | #endif /* __LINUX_HUB_H */ |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2bed83caacb1..9720e699f472 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
| 806 | return rc; | 806 | return rc; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf) | ||
| 810 | { | ||
| 811 | int err; | ||
| 812 | |||
| 813 | if (dev->have_langid) | ||
| 814 | return 0; | ||
| 815 | |||
| 816 | if (dev->string_langid < 0) | ||
| 817 | return -EPIPE; | ||
| 818 | |||
| 819 | err = usb_string_sub(dev, 0, 0, tbuf); | ||
| 820 | |||
| 821 | /* If the string was reported but is malformed, default to english | ||
| 822 | * (0x0409) */ | ||
| 823 | if (err == -ENODATA || (err > 0 && err < 4)) { | ||
| 824 | dev->string_langid = 0x0409; | ||
| 825 | dev->have_langid = 1; | ||
| 826 | dev_err(&dev->dev, | ||
| 827 | "string descriptor 0 malformed (err = %d), " | ||
| 828 | "defaulting to 0x%04x\n", | ||
| 829 | err, dev->string_langid); | ||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* In case of all other errors, we assume the device is not able to | ||
| 834 | * deal with strings at all. Set string_langid to -1 in order to | ||
| 835 | * prevent any string to be retrieved from the device */ | ||
| 836 | if (err < 0) { | ||
| 837 | dev_err(&dev->dev, "string descriptor 0 read error: %d\n", | ||
| 838 | err); | ||
| 839 | dev->string_langid = -1; | ||
| 840 | return -EPIPE; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* always use the first langid listed */ | ||
| 844 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
| 845 | dev->have_langid = 1; | ||
| 846 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
| 847 | dev->string_langid); | ||
| 848 | return 0; | ||
| 849 | } | ||
| 850 | |||
| 809 | /** | 851 | /** |
| 810 | * usb_string - returns UTF-8 version of a string descriptor | 852 | * usb_string - returns UTF-8 version of a string descriptor |
| 811 | * @dev: the device whose string descriptor is being retrieved | 853 | * @dev: the device whose string descriptor is being retrieved |
| @@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
| 837 | if (!tbuf) | 879 | if (!tbuf) |
| 838 | return -ENOMEM; | 880 | return -ENOMEM; |
| 839 | 881 | ||
| 840 | /* get langid for strings if it's not yet known */ | 882 | err = usb_get_langid(dev, tbuf); |
| 841 | if (!dev->have_langid) { | 883 | if (err < 0) |
| 842 | err = usb_string_sub(dev, 0, 0, tbuf); | 884 | goto errout; |
| 843 | if (err < 0) { | ||
| 844 | dev_err(&dev->dev, | ||
| 845 | "string descriptor 0 read error: %d\n", | ||
| 846 | err); | ||
| 847 | } else if (err < 4) { | ||
| 848 | dev_err(&dev->dev, "string descriptor 0 too short\n"); | ||
| 849 | } else { | ||
| 850 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
| 851 | /* always use the first langid listed */ | ||
| 852 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
| 853 | dev->string_langid); | ||
| 854 | } | ||
| 855 | |||
| 856 | dev->have_langid = 1; | ||
| 857 | } | ||
| 858 | 885 | ||
| 859 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); | 886 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); |
| 860 | if (err < 0) | 887 | if (err < 0) |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5d1ddf485d1e..7f8e83a954ac 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
| @@ -286,6 +286,27 @@ config USB_S3C_HSOTG | |||
| 286 | default USB_GADGET | 286 | default USB_GADGET |
| 287 | select USB_GADGET_SELECTED | 287 | select USB_GADGET_SELECTED |
| 288 | 288 | ||
| 289 | config USB_GADGET_IMX | ||
| 290 | boolean "Freescale IMX USB Peripheral Controller" | ||
| 291 | depends on ARCH_MX1 | ||
| 292 | help | ||
| 293 | Freescale's IMX series include an integrated full speed | ||
| 294 | USB 1.1 device controller. The controller in the IMX series | ||
| 295 | is register-compatible. | ||
| 296 | |||
| 297 | It has Six fixed-function endpoints, as well as endpoint | ||
| 298 | zero (for control transfers). | ||
| 299 | |||
| 300 | Say "y" to link the driver statically, or "m" to build a | ||
| 301 | dynamically linked module called "imx_udc" and force all | ||
| 302 | gadget drivers to also be dynamically linked. | ||
| 303 | |||
| 304 | config USB_IMX | ||
| 305 | tristate | ||
| 306 | depends on USB_GADGET_IMX | ||
| 307 | default USB_GADGET | ||
| 308 | select USB_GADGET_SELECTED | ||
| 309 | |||
| 289 | config USB_GADGET_S3C2410 | 310 | config USB_GADGET_S3C2410 |
| 290 | boolean "S3C2410 USB Device Controller" | 311 | boolean "S3C2410 USB Device Controller" |
| 291 | depends on ARCH_S3C2410 | 312 | depends on ARCH_S3C2410 |
| @@ -321,27 +342,6 @@ config USB_GADGET_MUSB_HDRC | |||
| 321 | This OTG-capable silicon IP is used in dual designs including | 342 | This OTG-capable silicon IP is used in dual designs including |
| 322 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin | 343 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin |
| 323 | 344 | ||
| 324 | config USB_GADGET_IMX | ||
| 325 | boolean "Freescale IMX USB Peripheral Controller" | ||
| 326 | depends on ARCH_MX1 | ||
| 327 | help | ||
| 328 | Freescale's IMX series include an integrated full speed | ||
| 329 | USB 1.1 device controller. The controller in the IMX series | ||
| 330 | is register-compatible. | ||
| 331 | |||
| 332 | It has Six fixed-function endpoints, as well as endpoint | ||
| 333 | zero (for control transfers). | ||
| 334 | |||
| 335 | Say "y" to link the driver statically, or "m" to build a | ||
| 336 | dynamically linked module called "imx_udc" and force all | ||
| 337 | gadget drivers to also be dynamically linked. | ||
| 338 | |||
| 339 | config USB_IMX | ||
| 340 | tristate | ||
| 341 | depends on USB_GADGET_IMX | ||
| 342 | default USB_GADGET | ||
| 343 | select USB_GADGET_SELECTED | ||
| 344 | |||
| 345 | config USB_GADGET_M66592 | 345 | config USB_GADGET_M66592 |
| 346 | boolean "Renesas M66592 USB Peripheral Controller" | 346 | boolean "Renesas M66592 USB Peripheral Controller" |
| 347 | select USB_GADGET_DUALSPEED | 347 | select USB_GADGET_DUALSPEED |
| @@ -604,6 +604,7 @@ config USB_ZERO_HNPTEST | |||
| 604 | config USB_AUDIO | 604 | config USB_AUDIO |
| 605 | tristate "Audio Gadget (EXPERIMENTAL)" | 605 | tristate "Audio Gadget (EXPERIMENTAL)" |
| 606 | depends on SND | 606 | depends on SND |
| 607 | select SND_PCM | ||
| 607 | help | 608 | help |
| 608 | Gadget Audio is compatible with USB Audio Class specification 1.0. | 609 | Gadget Audio is compatible with USB Audio Class specification 1.0. |
| 609 | It will include at least one AudioControl interface, zero or more | 610 | It will include at least one AudioControl interface, zero or more |
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 826f3adde5d8..77352ccc245e 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c | |||
| @@ -48,7 +48,6 @@ | |||
| 48 | #include <linux/ioport.h> | 48 | #include <linux/ioport.h> |
| 49 | #include <linux/sched.h> | 49 | #include <linux/sched.h> |
| 50 | #include <linux/slab.h> | 50 | #include <linux/slab.h> |
| 51 | #include <linux/smp_lock.h> | ||
| 52 | #include <linux/errno.h> | 51 | #include <linux/errno.h> |
| 53 | #include <linux/init.h> | 52 | #include <linux/init.h> |
| 54 | #include <linux/timer.h> | 53 | #include <linux/timer.h> |
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 94de7e864614..9f80f4e970bd 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c | |||
| @@ -42,9 +42,9 @@ | |||
| 42 | * Instead: allocate your own, using normal USB-IF procedures. | 42 | * Instead: allocate your own, using normal USB-IF procedures. |
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | /* Thanks to NetChip Technologies for donating this product ID. */ | 45 | /* Thanks to Linux Foundation for donating this product ID. */ |
| 46 | #define AUDIO_VENDOR_NUM 0x0525 /* NetChip */ | 46 | #define AUDIO_VENDOR_NUM 0x1d6b /* Linux Foundation */ |
| 47 | #define AUDIO_PRODUCT_NUM 0xa4a1 /* Linux-USB Audio Gadget */ | 47 | #define AUDIO_PRODUCT_NUM 0x0101 /* Linux-USB Audio Gadget */ |
| 48 | 48 | ||
| 49 | /*-------------------------------------------------------------------------*/ | 49 | /*-------------------------------------------------------------------------*/ |
| 50 | 50 | ||
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index d006dc652e02..bd102f5052ba 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
| @@ -293,15 +293,16 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
| 293 | /* CDC Subset */ | 293 | /* CDC Subset */ |
| 294 | eth_config_driver.label = "CDC Subset/SAFE"; | 294 | eth_config_driver.label = "CDC Subset/SAFE"; |
| 295 | 295 | ||
| 296 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM), | 296 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM); |
| 297 | device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM), | 297 | device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM); |
| 298 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; | 298 | if (!has_rndis()) |
| 299 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; | ||
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | if (has_rndis()) { | 302 | if (has_rndis()) { |
| 302 | /* RNDIS plus ECM-or-Subset */ | 303 | /* RNDIS plus ECM-or-Subset */ |
| 303 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM), | 304 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM); |
| 304 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM), | 305 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM); |
| 305 | device_desc.bNumConfigurations = 2; | 306 | device_desc.bNumConfigurations = 2; |
| 306 | } | 307 | } |
| 307 | 308 | ||
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 6829d5961359..a3913519fd58 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
| 35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | #include <linux/smp_lock.h> | ||
| 38 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
| 39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
| 40 | #include <linux/timer.h> | 39 | #include <linux/timer.h> |
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 0ce4e2819847..ed21e263f832 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c | |||
| @@ -139,7 +139,7 @@ static int is_vbus_present(void) | |||
| 139 | { | 139 | { |
| 140 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 140 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
| 141 | 141 | ||
| 142 | if (mach->gpio_vbus) { | 142 | if (gpio_is_valid(mach->gpio_vbus)) { |
| 143 | int value = gpio_get_value(mach->gpio_vbus); | 143 | int value = gpio_get_value(mach->gpio_vbus); |
| 144 | 144 | ||
| 145 | if (mach->gpio_vbus_inverted) | 145 | if (mach->gpio_vbus_inverted) |
| @@ -158,7 +158,7 @@ static void pullup_off(void) | |||
| 158 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 158 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
| 159 | int off_level = mach->gpio_pullup_inverted; | 159 | int off_level = mach->gpio_pullup_inverted; |
| 160 | 160 | ||
| 161 | if (mach->gpio_pullup) | 161 | if (gpio_is_valid(mach->gpio_pullup)) |
| 162 | gpio_set_value(mach->gpio_pullup, off_level); | 162 | gpio_set_value(mach->gpio_pullup, off_level); |
| 163 | else if (mach->udc_command) | 163 | else if (mach->udc_command) |
| 164 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | 164 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); |
| @@ -169,7 +169,7 @@ static void pullup_on(void) | |||
| 169 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 169 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
| 170 | int on_level = !mach->gpio_pullup_inverted; | 170 | int on_level = !mach->gpio_pullup_inverted; |
| 171 | 171 | ||
| 172 | if (mach->gpio_pullup) | 172 | if (gpio_is_valid(mach->gpio_pullup)) |
| 173 | gpio_set_value(mach->gpio_pullup, on_level); | 173 | gpio_set_value(mach->gpio_pullup, on_level); |
| 174 | else if (mach->udc_command) | 174 | else if (mach->udc_command) |
| 175 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); | 175 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); |
| @@ -1000,7 +1000,7 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active) | |||
| 1000 | udc = container_of(_gadget, struct pxa25x_udc, gadget); | 1000 | udc = container_of(_gadget, struct pxa25x_udc, gadget); |
| 1001 | 1001 | ||
| 1002 | /* not all boards support pullup control */ | 1002 | /* not all boards support pullup control */ |
| 1003 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 1003 | if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) |
| 1004 | return -EOPNOTSUPP; | 1004 | return -EOPNOTSUPP; |
| 1005 | 1005 | ||
| 1006 | udc->pullup = (is_active != 0); | 1006 | udc->pullup = (is_active != 0); |
| @@ -1802,11 +1802,13 @@ pxa25x_udc_irq(int irq, void *_dev) | |||
| 1802 | USIR0 |= tmp; | 1802 | USIR0 |= tmp; |
| 1803 | handled = 1; | 1803 | handled = 1; |
| 1804 | } | 1804 | } |
| 1805 | #ifndef CONFIG_USB_PXA25X_SMALL | ||
| 1805 | if (usir1 & tmp) { | 1806 | if (usir1 & tmp) { |
| 1806 | handle_ep(&dev->ep[i+8]); | 1807 | handle_ep(&dev->ep[i+8]); |
| 1807 | USIR1 |= tmp; | 1808 | USIR1 |= tmp; |
| 1808 | handled = 1; | 1809 | handled = 1; |
| 1809 | } | 1810 | } |
| 1811 | #endif | ||
| 1810 | } | 1812 | } |
| 1811 | } | 1813 | } |
| 1812 | 1814 | ||
| @@ -2160,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
| 2160 | dev->dev = &pdev->dev; | 2162 | dev->dev = &pdev->dev; |
| 2161 | dev->mach = pdev->dev.platform_data; | 2163 | dev->mach = pdev->dev.platform_data; |
| 2162 | 2164 | ||
| 2163 | if (dev->mach->gpio_vbus) { | 2165 | if (gpio_is_valid(dev->mach->gpio_vbus)) { |
| 2164 | if ((retval = gpio_request(dev->mach->gpio_vbus, | 2166 | if ((retval = gpio_request(dev->mach->gpio_vbus, |
| 2165 | "pxa25x_udc GPIO VBUS"))) { | 2167 | "pxa25x_udc GPIO VBUS"))) { |
| 2166 | dev_dbg(&pdev->dev, | 2168 | dev_dbg(&pdev->dev, |
| @@ -2173,7 +2175,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
| 2173 | } else | 2175 | } else |
| 2174 | vbus_irq = 0; | 2176 | vbus_irq = 0; |
| 2175 | 2177 | ||
| 2176 | if (dev->mach->gpio_pullup) { | 2178 | if (gpio_is_valid(dev->mach->gpio_pullup)) { |
| 2177 | if ((retval = gpio_request(dev->mach->gpio_pullup, | 2179 | if ((retval = gpio_request(dev->mach->gpio_pullup, |
| 2178 | "pca25x_udc GPIO PULLUP"))) { | 2180 | "pca25x_udc GPIO PULLUP"))) { |
| 2179 | dev_dbg(&pdev->dev, | 2181 | dev_dbg(&pdev->dev, |
| @@ -2256,10 +2258,10 @@ lubbock_fail0: | |||
| 2256 | #endif | 2258 | #endif |
| 2257 | free_irq(irq, dev); | 2259 | free_irq(irq, dev); |
| 2258 | err_irq1: | 2260 | err_irq1: |
| 2259 | if (dev->mach->gpio_pullup) | 2261 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
| 2260 | gpio_free(dev->mach->gpio_pullup); | 2262 | gpio_free(dev->mach->gpio_pullup); |
| 2261 | err_gpio_pullup: | 2263 | err_gpio_pullup: |
| 2262 | if (dev->mach->gpio_vbus) | 2264 | if (gpio_is_valid(dev->mach->gpio_vbus)) |
| 2263 | gpio_free(dev->mach->gpio_vbus); | 2265 | gpio_free(dev->mach->gpio_vbus); |
| 2264 | err_gpio_vbus: | 2266 | err_gpio_vbus: |
| 2265 | clk_put(dev->clk); | 2267 | clk_put(dev->clk); |
| @@ -2294,11 +2296,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) | |||
| 2294 | free_irq(LUBBOCK_USB_IRQ, dev); | 2296 | free_irq(LUBBOCK_USB_IRQ, dev); |
| 2295 | } | 2297 | } |
| 2296 | #endif | 2298 | #endif |
| 2297 | if (dev->mach->gpio_vbus) { | 2299 | if (gpio_is_valid(dev->mach->gpio_vbus)) { |
| 2298 | free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); | 2300 | free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); |
| 2299 | gpio_free(dev->mach->gpio_vbus); | 2301 | gpio_free(dev->mach->gpio_vbus); |
| 2300 | } | 2302 | } |
| 2301 | if (dev->mach->gpio_pullup) | 2303 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
| 2302 | gpio_free(dev->mach->gpio_pullup); | 2304 | gpio_free(dev->mach->gpio_pullup); |
| 2303 | 2305 | ||
| 2304 | clk_put(dev->clk); | 2306 | clk_put(dev->clk); |
| @@ -2329,7 +2331,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state) | |||
| 2329 | struct pxa25x_udc *udc = platform_get_drvdata(dev); | 2331 | struct pxa25x_udc *udc = platform_get_drvdata(dev); |
| 2330 | unsigned long flags; | 2332 | unsigned long flags; |
| 2331 | 2333 | ||
| 2332 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 2334 | if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) |
| 2333 | WARNING("USB host won't detect disconnect!\n"); | 2335 | WARNING("USB host won't detect disconnect!\n"); |
| 2334 | udc->suspended = 1; | 2336 | udc->suspended = 1; |
| 2335 | 2337 | ||
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 2b4660e08c4d..ca41b0b5afb3 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
| @@ -442,6 +442,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
| 442 | 442 | ||
| 443 | case OID_802_3_MAC_OPTIONS: | 443 | case OID_802_3_MAC_OPTIONS: |
| 444 | pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); | 444 | pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); |
| 445 | *outbuf = cpu_to_le32(0); | ||
| 446 | retval = 0; | ||
| 445 | break; | 447 | break; |
| 446 | 448 | ||
| 447 | /* ieee802.3 statistics OIDs (table 4-4) */ | 449 | /* ieee802.3 statistics OIDs (table 4-4) */ |
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 9a2b8920532d..a9b452fe6221 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/smp_lock.h> | ||
| 32 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
| 33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
| 34 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1576a0520adf..1a920c70b5a1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
| @@ -181,26 +181,27 @@ config USB_OHCI_HCD_PPC_SOC | |||
| 181 | Enables support for the USB controller on the MPC52xx or | 181 | Enables support for the USB controller on the MPC52xx or |
| 182 | STB03xxx processor chip. If unsure, say Y. | 182 | STB03xxx processor chip. If unsure, say Y. |
| 183 | 183 | ||
| 184 | config USB_OHCI_HCD_PPC_OF | ||
| 185 | bool "OHCI support for PPC USB controller on OF platform bus" | ||
| 186 | depends on USB_OHCI_HCD && PPC_OF | ||
| 187 | default y | ||
| 188 | ---help--- | ||
| 189 | Enables support for the USB controller PowerPC present on the | ||
| 190 | OpenFirmware platform bus. | ||
| 191 | |||
| 192 | config USB_OHCI_HCD_PPC_OF_BE | 184 | config USB_OHCI_HCD_PPC_OF_BE |
| 193 | bool "Support big endian HC" | 185 | bool "OHCI support for OF platform bus (big endian)" |
| 194 | depends on USB_OHCI_HCD_PPC_OF | 186 | depends on USB_OHCI_HCD && PPC_OF |
| 195 | default y | ||
| 196 | select USB_OHCI_BIG_ENDIAN_DESC | 187 | select USB_OHCI_BIG_ENDIAN_DESC |
| 197 | select USB_OHCI_BIG_ENDIAN_MMIO | 188 | select USB_OHCI_BIG_ENDIAN_MMIO |
| 189 | ---help--- | ||
| 190 | Enables support for big-endian USB controllers present on the | ||
| 191 | OpenFirmware platform bus. | ||
| 198 | 192 | ||
| 199 | config USB_OHCI_HCD_PPC_OF_LE | 193 | config USB_OHCI_HCD_PPC_OF_LE |
| 200 | bool "Support little endian HC" | 194 | bool "OHCI support for OF platform bus (little endian)" |
| 201 | depends on USB_OHCI_HCD_PPC_OF | 195 | depends on USB_OHCI_HCD && PPC_OF |
| 202 | default n | ||
| 203 | select USB_OHCI_LITTLE_ENDIAN | 196 | select USB_OHCI_LITTLE_ENDIAN |
| 197 | ---help--- | ||
| 198 | Enables support for little-endian USB controllers present on the | ||
| 199 | OpenFirmware platform bus. | ||
| 200 | |||
| 201 | config USB_OHCI_HCD_PPC_OF | ||
| 202 | bool | ||
| 203 | depends on USB_OHCI_HCD && PPC_OF | ||
| 204 | default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE | ||
| 204 | 205 | ||
| 205 | config USB_OHCI_HCD_PCI | 206 | config USB_OHCI_HCD_PCI |
| 206 | bool "OHCI support for PCI-bus USB controllers" | 207 | bool "OHCI support for PCI-bus USB controllers" |
| @@ -337,10 +338,10 @@ config USB_R8A66597_HCD | |||
| 337 | 338 | ||
| 338 | config SUPERH_ON_CHIP_R8A66597 | 339 | config SUPERH_ON_CHIP_R8A66597 |
| 339 | boolean "Enable SuperH on-chip R8A66597 USB" | 340 | boolean "Enable SuperH on-chip R8A66597 USB" |
| 340 | depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723) | 341 | depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724) |
| 341 | help | 342 | help |
| 342 | This driver enables support for the on-chip R8A66597 in the | 343 | This driver enables support for the on-chip R8A66597 in the |
| 343 | SH7366 and SH7723 processors. | 344 | SH7366, SH7723 and SH7724 processors. |
| 344 | 345 | ||
| 345 | config USB_WHCI_HCD | 346 | config USB_WHCI_HCD |
| 346 | tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" | 347 | tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index c3a778bd359c..59d208d94d4e 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
| @@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { | |||
| 113 | .bus_resume = ehci_bus_resume, | 113 | .bus_resume = ehci_bus_resume, |
| 114 | .relinquish_port = ehci_relinquish_port, | 114 | .relinquish_port = ehci_relinquish_port, |
| 115 | .port_handed_over = ehci_port_handed_over, | 115 | .port_handed_over = ehci_port_handed_over, |
| 116 | |||
| 117 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 116 | }; | 118 | }; |
| 117 | 119 | ||
| 118 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | 120 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index bf86809c5120..991174937db3 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
| @@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = { | |||
| 325 | .bus_resume = ehci_bus_resume, | 325 | .bus_resume = ehci_bus_resume, |
| 326 | .relinquish_port = ehci_relinquish_port, | 326 | .relinquish_port = ehci_relinquish_port, |
| 327 | .port_handed_over = ehci_port_handed_over, | 327 | .port_handed_over = ehci_port_handed_over, |
| 328 | |||
| 329 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 328 | }; | 330 | }; |
| 329 | 331 | ||
| 330 | static int ehci_fsl_drv_probe(struct platform_device *pdev) | 332 | static int ehci_fsl_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2b72473544d3..7d03549c3339 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -1003,6 +1003,8 @@ idle_timeout: | |||
| 1003 | schedule_timeout_uninterruptible(1); | 1003 | schedule_timeout_uninterruptible(1); |
| 1004 | goto rescan; | 1004 | goto rescan; |
| 1005 | case QH_STATE_IDLE: /* fully unlinked */ | 1005 | case QH_STATE_IDLE: /* fully unlinked */ |
| 1006 | if (qh->clearing_tt) | ||
| 1007 | goto idle_timeout; | ||
| 1006 | if (list_empty (&qh->qtd_list)) { | 1008 | if (list_empty (&qh->qtd_list)) { |
| 1007 | qh_put (qh); | 1009 | qh_put (qh); |
| 1008 | break; | 1010 | break; |
| @@ -1030,12 +1032,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
| 1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1032 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 1031 | struct ehci_qh *qh; | 1033 | struct ehci_qh *qh; |
| 1032 | int eptype = usb_endpoint_type(&ep->desc); | 1034 | int eptype = usb_endpoint_type(&ep->desc); |
| 1035 | int epnum = usb_endpoint_num(&ep->desc); | ||
| 1036 | int is_out = usb_endpoint_dir_out(&ep->desc); | ||
| 1037 | unsigned long flags; | ||
| 1033 | 1038 | ||
| 1034 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | 1039 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) |
| 1035 | return; | 1040 | return; |
| 1036 | 1041 | ||
| 1037 | rescan: | 1042 | spin_lock_irqsave(&ehci->lock, flags); |
| 1038 | spin_lock_irq(&ehci->lock); | ||
| 1039 | qh = ep->hcpriv; | 1043 | qh = ep->hcpriv; |
| 1040 | 1044 | ||
| 1041 | /* For Bulk and Interrupt endpoints we maintain the toggle state | 1045 | /* For Bulk and Interrupt endpoints we maintain the toggle state |
| @@ -1044,29 +1048,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
| 1044 | * the toggle bit in the QH. | 1048 | * the toggle bit in the QH. |
| 1045 | */ | 1049 | */ |
| 1046 | if (qh) { | 1050 | if (qh) { |
| 1051 | usb_settoggle(qh->dev, epnum, is_out, 0); | ||
| 1047 | if (!list_empty(&qh->qtd_list)) { | 1052 | if (!list_empty(&qh->qtd_list)) { |
| 1048 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | 1053 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); |
| 1049 | } else if (qh->qh_state == QH_STATE_IDLE) { | 1054 | } else if (qh->qh_state == QH_STATE_LINKED) { |
| 1050 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | 1055 | |
| 1051 | } else { | 1056 | /* The toggle value in the QH can't be updated |
| 1052 | /* It's not safe to write into the overlay area | 1057 | * while the QH is active. Unlink it now; |
| 1053 | * while the QH is active. Unlink it first and | 1058 | * re-linking will call qh_refresh(). |
| 1054 | * wait for the unlink to complete. | ||
| 1055 | */ | 1059 | */ |
| 1056 | if (qh->qh_state == QH_STATE_LINKED) { | 1060 | if (eptype == USB_ENDPOINT_XFER_BULK) { |
| 1057 | if (eptype == USB_ENDPOINT_XFER_BULK) { | 1061 | unlink_async(ehci, qh); |
| 1058 | unlink_async(ehci, qh); | 1062 | } else { |
| 1059 | } else { | 1063 | intr_deschedule(ehci, qh); |
| 1060 | intr_deschedule(ehci, qh); | 1064 | (void) qh_schedule(ehci, qh); |
| 1061 | (void) qh_schedule(ehci, qh); | ||
| 1062 | } | ||
| 1063 | } | 1065 | } |
| 1064 | spin_unlock_irq(&ehci->lock); | ||
| 1065 | schedule_timeout_uninterruptible(1); | ||
| 1066 | goto rescan; | ||
| 1067 | } | 1066 | } |
| 1068 | } | 1067 | } |
| 1069 | spin_unlock_irq(&ehci->lock); | 1068 | spin_unlock_irqrestore(&ehci->lock, flags); |
| 1070 | } | 1069 | } |
| 1071 | 1070 | ||
| 1072 | static int ehci_get_frame (struct usb_hcd *hcd) | 1071 | static int ehci_get_frame (struct usb_hcd *hcd) |
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index a44bb4a94954..89b7c70c6ed6 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c | |||
| @@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { | |||
| 61 | #endif | 61 | #endif |
| 62 | .relinquish_port = ehci_relinquish_port, | 62 | .relinquish_port = ehci_relinquish_port, |
| 63 | .port_handed_over = ehci_port_handed_over, | 63 | .port_handed_over = ehci_port_handed_over, |
| 64 | |||
| 65 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 64 | }; | 66 | }; |
| 65 | 67 | ||
| 66 | static int ixp4xx_ehci_probe(struct platform_device *pdev) | 68 | static int ixp4xx_ehci_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 770dd9aba62a..dc2ac613a9d1 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
| @@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = { | |||
| 165 | .bus_resume = ehci_bus_resume, | 165 | .bus_resume = ehci_bus_resume, |
| 166 | .relinquish_port = ehci_relinquish_port, | 166 | .relinquish_port = ehci_relinquish_port, |
| 167 | .port_handed_over = ehci_port_handed_over, | 167 | .port_handed_over = ehci_port_handed_over, |
| 168 | |||
| 169 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 168 | }; | 170 | }; |
| 169 | 171 | ||
| 170 | static void __init | 172 | static void __init |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index f3683e1da161..c2f1b7df918c 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
| 404 | .bus_resume = ehci_bus_resume, | 404 | .bus_resume = ehci_bus_resume, |
| 405 | .relinquish_port = ehci_relinquish_port, | 405 | .relinquish_port = ehci_relinquish_port, |
| 406 | .port_handed_over = ehci_port_handed_over, | 406 | .port_handed_over = ehci_port_handed_over, |
| 407 | |||
| 408 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 407 | }; | 409 | }; |
| 408 | 410 | ||
| 409 | /*-------------------------------------------------------------------------*/ | 411 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index fbd272288fc2..36f96da129f5 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
| @@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { | |||
| 79 | #endif | 79 | #endif |
| 80 | .relinquish_port = ehci_relinquish_port, | 80 | .relinquish_port = ehci_relinquish_port, |
| 81 | .port_handed_over = ehci_port_handed_over, | 81 | .port_handed_over = ehci_port_handed_over, |
| 82 | |||
| 83 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 82 | }; | 84 | }; |
| 83 | 85 | ||
| 84 | 86 | ||
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 93f7035d00a1..1dee33b9139e 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
| @@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = { | |||
| 75 | #endif | 75 | #endif |
| 76 | .relinquish_port = ehci_relinquish_port, | 76 | .relinquish_port = ehci_relinquish_port, |
| 77 | .port_handed_over = ehci_port_handed_over, | 77 | .port_handed_over = ehci_port_handed_over, |
| 78 | |||
| 79 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| 80 | static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) | 82 | static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3192f683f807..9a1384747f3b 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
| 93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); | 93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); |
| 94 | qh->hw_alt_next = EHCI_LIST_END(ehci); | 94 | qh->hw_alt_next = EHCI_LIST_END(ehci); |
| 95 | 95 | ||
| 96 | /* Except for control endpoints, we make hardware maintain data | ||
| 97 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | ||
| 98 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | ||
| 99 | * ever clear it. | ||
| 100 | */ | ||
| 101 | if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { | ||
| 102 | unsigned is_out, epnum; | ||
| 103 | |||
| 104 | is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); | ||
| 105 | epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; | ||
| 106 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | ||
| 107 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | ||
| 108 | usb_settoggle (qh->dev, epnum, is_out, 1); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 96 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | 112 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ |
| 97 | wmb (); | 113 | wmb (); |
| 98 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); | 114 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
| @@ -123,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 123 | 139 | ||
| 124 | /*-------------------------------------------------------------------------*/ | 140 | /*-------------------------------------------------------------------------*/ |
| 125 | 141 | ||
| 142 | static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh); | ||
| 143 | |||
| 144 | static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, | ||
| 145 | struct usb_host_endpoint *ep) | ||
| 146 | { | ||
| 147 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 148 | struct ehci_qh *qh = ep->hcpriv; | ||
| 149 | unsigned long flags; | ||
| 150 | |||
| 151 | spin_lock_irqsave(&ehci->lock, flags); | ||
| 152 | qh->clearing_tt = 0; | ||
| 153 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) | ||
| 154 | && HC_IS_RUNNING(hcd->state)) | ||
| 155 | qh_link_async(ehci, qh); | ||
| 156 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh, | ||
| 160 | struct urb *urb, u32 token) | ||
| 161 | { | ||
| 162 | |||
| 163 | /* If an async split transaction gets an error or is unlinked, | ||
| 164 | * the TT buffer may be left in an indeterminate state. We | ||
| 165 | * have to clear the TT buffer. | ||
| 166 | * | ||
| 167 | * Note: this routine is never called for Isochronous transfers. | ||
| 168 | */ | ||
| 169 | if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { | ||
| 170 | #ifdef DEBUG | ||
| 171 | struct usb_device *tt = urb->dev->tt->hub; | ||
| 172 | dev_dbg(&tt->dev, | ||
| 173 | "clear tt buffer port %d, a%d ep%d t%08x\n", | ||
| 174 | urb->dev->ttport, urb->dev->devnum, | ||
| 175 | usb_pipeendpoint(urb->pipe), token); | ||
| 176 | #endif /* DEBUG */ | ||
| 177 | if (!ehci_is_TDI(ehci) | ||
| 178 | || urb->dev->tt->hub != | ||
| 179 | ehci_to_hcd(ehci)->self.root_hub) { | ||
| 180 | if (usb_hub_clear_tt_buffer(urb) == 0) | ||
| 181 | qh->clearing_tt = 1; | ||
| 182 | } else { | ||
| 183 | |||
| 184 | /* REVISIT ARC-derived cores don't clear the root | ||
| 185 | * hub TT buffer in this way... | ||
| 186 | */ | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 126 | static int qtd_copy_status ( | 191 | static int qtd_copy_status ( |
| 127 | struct ehci_hcd *ehci, | 192 | struct ehci_hcd *ehci, |
| 128 | struct urb *urb, | 193 | struct urb *urb, |
| @@ -149,6 +214,14 @@ static int qtd_copy_status ( | |||
| 149 | if (token & QTD_STS_BABBLE) { | 214 | if (token & QTD_STS_BABBLE) { |
| 150 | /* FIXME "must" disable babbling device's port too */ | 215 | /* FIXME "must" disable babbling device's port too */ |
| 151 | status = -EOVERFLOW; | 216 | status = -EOVERFLOW; |
| 217 | /* CERR nonzero + halt --> stall */ | ||
| 218 | } else if (QTD_CERR(token)) { | ||
| 219 | status = -EPIPE; | ||
| 220 | |||
| 221 | /* In theory, more than one of the following bits can be set | ||
| 222 | * since they are sticky and the transaction is retried. | ||
| 223 | * Which to test first is rather arbitrary. | ||
| 224 | */ | ||
| 152 | } else if (token & QTD_STS_MMF) { | 225 | } else if (token & QTD_STS_MMF) { |
| 153 | /* fs/ls interrupt xfer missed the complete-split */ | 226 | /* fs/ls interrupt xfer missed the complete-split */ |
| 154 | status = -EPROTO; | 227 | status = -EPROTO; |
| @@ -157,21 +230,15 @@ static int qtd_copy_status ( | |||
| 157 | ? -ENOSR /* hc couldn't read data */ | 230 | ? -ENOSR /* hc couldn't read data */ |
| 158 | : -ECOMM; /* hc couldn't write data */ | 231 | : -ECOMM; /* hc couldn't write data */ |
| 159 | } else if (token & QTD_STS_XACT) { | 232 | } else if (token & QTD_STS_XACT) { |
| 160 | /* timeout, bad crc, wrong PID, etc; retried */ | 233 | /* timeout, bad CRC, wrong PID, etc */ |
| 161 | if (QTD_CERR (token)) | 234 | ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n", |
| 162 | status = -EPIPE; | 235 | urb->dev->devpath, |
| 163 | else { | 236 | usb_pipeendpoint(urb->pipe), |
| 164 | ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", | 237 | usb_pipein(urb->pipe) ? "in" : "out"); |
| 165 | urb->dev->devpath, | 238 | status = -EPROTO; |
| 166 | usb_pipeendpoint (urb->pipe), | 239 | } else { /* unknown */ |
| 167 | usb_pipein (urb->pipe) ? "in" : "out"); | ||
| 168 | status = -EPROTO; | ||
| 169 | } | ||
| 170 | /* CERR nonzero + no errors + halt --> stall */ | ||
| 171 | } else if (QTD_CERR (token)) | ||
| 172 | status = -EPIPE; | ||
| 173 | else /* unknown */ | ||
| 174 | status = -EPROTO; | 240 | status = -EPROTO; |
| 241 | } | ||
| 175 | 242 | ||
| 176 | ehci_vdbg (ehci, | 243 | ehci_vdbg (ehci, |
| 177 | "dev%d ep%d%s qtd token %08x --> status %d\n", | 244 | "dev%d ep%d%s qtd token %08x --> status %d\n", |
| @@ -179,28 +246,6 @@ static int qtd_copy_status ( | |||
| 179 | usb_pipeendpoint (urb->pipe), | 246 | usb_pipeendpoint (urb->pipe), |
| 180 | usb_pipein (urb->pipe) ? "in" : "out", | 247 | usb_pipein (urb->pipe) ? "in" : "out", |
| 181 | token, status); | 248 | token, status); |
| 182 | |||
| 183 | /* if async CSPLIT failed, try cleaning out the TT buffer */ | ||
| 184 | if (status != -EPIPE | ||
| 185 | && urb->dev->tt | ||
| 186 | && !usb_pipeint(urb->pipe) | ||
| 187 | && ((token & QTD_STS_MMF) != 0 | ||
| 188 | || QTD_CERR(token) == 0) | ||
| 189 | && (!ehci_is_TDI(ehci) | ||
| 190 | || urb->dev->tt->hub != | ||
| 191 | ehci_to_hcd(ehci)->self.root_hub)) { | ||
| 192 | #ifdef DEBUG | ||
| 193 | struct usb_device *tt = urb->dev->tt->hub; | ||
| 194 | dev_dbg (&tt->dev, | ||
| 195 | "clear tt buffer port %d, a%d ep%d t%08x\n", | ||
| 196 | urb->dev->ttport, urb->dev->devnum, | ||
| 197 | usb_pipeendpoint (urb->pipe), token); | ||
| 198 | #endif /* DEBUG */ | ||
| 199 | /* REVISIT ARC-derived cores don't clear the root | ||
| 200 | * hub TT buffer in this way... | ||
| 201 | */ | ||
| 202 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); | ||
| 203 | } | ||
| 204 | } | 249 | } |
| 205 | 250 | ||
| 206 | return status; | 251 | return status; |
| @@ -391,9 +436,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 391 | /* qh unlinked; token in overlay may be most current */ | 436 | /* qh unlinked; token in overlay may be most current */ |
| 392 | if (state == QH_STATE_IDLE | 437 | if (state == QH_STATE_IDLE |
| 393 | && cpu_to_hc32(ehci, qtd->qtd_dma) | 438 | && cpu_to_hc32(ehci, qtd->qtd_dma) |
| 394 | == qh->hw_current) | 439 | == qh->hw_current) { |
| 395 | token = hc32_to_cpu(ehci, qh->hw_token); | 440 | token = hc32_to_cpu(ehci, qh->hw_token); |
| 396 | 441 | ||
| 442 | /* An unlink may leave an incomplete | ||
| 443 | * async transaction in the TT buffer. | ||
| 444 | * We have to clear it. | ||
| 445 | */ | ||
| 446 | ehci_clear_tt_buffer(ehci, qh, urb, token); | ||
| 447 | } | ||
| 448 | |||
| 397 | /* force halt for unlinked or blocked qh, so we'll | 449 | /* force halt for unlinked or blocked qh, so we'll |
| 398 | * patch the qh later and so that completions can't | 450 | * patch the qh later and so that completions can't |
| 399 | * activate it while we "know" it's stopped. | 451 | * activate it while we "know" it's stopped. |
| @@ -419,6 +471,13 @@ halt: | |||
| 419 | && (qtd->hw_alt_next | 471 | && (qtd->hw_alt_next |
| 420 | & EHCI_LIST_END(ehci))) | 472 | & EHCI_LIST_END(ehci))) |
| 421 | last_status = -EINPROGRESS; | 473 | last_status = -EINPROGRESS; |
| 474 | |||
| 475 | /* As part of low/full-speed endpoint-halt processing | ||
| 476 | * we must clear the TT buffer (11.17.5). | ||
| 477 | */ | ||
| 478 | if (unlikely(last_status != -EINPROGRESS && | ||
| 479 | last_status != -EREMOTEIO)) | ||
| 480 | ehci_clear_tt_buffer(ehci, qh, urb, token); | ||
| 422 | } | 481 | } |
| 423 | 482 | ||
| 424 | /* if we're removing something not at the queue head, | 483 | /* if we're removing something not at the queue head, |
| @@ -834,6 +893,7 @@ done: | |||
| 834 | qh->qh_state = QH_STATE_IDLE; | 893 | qh->qh_state = QH_STATE_IDLE; |
| 835 | qh->hw_info1 = cpu_to_hc32(ehci, info1); | 894 | qh->hw_info1 = cpu_to_hc32(ehci, info1); |
| 836 | qh->hw_info2 = cpu_to_hc32(ehci, info2); | 895 | qh->hw_info2 = cpu_to_hc32(ehci, info2); |
| 896 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | ||
| 837 | qh_refresh (ehci, qh); | 897 | qh_refresh (ehci, qh); |
| 838 | return qh; | 898 | return qh; |
| 839 | } | 899 | } |
| @@ -847,6 +907,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 847 | __hc32 dma = QH_NEXT(ehci, qh->qh_dma); | 907 | __hc32 dma = QH_NEXT(ehci, qh->qh_dma); |
| 848 | struct ehci_qh *head; | 908 | struct ehci_qh *head; |
| 849 | 909 | ||
| 910 | /* Don't link a QH if there's a Clear-TT-Buffer pending */ | ||
| 911 | if (unlikely(qh->clearing_tt)) | ||
| 912 | return; | ||
| 913 | |||
| 850 | /* (re)start the async schedule? */ | 914 | /* (re)start the async schedule? */ |
| 851 | head = ehci->async; | 915 | head = ehci->async; |
| 852 | timer_action_done (ehci, TIMER_ASYNC_OFF); | 916 | timer_action_done (ehci, TIMER_ASYNC_OFF); |
| @@ -864,7 +928,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
| 864 | } | 928 | } |
| 865 | } | 929 | } |
| 866 | 930 | ||
| 867 | /* clear halt and maybe recover from silicon quirk */ | 931 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ |
| 868 | if (qh->qh_state == QH_STATE_IDLE) | 932 | if (qh->qh_state == QH_STATE_IDLE) |
| 869 | qh_refresh (ehci, qh); | 933 | qh_refresh (ehci, qh); |
| 870 | 934 | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 9d1babc7ff65..74f7f83b29ad 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -1619,11 +1619,14 @@ itd_complete ( | |||
| 1619 | desc->status = -EPROTO; | 1619 | desc->status = -EPROTO; |
| 1620 | 1620 | ||
| 1621 | /* HC need not update length with this error */ | 1621 | /* HC need not update length with this error */ |
| 1622 | if (!(t & EHCI_ISOC_BABBLE)) | 1622 | if (!(t & EHCI_ISOC_BABBLE)) { |
| 1623 | desc->actual_length = EHCI_ITD_LENGTH (t); | 1623 | desc->actual_length = EHCI_ITD_LENGTH(t); |
| 1624 | urb->actual_length += desc->actual_length; | ||
| 1625 | } | ||
| 1624 | } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { | 1626 | } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { |
| 1625 | desc->status = 0; | 1627 | desc->status = 0; |
| 1626 | desc->actual_length = EHCI_ITD_LENGTH (t); | 1628 | desc->actual_length = EHCI_ITD_LENGTH(t); |
| 1629 | urb->actual_length += desc->actual_length; | ||
| 1627 | } else { | 1630 | } else { |
| 1628 | /* URB was too late */ | 1631 | /* URB was too late */ |
| 1629 | desc->status = -EXDEV; | 1632 | desc->status = -EXDEV; |
| @@ -2014,7 +2017,8 @@ sitd_complete ( | |||
| 2014 | desc->status = -EPROTO; | 2017 | desc->status = -EPROTO; |
| 2015 | } else { | 2018 | } else { |
| 2016 | desc->status = 0; | 2019 | desc->status = 0; |
| 2017 | desc->actual_length = desc->length - SITD_LENGTH (t); | 2020 | desc->actual_length = desc->length - SITD_LENGTH(t); |
| 2021 | urb->actual_length += desc->actual_length; | ||
| 2018 | } | 2022 | } |
| 2019 | stream->depth -= stream->interval << 3; | 2023 | stream->depth -= stream->interval << 3; |
| 2020 | 2024 | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 90ad3395bb21..2bfff30f4704 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
| @@ -354,7 +354,9 @@ struct ehci_qh { | |||
| 354 | unsigned short period; /* polling interval */ | 354 | unsigned short period; /* polling interval */ |
| 355 | unsigned short start; /* where polling starts */ | 355 | unsigned short start; /* where polling starts */ |
| 356 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | 356 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ |
| 357 | |||
| 357 | struct usb_device *dev; /* access to TT */ | 358 | struct usb_device *dev; /* access to TT */ |
| 359 | unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ | ||
| 358 | } __attribute__ ((aligned (32))); | 360 | } __attribute__ ((aligned (32))); |
| 359 | 361 | ||
| 360 | /*-------------------------------------------------------------------------*/ | 362 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index bb63b68ddb77..62a226b61670 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c | |||
| @@ -576,9 +576,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) | |||
| 576 | out_be16(&usb->fhci->regs->usb_event, | 576 | out_be16(&usb->fhci->regs->usb_event, |
| 577 | usb->saved_msk); | 577 | usb->saved_msk); |
| 578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { | 578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { |
| 579 | if (fhci_ioports_check_bus_state(fhci) == 1 && | 579 | if (fhci_ioports_check_bus_state(fhci) == 1) |
| 580 | usb->port_status != FHCI_PORT_LOW && | ||
| 581 | usb->port_status != FHCI_PORT_FULL) | ||
| 582 | fhci_device_connected_interrupt(fhci); | 580 | fhci_device_connected_interrupt(fhci); |
| 583 | } | 581 | } |
| 584 | usb_er &= ~USB_E_RESET_MASK; | 582 | usb_er &= ~USB_E_RESET_MASK; |
| @@ -605,9 +603,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) | |||
| 605 | } | 603 | } |
| 606 | 604 | ||
| 607 | if (usb_er & USB_E_IDLE_MASK) { | 605 | if (usb_er & USB_E_IDLE_MASK) { |
| 608 | if (usb->port_status == FHCI_PORT_DISABLED && | 606 | if (usb->port_status == FHCI_PORT_DISABLED) { |
| 609 | usb->port_status != FHCI_PORT_LOW && | ||
| 610 | usb->port_status != FHCI_PORT_FULL) { | ||
| 611 | usb_er &= ~USB_E_RESET_MASK; | 607 | usb_er &= ~USB_E_RESET_MASK; |
| 612 | fhci_device_connected_interrupt(fhci); | 608 | fhci_device_connected_interrupt(fhci); |
| 613 | } else if (usb->port_status == | 609 | } else if (usb->port_status == |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 3fa3a1702796..d4feebfc63bd 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
| @@ -361,7 +361,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev) | |||
| 361 | 361 | ||
| 362 | static struct platform_driver isp1760_plat_driver = { | 362 | static struct platform_driver isp1760_plat_driver = { |
| 363 | .probe = isp1760_plat_probe, | 363 | .probe = isp1760_plat_probe, |
| 364 | .remove = isp1760_plat_remove, | 364 | .remove = __devexit_p(isp1760_plat_remove), |
| 365 | .driver = { | 365 | .driver = { |
| 366 | .name = "isp1760", | 366 | .name = "isp1760", |
| 367 | }, | 367 | }, |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 56976cc0352a..e18f74946e68 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
| 31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 32 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 3c5fe5cee05a..90e1a8dedfa9 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/smp_lock.h> | ||
| 21 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
| 22 | #include <linux/usb/iowarrior.h> | 23 | #include <linux/usb/iowarrior.h> |
| 23 | 24 | ||
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index deb95bb49fd1..d645f3899fe1 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 33 | #include <linux/signal.h> | 33 | #include <linux/signal.h> |
| 34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
| 35 | #include <linux/smp_lock.h> | ||
| 35 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
| 36 | #include <linux/random.h> | 37 | #include <linux/random.h> |
| 37 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index e0ff9ccd866b..29092b8e59ce 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/smp_lock.h> | ||
| 19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| 20 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
| 21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f8d9045d668a..0f7a30b7d2d1 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
| @@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages) | |||
| 1261 | return -ENOMEM; | 1261 | return -ENOMEM; |
| 1262 | } | 1262 | } |
| 1263 | map[n].ptr = (unsigned char *) vaddr; | 1263 | map[n].ptr = (unsigned char *) vaddr; |
| 1264 | map[n].pg = virt_to_page(vaddr); | 1264 | map[n].pg = virt_to_page((void *) vaddr); |
| 1265 | } | 1265 | } |
| 1266 | return 0; | 1266 | return 0; |
| 1267 | } | 1267 | } |
diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h index 8a39de3e6e47..59bf949e589b 100644 --- a/drivers/usb/musb/cppi_dma.h +++ b/drivers/usb/musb/cppi_dma.h | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
| 7 | #include <linux/list.h> | 7 | #include <linux/list.h> |
| 8 | #include <linux/smp_lock.h> | ||
| 9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
| 10 | #include <linux/dmapool.h> | 9 | #include <linux/dmapool.h> |
| 11 | 10 | ||
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 180d7daa4099..e16ff605c458 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
| @@ -35,13 +35,14 @@ | |||
| 35 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
| 36 | #include <mach/memory.h> | 36 | #include <mach/memory.h> |
| 37 | #include <mach/gpio.h> | 37 | #include <mach/gpio.h> |
| 38 | #include <mach/cputype.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/mach-types.h> | 40 | #include <asm/mach-types.h> |
| 40 | 41 | ||
| 41 | #include "musb_core.h" | 42 | #include "musb_core.h" |
| 42 | 43 | ||
| 43 | #ifdef CONFIG_MACH_DAVINCI_EVM | 44 | #ifdef CONFIG_MACH_DAVINCI_EVM |
| 44 | #define GPIO_nVBUS_DRV 87 | 45 | #define GPIO_nVBUS_DRV 144 |
| 45 | #endif | 46 | #endif |
| 46 | 47 | ||
| 47 | #include "davinci.h" | 48 | #include "davinci.h" |
| @@ -329,7 +330,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
| 329 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | 330 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); |
| 330 | WARNING("VBUS error workaround (delay coming)\n"); | 331 | WARNING("VBUS error workaround (delay coming)\n"); |
| 331 | } else if (is_host_enabled(musb) && drvvbus) { | 332 | } else if (is_host_enabled(musb) && drvvbus) { |
| 332 | musb->is_active = 1; | ||
| 333 | MUSB_HST_MODE(musb); | 333 | MUSB_HST_MODE(musb); |
| 334 | musb->xceiv->default_a = 1; | 334 | musb->xceiv->default_a = 1; |
| 335 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | 335 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; |
| @@ -343,7 +343,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
| 343 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | 343 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | /* NOTE: this must complete poweron within 100 msec */ | 346 | /* NOTE: this must complete poweron within 100 msec |
| 347 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. | ||
| 348 | */ | ||
| 347 | davinci_source_power(musb, drvvbus, 0); | 349 | davinci_source_power(musb, drvvbus, 0); |
| 348 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", | 350 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", |
| 349 | drvvbus ? "on" : "off", | 351 | drvvbus ? "on" : "off", |
| @@ -411,6 +413,21 @@ int __init musb_platform_init(struct musb *musb) | |||
| 411 | __raw_writel(phy_ctrl, USB_PHY_CTRL); | 413 | __raw_writel(phy_ctrl, USB_PHY_CTRL); |
| 412 | } | 414 | } |
| 413 | 415 | ||
| 416 | /* On dm355, the default-A state machine needs DRVVBUS control. | ||
| 417 | * If we won't be a host, there's no need to turn it on. | ||
| 418 | */ | ||
| 419 | if (cpu_is_davinci_dm355()) { | ||
| 420 | u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); | ||
| 421 | |||
| 422 | if (is_host_enabled(musb)) { | ||
| 423 | deepsleep &= ~DRVVBUS_OVERRIDE; | ||
| 424 | } else { | ||
| 425 | deepsleep &= ~DRVVBUS_FORCE; | ||
| 426 | deepsleep |= DRVVBUS_OVERRIDE; | ||
| 427 | } | ||
| 428 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | ||
| 429 | } | ||
| 430 | |||
| 414 | /* reset the controller */ | 431 | /* reset the controller */ |
| 415 | musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); | 432 | musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); |
| 416 | 433 | ||
| @@ -437,6 +454,15 @@ int musb_platform_exit(struct musb *musb) | |||
| 437 | if (is_host_enabled(musb)) | 454 | if (is_host_enabled(musb)) |
| 438 | del_timer_sync(&otg_workaround); | 455 | del_timer_sync(&otg_workaround); |
| 439 | 456 | ||
| 457 | /* force VBUS off */ | ||
| 458 | if (cpu_is_davinci_dm355()) { | ||
| 459 | u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); | ||
| 460 | |||
| 461 | deepsleep &= ~DRVVBUS_FORCE; | ||
| 462 | deepsleep |= DRVVBUS_OVERRIDE; | ||
| 463 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | ||
| 464 | } | ||
| 465 | |||
| 440 | davinci_source_power(musb, 0 /*off*/, 1); | 466 | davinci_source_power(musb, 0 /*off*/, 1); |
| 441 | 467 | ||
| 442 | /* delay, to avoid problems with module reload */ | 468 | /* delay, to avoid problems with module reload */ |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index f3772ca3b2cf..381d648a36b8 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
| 39 | #include <linux/list.h> | 39 | #include <linux/list.h> |
| 40 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
| 41 | #include <linux/smp_lock.h> | ||
| 42 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
| 43 | #include <linux/timer.h> | 42 | #include <linux/timer.h> |
| 44 | #include <linux/clk.h> | 43 | #include <linux/clk.h> |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 94a2a350a414..cf94511485f2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
| @@ -373,7 +373,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, | |||
| 373 | musb_save_toggle(qh, is_in, urb); | 373 | musb_save_toggle(qh, is_in, urb); |
| 374 | break; | 374 | break; |
| 375 | case USB_ENDPOINT_XFER_ISOC: | 375 | case USB_ENDPOINT_XFER_ISOC: |
| 376 | if (urb->error_count) | 376 | if (status == 0 && urb->error_count) |
| 377 | status = -EXDEV; | 377 | status = -EXDEV; |
| 378 | break; | 378 | break; |
| 379 | } | 379 | } |
| @@ -2235,13 +2235,30 @@ static void musb_h_stop(struct usb_hcd *hcd) | |||
| 2235 | static int musb_bus_suspend(struct usb_hcd *hcd) | 2235 | static int musb_bus_suspend(struct usb_hcd *hcd) |
| 2236 | { | 2236 | { |
| 2237 | struct musb *musb = hcd_to_musb(hcd); | 2237 | struct musb *musb = hcd_to_musb(hcd); |
| 2238 | u8 devctl; | ||
| 2238 | 2239 | ||
| 2239 | if (musb->xceiv->state == OTG_STATE_A_SUSPEND) | 2240 | if (!is_host_active(musb)) |
| 2240 | return 0; | 2241 | return 0; |
| 2241 | 2242 | ||
| 2242 | if (is_host_active(musb) && musb->is_active) { | 2243 | switch (musb->xceiv->state) { |
| 2243 | WARNING("trying to suspend as %s is_active=%i\n", | 2244 | case OTG_STATE_A_SUSPEND: |
| 2244 | otg_state_string(musb), musb->is_active); | 2245 | return 0; |
| 2246 | case OTG_STATE_A_WAIT_VRISE: | ||
| 2247 | /* ID could be grounded even if there's no device | ||
| 2248 | * on the other end of the cable. NOTE that the | ||
| 2249 | * A_WAIT_VRISE timers are messy with MUSB... | ||
| 2250 | */ | ||
| 2251 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
| 2252 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | ||
| 2253 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
| 2254 | break; | ||
| 2255 | default: | ||
| 2256 | break; | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | if (musb->is_active) { | ||
| 2260 | WARNING("trying to suspend as %s while active\n", | ||
| 2261 | otg_state_string(musb)); | ||
| 2245 | return -EBUSY; | 2262 | return -EBUSY; |
| 2246 | } else | 2263 | } else |
| 2247 | return 0; | 2264 | return 0; |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 69feeec1628c..aa884d072f0b 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
| @@ -59,18 +59,4 @@ config NOP_USB_XCEIV | |||
| 59 | built-in with usb ip or which are autonomous and doesn't require any | 59 | built-in with usb ip or which are autonomous and doesn't require any |
| 60 | phy programming such as ISP1x04 etc. | 60 | phy programming such as ISP1x04 etc. |
| 61 | 61 | ||
| 62 | config USB_LANGWELL_OTG | ||
| 63 | tristate "Intel Langwell USB OTG dual-role support" | ||
| 64 | depends on USB && MRST | ||
| 65 | select USB_OTG | ||
| 66 | select USB_OTG_UTILS | ||
| 67 | help | ||
| 68 | Say Y here if you want to build Intel Langwell USB OTG | ||
| 69 | transciever driver in kernel. This driver implements role | ||
| 70 | switch between EHCI host driver and Langwell USB OTG | ||
| 71 | client driver. | ||
| 72 | |||
| 73 | To compile this driver as a module, choose M here: the | ||
| 74 | module will be called langwell_otg. | ||
| 75 | |||
| 76 | endif # USB || OTG | 62 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 6d1abdd3c0ac..208167856529 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
| @@ -9,7 +9,6 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | |||
| 9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | 9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o |
| 10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
| 11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | 11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o |
| 12 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o | ||
| 13 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | 12 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o |
| 14 | 13 | ||
| 15 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG | 14 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG |
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c deleted file mode 100644 index 6f628d0e9f39..000000000000 --- a/drivers/usb/otg/langwell_otg.c +++ /dev/null | |||
| @@ -1,1915 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Intel Langwell USB OTG transceiver driver | ||
| 3 | * Copyright (C) 2008 - 2009, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along with | ||
| 15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | /* This driver helps to switch Langwell OTG controller function between host | ||
| 20 | * and peripheral. It works with EHCI driver and Langwell client controller | ||
| 21 | * driver together. | ||
| 22 | */ | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/pci.h> | ||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/device.h> | ||
| 30 | #include <linux/moduleparam.h> | ||
| 31 | #include <linux/usb/ch9.h> | ||
| 32 | #include <linux/usb/gadget.h> | ||
| 33 | #include <linux/usb.h> | ||
| 34 | #include <linux/usb/otg.h> | ||
| 35 | #include <linux/notifier.h> | ||
| 36 | #include <asm/ipc_defs.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include "../core/hcd.h" | ||
| 39 | |||
| 40 | #include <linux/usb/langwell_otg.h> | ||
| 41 | |||
| 42 | #define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" | ||
| 43 | #define DRIVER_VERSION "3.0.0.32L.0002" | ||
| 44 | |||
| 45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 46 | MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); | ||
| 47 | MODULE_VERSION(DRIVER_VERSION); | ||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | |||
| 50 | static const char driver_name[] = "langwell_otg"; | ||
| 51 | |||
| 52 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
| 53 | const struct pci_device_id *id); | ||
| 54 | static void langwell_otg_remove(struct pci_dev *pdev); | ||
| 55 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); | ||
| 56 | static int langwell_otg_resume(struct pci_dev *pdev); | ||
| 57 | |||
| 58 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
| 59 | struct usb_bus *host); | ||
| 60 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
| 61 | struct usb_gadget *gadget); | ||
| 62 | static int langwell_otg_start_srp(struct otg_transceiver *otg); | ||
| 63 | |||
| 64 | static const struct pci_device_id pci_ids[] = {{ | ||
| 65 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | ||
| 66 | .class_mask = ~0, | ||
| 67 | .vendor = 0x8086, | ||
| 68 | .device = 0x0811, | ||
| 69 | .subvendor = PCI_ANY_ID, | ||
| 70 | .subdevice = PCI_ANY_ID, | ||
| 71 | }, { /* end: all zeroes */ } | ||
| 72 | }; | ||
| 73 | |||
| 74 | static struct pci_driver otg_pci_driver = { | ||
| 75 | .name = (char *) driver_name, | ||
| 76 | .id_table = pci_ids, | ||
| 77 | |||
| 78 | .probe = langwell_otg_probe, | ||
| 79 | .remove = langwell_otg_remove, | ||
| 80 | |||
| 81 | .suspend = langwell_otg_suspend, | ||
| 82 | .resume = langwell_otg_resume, | ||
| 83 | }; | ||
| 84 | |||
| 85 | static const char *state_string(enum usb_otg_state state) | ||
| 86 | { | ||
| 87 | switch (state) { | ||
| 88 | case OTG_STATE_A_IDLE: | ||
| 89 | return "a_idle"; | ||
| 90 | case OTG_STATE_A_WAIT_VRISE: | ||
| 91 | return "a_wait_vrise"; | ||
| 92 | case OTG_STATE_A_WAIT_BCON: | ||
| 93 | return "a_wait_bcon"; | ||
| 94 | case OTG_STATE_A_HOST: | ||
| 95 | return "a_host"; | ||
| 96 | case OTG_STATE_A_SUSPEND: | ||
| 97 | return "a_suspend"; | ||
| 98 | case OTG_STATE_A_PERIPHERAL: | ||
| 99 | return "a_peripheral"; | ||
| 100 | case OTG_STATE_A_WAIT_VFALL: | ||
| 101 | return "a_wait_vfall"; | ||
| 102 | case OTG_STATE_A_VBUS_ERR: | ||
| 103 | return "a_vbus_err"; | ||
| 104 | case OTG_STATE_B_IDLE: | ||
| 105 | return "b_idle"; | ||
| 106 | case OTG_STATE_B_SRP_INIT: | ||
| 107 | return "b_srp_init"; | ||
| 108 | case OTG_STATE_B_PERIPHERAL: | ||
| 109 | return "b_peripheral"; | ||
| 110 | case OTG_STATE_B_WAIT_ACON: | ||
| 111 | return "b_wait_acon"; | ||
| 112 | case OTG_STATE_B_HOST: | ||
| 113 | return "b_host"; | ||
| 114 | default: | ||
| 115 | return "UNDEFINED"; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | /* HSM timers */ | ||
| 120 | static inline struct langwell_otg_timer *otg_timer_initializer | ||
| 121 | (void (*function)(unsigned long), unsigned long expires, unsigned long data) | ||
| 122 | { | ||
| 123 | struct langwell_otg_timer *timer; | ||
| 124 | timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); | ||
| 125 | timer->function = function; | ||
| 126 | timer->expires = expires; | ||
| 127 | timer->data = data; | ||
| 128 | return timer; | ||
| 129 | } | ||
| 130 | |||
| 131 | static struct langwell_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, | ||
| 132 | *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_res_tmr, | ||
| 133 | *b_bus_suspend_tmr; | ||
| 134 | |||
| 135 | static struct list_head active_timers; | ||
| 136 | |||
| 137 | static struct langwell_otg *the_transceiver; | ||
| 138 | |||
| 139 | /* host/client notify transceiver when event affects HNP state */ | ||
| 140 | void langwell_update_transceiver() | ||
| 141 | { | ||
| 142 | otg_dbg("transceiver driver is notified\n"); | ||
| 143 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
| 144 | } | ||
| 145 | EXPORT_SYMBOL(langwell_update_transceiver); | ||
| 146 | |||
| 147 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
| 148 | struct usb_bus *host) | ||
| 149 | { | ||
| 150 | otg->host = host; | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
| 156 | struct usb_gadget *gadget) | ||
| 157 | { | ||
| 158 | otg->gadget = gadget; | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int langwell_otg_set_power(struct otg_transceiver *otg, | ||
| 164 | unsigned mA) | ||
| 165 | { | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* A-device drives vbus, controlled through PMIC CHRGCNTL register*/ | ||
| 170 | static void langwell_otg_drv_vbus(int on) | ||
| 171 | { | ||
| 172 | struct ipc_pmic_reg_data pmic_data = {0}; | ||
| 173 | struct ipc_pmic_reg_data battery_data; | ||
| 174 | |||
| 175 | /* Check if battery is attached or not */ | ||
| 176 | battery_data.pmic_reg_data[0].register_address = 0xd2; | ||
| 177 | battery_data.ioc = 0; | ||
| 178 | battery_data.num_entries = 1; | ||
| 179 | if (ipc_pmic_register_read(&battery_data)) { | ||
| 180 | otg_dbg("Failed to read PMIC register 0xd2.\n"); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | if ((battery_data.pmic_reg_data[0].value & 0x20) == 0) { | ||
| 185 | otg_dbg("no battery attached\n"); | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | |||
| 189 | /* Workaround for battery attachment issue */ | ||
| 190 | if (battery_data.pmic_reg_data[0].value == 0x34) { | ||
| 191 | otg_dbg("battery \n"); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | otg_dbg("battery attached\n"); | ||
| 196 | |||
| 197 | pmic_data.ioc = 0; | ||
| 198 | pmic_data.pmic_reg_data[0].register_address = 0xD4; | ||
| 199 | pmic_data.num_entries = 1; | ||
| 200 | if (on) | ||
| 201 | pmic_data.pmic_reg_data[0].value = 0x20; | ||
| 202 | else | ||
| 203 | pmic_data.pmic_reg_data[0].value = 0xc0; | ||
| 204 | |||
| 205 | if (ipc_pmic_register_write(&pmic_data, TRUE)) | ||
| 206 | otg_dbg("Failed to write PMIC.\n"); | ||
| 207 | |||
| 208 | } | ||
| 209 | |||
| 210 | /* charge vbus or discharge vbus through a resistor to ground */ | ||
| 211 | static void langwell_otg_chrg_vbus(int on) | ||
| 212 | { | ||
| 213 | |||
| 214 | u32 val; | ||
| 215 | |||
| 216 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 217 | |||
| 218 | if (on) | ||
| 219 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, | ||
| 220 | the_transceiver->regs + CI_OTGSC); | ||
| 221 | else | ||
| 222 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, | ||
| 223 | the_transceiver->regs + CI_OTGSC); | ||
| 224 | |||
| 225 | } | ||
| 226 | |||
| 227 | /* Start SRP */ | ||
| 228 | static int langwell_otg_start_srp(struct otg_transceiver *otg) | ||
| 229 | { | ||
| 230 | u32 val; | ||
| 231 | |||
| 232 | otg_dbg("Start SRP ->\n"); | ||
| 233 | |||
| 234 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 235 | |||
| 236 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, | ||
| 237 | the_transceiver->regs + CI_OTGSC); | ||
| 238 | |||
| 239 | /* Check if the data plus is finished or not */ | ||
| 240 | msleep(8); | ||
| 241 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 242 | if (val & (OTGSC_HADP | OTGSC_DP)) | ||
| 243 | otg_dbg("DataLine SRP Error\n"); | ||
| 244 | |||
| 245 | /* FIXME: VBus SRP */ | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | /* stop SOF via bus_suspend */ | ||
| 252 | static void langwell_otg_loc_sof(int on) | ||
| 253 | { | ||
| 254 | struct usb_hcd *hcd; | ||
| 255 | int err; | ||
| 256 | |||
| 257 | otg_dbg("loc_sof -> %d\n", on); | ||
| 258 | |||
| 259 | hcd = bus_to_hcd(the_transceiver->otg.host); | ||
| 260 | if (on) | ||
| 261 | err = hcd->driver->bus_resume(hcd); | ||
| 262 | else | ||
| 263 | err = hcd->driver->bus_suspend(hcd); | ||
| 264 | |||
| 265 | if (err) | ||
| 266 | otg_dbg("Failed to resume/suspend bus - %d\n", err); | ||
| 267 | } | ||
| 268 | |||
| 269 | static void langwell_otg_phy_low_power(int on) | ||
| 270 | { | ||
| 271 | u32 val; | ||
| 272 | |||
| 273 | otg_dbg("phy low power mode-> %d\n", on); | ||
| 274 | |||
| 275 | val = readl(the_transceiver->regs + CI_HOSTPC1); | ||
| 276 | if (on) | ||
| 277 | writel(val | HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1); | ||
| 278 | else | ||
| 279 | writel(val & ~HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1); | ||
| 280 | } | ||
| 281 | |||
| 282 | /* Enable/Disable OTG interrupt */ | ||
| 283 | static void langwell_otg_intr(int on) | ||
| 284 | { | ||
| 285 | u32 val; | ||
| 286 | |||
| 287 | otg_dbg("interrupt -> %d\n", on); | ||
| 288 | |||
| 289 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 290 | if (on) { | ||
| 291 | val = val | (OTGSC_INTEN_MASK | OTGSC_IDPU); | ||
| 292 | writel(val, the_transceiver->regs + CI_OTGSC); | ||
| 293 | } else { | ||
| 294 | val = val & ~(OTGSC_INTEN_MASK | OTGSC_IDPU); | ||
| 295 | writel(val, the_transceiver->regs + CI_OTGSC); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | /* set HAAR: Hardware Assist Auto-Reset */ | ||
| 300 | static void langwell_otg_HAAR(int on) | ||
| 301 | { | ||
| 302 | u32 val; | ||
| 303 | |||
| 304 | otg_dbg("HAAR -> %d\n", on); | ||
| 305 | |||
| 306 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 307 | if (on) | ||
| 308 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, | ||
| 309 | the_transceiver->regs + CI_OTGSC); | ||
| 310 | else | ||
| 311 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, | ||
| 312 | the_transceiver->regs + CI_OTGSC); | ||
| 313 | } | ||
| 314 | |||
| 315 | /* set HABA: Hardware Assist B-Disconnect to A-Connect */ | ||
| 316 | static void langwell_otg_HABA(int on) | ||
| 317 | { | ||
| 318 | u32 val; | ||
| 319 | |||
| 320 | otg_dbg("HABA -> %d\n", on); | ||
| 321 | |||
| 322 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
| 323 | if (on) | ||
| 324 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, | ||
| 325 | the_transceiver->regs + CI_OTGSC); | ||
| 326 | else | ||
| 327 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, | ||
| 328 | the_transceiver->regs + CI_OTGSC); | ||
| 329 | } | ||
| 330 | |||
| 331 | static int langwell_otg_check_se0_srp(int on) | ||
| 332 | { | ||
| 333 | u32 val; | ||
| 334 | |||
| 335 | int delay_time = TB_SE0_SRP * 10; /* step is 100us */ | ||
| 336 | |||
| 337 | otg_dbg("check_se0_srp -> \n"); | ||
| 338 | |||
| 339 | do { | ||
| 340 | udelay(100); | ||
| 341 | if (!delay_time--) | ||
| 342 | break; | ||
| 343 | val = readl(the_transceiver->regs + CI_PORTSC1); | ||
| 344 | val &= PORTSC_LS; | ||
| 345 | } while (!val); | ||
| 346 | |||
| 347 | otg_dbg("check_se0_srp <- \n"); | ||
| 348 | return val; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* The timeout callback function to set time out bit */ | ||
| 352 | static void set_tmout(unsigned long indicator) | ||
| 353 | { | ||
| 354 | *(int *)indicator = 1; | ||
| 355 | } | ||
| 356 | |||
| 357 | void langwell_otg_nsf_msg(unsigned long indicator) | ||
| 358 | { | ||
| 359 | switch (indicator) { | ||
| 360 | case 2: | ||
| 361 | case 4: | ||
| 362 | case 6: | ||
| 363 | case 7: | ||
| 364 | printk(KERN_ERR "OTG:NSF-%lu - deivce not responding\n", | ||
| 365 | indicator); | ||
| 366 | break; | ||
| 367 | case 3: | ||
| 368 | printk(KERN_ERR "OTG:NSF-%lu - deivce not supported\n", | ||
| 369 | indicator); | ||
| 370 | break; | ||
| 371 | default: | ||
| 372 | printk(KERN_ERR "Do not have this kind of NSF\n"); | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Initialize timers */ | ||
| 378 | static void langwell_otg_init_timers(struct otg_hsm *hsm) | ||
| 379 | { | ||
| 380 | /* HSM used timers */ | ||
| 381 | a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, | ||
| 382 | (unsigned long)&hsm->a_wait_vrise_tmout); | ||
| 383 | a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, | ||
| 384 | (unsigned long)&hsm->a_wait_bcon_tmout); | ||
| 385 | a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, | ||
| 386 | (unsigned long)&hsm->a_aidl_bdis_tmout); | ||
| 387 | b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, | ||
| 388 | (unsigned long)&hsm->b_ase0_brst_tmout); | ||
| 389 | b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, | ||
| 390 | (unsigned long)&hsm->b_se0_srp); | ||
| 391 | b_srp_res_tmr = otg_timer_initializer(&set_tmout, TB_SRP_RES, | ||
| 392 | (unsigned long)&hsm->b_srp_res_tmout); | ||
| 393 | b_bus_suspend_tmr = otg_timer_initializer(&set_tmout, TB_BUS_SUSPEND, | ||
| 394 | (unsigned long)&hsm->b_bus_suspend_tmout); | ||
| 395 | } | ||
| 396 | |||
| 397 | /* Free timers */ | ||
| 398 | static void langwell_otg_free_timers(void) | ||
| 399 | { | ||
| 400 | kfree(a_wait_vrise_tmr); | ||
| 401 | kfree(a_wait_bcon_tmr); | ||
| 402 | kfree(a_aidl_bdis_tmr); | ||
| 403 | kfree(b_ase0_brst_tmr); | ||
| 404 | kfree(b_se0_srp_tmr); | ||
| 405 | kfree(b_srp_res_tmr); | ||
| 406 | kfree(b_bus_suspend_tmr); | ||
| 407 | } | ||
| 408 | |||
| 409 | /* Add timer to timer list */ | ||
| 410 | static void langwell_otg_add_timer(void *gtimer) | ||
| 411 | { | ||
| 412 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
| 413 | struct langwell_otg_timer *tmp_timer; | ||
| 414 | u32 val32; | ||
| 415 | |||
| 416 | /* Check if the timer is already in the active list, | ||
| 417 | * if so update timer count | ||
| 418 | */ | ||
| 419 | list_for_each_entry(tmp_timer, &active_timers, list) | ||
| 420 | if (tmp_timer == timer) { | ||
| 421 | timer->count = timer->expires; | ||
| 422 | return; | ||
| 423 | } | ||
| 424 | timer->count = timer->expires; | ||
| 425 | |||
| 426 | if (list_empty(&active_timers)) { | ||
| 427 | val32 = readl(the_transceiver->regs + CI_OTGSC); | ||
| 428 | writel(val32 | OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); | ||
| 429 | } | ||
| 430 | |||
| 431 | list_add_tail(&timer->list, &active_timers); | ||
| 432 | } | ||
| 433 | |||
| 434 | /* Remove timer from the timer list; clear timeout status */ | ||
| 435 | static void langwell_otg_del_timer(void *gtimer) | ||
| 436 | { | ||
| 437 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
| 438 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
| 439 | u32 val32; | ||
| 440 | |||
| 441 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) | ||
| 442 | if (tmp_timer == timer) | ||
| 443 | list_del(&timer->list); | ||
| 444 | |||
| 445 | if (list_empty(&active_timers)) { | ||
| 446 | val32 = readl(the_transceiver->regs + CI_OTGSC); | ||
| 447 | writel(val32 & ~OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | /* Reduce timer count by 1, and find timeout conditions.*/ | ||
| 452 | static int langwell_otg_tick_timer(u32 *int_sts) | ||
| 453 | { | ||
| 454 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
| 455 | int expired = 0; | ||
| 456 | |||
| 457 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { | ||
| 458 | tmp_timer->count--; | ||
| 459 | /* check if timer expires */ | ||
| 460 | if (!tmp_timer->count) { | ||
| 461 | list_del(&tmp_timer->list); | ||
| 462 | tmp_timer->function(tmp_timer->data); | ||
| 463 | expired = 1; | ||
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 | if (list_empty(&active_timers)) { | ||
| 468 | otg_dbg("tick timer: disable 1ms int\n"); | ||
| 469 | *int_sts = *int_sts & ~OTGSC_1MSE; | ||
| 470 | } | ||
| 471 | return expired; | ||
| 472 | } | ||
| 473 | |||
| 474 | static void reset_otg(void) | ||
| 475 | { | ||
| 476 | u32 val; | ||
| 477 | int delay_time = 1000; | ||
| 478 | |||
| 479 | otg_dbg("reseting OTG controller ...\n"); | ||
| 480 | val = readl(the_transceiver->regs + CI_USBCMD); | ||
| 481 | writel(val | USBCMD_RST, the_transceiver->regs + CI_USBCMD); | ||
| 482 | do { | ||
| 483 | udelay(100); | ||
| 484 | if (!delay_time--) | ||
| 485 | otg_dbg("reset timeout\n"); | ||
| 486 | val = readl(the_transceiver->regs + CI_USBCMD); | ||
| 487 | val &= USBCMD_RST; | ||
| 488 | } while (val != 0); | ||
| 489 | otg_dbg("reset done.\n"); | ||
| 490 | } | ||
| 491 | |||
| 492 | static void set_host_mode(void) | ||
| 493 | { | ||
| 494 | u32 val; | ||
| 495 | |||
| 496 | reset_otg(); | ||
| 497 | val = readl(the_transceiver->regs + CI_USBMODE); | ||
| 498 | val = (val & (~USBMODE_CM)) | USBMODE_HOST; | ||
| 499 | writel(val, the_transceiver->regs + CI_USBMODE); | ||
| 500 | } | ||
| 501 | |||
| 502 | static void set_client_mode(void) | ||
| 503 | { | ||
| 504 | u32 val; | ||
| 505 | |||
| 506 | reset_otg(); | ||
| 507 | val = readl(the_transceiver->regs + CI_USBMODE); | ||
| 508 | val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; | ||
| 509 | writel(val, the_transceiver->regs + CI_USBMODE); | ||
| 510 | } | ||
| 511 | |||
| 512 | static void init_hsm(void) | ||
| 513 | { | ||
| 514 | struct langwell_otg *langwell = the_transceiver; | ||
| 515 | u32 val32; | ||
| 516 | |||
| 517 | /* read OTGSC after reset */ | ||
| 518 | val32 = readl(langwell->regs + CI_OTGSC); | ||
| 519 | otg_dbg("%s: OTGSC init value = 0x%x\n", __func__, val32); | ||
| 520 | |||
| 521 | /* set init state */ | ||
| 522 | if (val32 & OTGSC_ID) { | ||
| 523 | langwell->hsm.id = 1; | ||
| 524 | langwell->otg.default_a = 0; | ||
| 525 | set_client_mode(); | ||
| 526 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 527 | langwell_otg_drv_vbus(0); | ||
| 528 | } else { | ||
| 529 | langwell->hsm.id = 0; | ||
| 530 | langwell->otg.default_a = 1; | ||
| 531 | set_host_mode(); | ||
| 532 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 533 | } | ||
| 534 | |||
| 535 | /* set session indicator */ | ||
| 536 | if (val32 & OTGSC_BSE) | ||
| 537 | langwell->hsm.b_sess_end = 1; | ||
| 538 | if (val32 & OTGSC_BSV) | ||
| 539 | langwell->hsm.b_sess_vld = 1; | ||
| 540 | if (val32 & OTGSC_ASV) | ||
| 541 | langwell->hsm.a_sess_vld = 1; | ||
| 542 | if (val32 & OTGSC_AVV) | ||
| 543 | langwell->hsm.a_vbus_vld = 1; | ||
| 544 | |||
| 545 | /* defautly power the bus */ | ||
| 546 | langwell->hsm.a_bus_req = 1; | ||
| 547 | langwell->hsm.a_bus_drop = 0; | ||
| 548 | /* defautly don't request bus as B device */ | ||
| 549 | langwell->hsm.b_bus_req = 0; | ||
| 550 | /* no system error */ | ||
| 551 | langwell->hsm.a_clr_err = 0; | ||
| 552 | } | ||
| 553 | |||
| 554 | static irqreturn_t otg_dummy_irq(int irq, void *_dev) | ||
| 555 | { | ||
| 556 | void __iomem *reg_base = _dev; | ||
| 557 | u32 val; | ||
| 558 | u32 int_mask = 0; | ||
| 559 | |||
| 560 | val = readl(reg_base + CI_USBMODE); | ||
| 561 | if ((val & USBMODE_CM) != USBMODE_DEVICE) | ||
| 562 | return IRQ_NONE; | ||
| 563 | |||
| 564 | val = readl(reg_base + CI_USBSTS); | ||
| 565 | int_mask = val & INTR_DUMMY_MASK; | ||
| 566 | |||
| 567 | if (int_mask == 0) | ||
| 568 | return IRQ_NONE; | ||
| 569 | |||
| 570 | /* clear hsm.b_conn here since host driver can't detect it | ||
| 571 | * otg_dummy_irq called means B-disconnect happened. | ||
| 572 | */ | ||
| 573 | if (the_transceiver->hsm.b_conn) { | ||
| 574 | the_transceiver->hsm.b_conn = 0; | ||
| 575 | if (spin_trylock(&the_transceiver->wq_lock)) { | ||
| 576 | queue_work(the_transceiver->qwork, | ||
| 577 | &the_transceiver->work); | ||
| 578 | spin_unlock(&the_transceiver->wq_lock); | ||
| 579 | } | ||
| 580 | } | ||
| 581 | /* Clear interrupts */ | ||
| 582 | writel(int_mask, reg_base + CI_USBSTS); | ||
| 583 | return IRQ_HANDLED; | ||
| 584 | } | ||
| 585 | |||
| 586 | static irqreturn_t otg_irq(int irq, void *_dev) | ||
| 587 | { | ||
| 588 | struct langwell_otg *langwell = _dev; | ||
| 589 | u32 int_sts, int_en; | ||
| 590 | u32 int_mask = 0; | ||
| 591 | int flag = 0; | ||
| 592 | |||
| 593 | int_sts = readl(langwell->regs + CI_OTGSC); | ||
| 594 | int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; | ||
| 595 | int_mask = int_sts & int_en; | ||
| 596 | if (int_mask == 0) | ||
| 597 | return IRQ_NONE; | ||
| 598 | |||
| 599 | if (int_mask & OTGSC_IDIS) { | ||
| 600 | otg_dbg("%s: id change int\n", __func__); | ||
| 601 | langwell->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; | ||
| 602 | flag = 1; | ||
| 603 | } | ||
| 604 | if (int_mask & OTGSC_DPIS) { | ||
| 605 | otg_dbg("%s: data pulse int\n", __func__); | ||
| 606 | langwell->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; | ||
| 607 | flag = 1; | ||
| 608 | } | ||
| 609 | if (int_mask & OTGSC_BSEIS) { | ||
| 610 | otg_dbg("%s: b session end int\n", __func__); | ||
| 611 | langwell->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; | ||
| 612 | flag = 1; | ||
| 613 | } | ||
| 614 | if (int_mask & OTGSC_BSVIS) { | ||
| 615 | otg_dbg("%s: b session valid int\n", __func__); | ||
| 616 | langwell->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; | ||
| 617 | flag = 1; | ||
| 618 | } | ||
| 619 | if (int_mask & OTGSC_ASVIS) { | ||
| 620 | otg_dbg("%s: a session valid int\n", __func__); | ||
| 621 | langwell->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; | ||
| 622 | flag = 1; | ||
| 623 | } | ||
| 624 | if (int_mask & OTGSC_AVVIS) { | ||
| 625 | otg_dbg("%s: a vbus valid int\n", __func__); | ||
| 626 | langwell->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; | ||
| 627 | flag = 1; | ||
| 628 | } | ||
| 629 | |||
| 630 | if (int_mask & OTGSC_1MSS) { | ||
| 631 | /* need to schedule otg_work if any timer is expired */ | ||
| 632 | if (langwell_otg_tick_timer(&int_sts)) | ||
| 633 | flag = 1; | ||
| 634 | } | ||
| 635 | |||
| 636 | writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, | ||
| 637 | langwell->regs + CI_OTGSC); | ||
| 638 | if (flag) | ||
| 639 | queue_work(langwell->qwork, &langwell->work); | ||
| 640 | |||
| 641 | return IRQ_HANDLED; | ||
| 642 | } | ||
| 643 | |||
| 644 | static void langwell_otg_work(struct work_struct *work) | ||
| 645 | { | ||
| 646 | struct langwell_otg *langwell = container_of(work, | ||
| 647 | struct langwell_otg, work); | ||
| 648 | int retval; | ||
| 649 | |||
| 650 | otg_dbg("%s: old state = %s\n", __func__, | ||
| 651 | state_string(langwell->otg.state)); | ||
| 652 | |||
| 653 | switch (langwell->otg.state) { | ||
| 654 | case OTG_STATE_UNDEFINED: | ||
| 655 | case OTG_STATE_B_IDLE: | ||
| 656 | if (!langwell->hsm.id) { | ||
| 657 | langwell_otg_del_timer(b_srp_res_tmr); | ||
| 658 | langwell->otg.default_a = 1; | ||
| 659 | langwell->hsm.a_srp_det = 0; | ||
| 660 | |||
| 661 | langwell_otg_chrg_vbus(0); | ||
| 662 | langwell_otg_drv_vbus(0); | ||
| 663 | |||
| 664 | set_host_mode(); | ||
| 665 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 666 | queue_work(langwell->qwork, &langwell->work); | ||
| 667 | } else if (langwell->hsm.b_srp_res_tmout) { | ||
| 668 | langwell->hsm.b_srp_res_tmout = 0; | ||
| 669 | langwell->hsm.b_bus_req = 0; | ||
| 670 | langwell_otg_nsf_msg(6); | ||
| 671 | } else if (langwell->hsm.b_sess_vld) { | ||
| 672 | langwell_otg_del_timer(b_srp_res_tmr); | ||
| 673 | langwell->hsm.b_sess_end = 0; | ||
| 674 | langwell->hsm.a_bus_suspend = 0; | ||
| 675 | |||
| 676 | langwell_otg_chrg_vbus(0); | ||
| 677 | if (langwell->client_ops) { | ||
| 678 | langwell->client_ops->resume(langwell->pdev); | ||
| 679 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 680 | } else | ||
| 681 | otg_dbg("client driver not loaded.\n"); | ||
| 682 | |||
| 683 | } else if (langwell->hsm.b_bus_req && | ||
| 684 | (langwell->hsm.b_sess_end)) { | ||
| 685 | /* workaround for b_se0_srp detection */ | ||
| 686 | retval = langwell_otg_check_se0_srp(0); | ||
| 687 | if (retval) { | ||
| 688 | langwell->hsm.b_bus_req = 0; | ||
| 689 | otg_dbg("LS is not SE0, try again later\n"); | ||
| 690 | } else { | ||
| 691 | /* Start SRP */ | ||
| 692 | langwell_otg_start_srp(&langwell->otg); | ||
| 693 | langwell_otg_add_timer(b_srp_res_tmr); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | break; | ||
| 697 | case OTG_STATE_B_SRP_INIT: | ||
| 698 | if (!langwell->hsm.id) { | ||
| 699 | langwell->otg.default_a = 1; | ||
| 700 | langwell->hsm.a_srp_det = 0; | ||
| 701 | |||
| 702 | langwell_otg_drv_vbus(0); | ||
| 703 | langwell_otg_chrg_vbus(0); | ||
| 704 | |||
| 705 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 706 | queue_work(langwell->qwork, &langwell->work); | ||
| 707 | } else if (langwell->hsm.b_sess_vld) { | ||
| 708 | langwell_otg_chrg_vbus(0); | ||
| 709 | if (langwell->client_ops) { | ||
| 710 | langwell->client_ops->resume(langwell->pdev); | ||
| 711 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 712 | } else | ||
| 713 | otg_dbg("client driver not loaded.\n"); | ||
| 714 | } | ||
| 715 | break; | ||
| 716 | case OTG_STATE_B_PERIPHERAL: | ||
| 717 | if (!langwell->hsm.id) { | ||
| 718 | langwell->otg.default_a = 1; | ||
| 719 | langwell->hsm.a_srp_det = 0; | ||
| 720 | |||
| 721 | langwell_otg_drv_vbus(0); | ||
| 722 | langwell_otg_chrg_vbus(0); | ||
| 723 | set_host_mode(); | ||
| 724 | |||
| 725 | if (langwell->client_ops) { | ||
| 726 | langwell->client_ops->suspend(langwell->pdev, | ||
| 727 | PMSG_FREEZE); | ||
| 728 | } else | ||
| 729 | otg_dbg("client driver has been removed.\n"); | ||
| 730 | |||
| 731 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 732 | queue_work(langwell->qwork, &langwell->work); | ||
| 733 | } else if (!langwell->hsm.b_sess_vld) { | ||
| 734 | langwell->hsm.b_hnp_enable = 0; | ||
| 735 | |||
| 736 | if (langwell->client_ops) { | ||
| 737 | langwell->client_ops->suspend(langwell->pdev, | ||
| 738 | PMSG_FREEZE); | ||
| 739 | } else | ||
| 740 | otg_dbg("client driver has been removed.\n"); | ||
| 741 | |||
| 742 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 743 | } else if (langwell->hsm.b_bus_req && langwell->hsm.b_hnp_enable | ||
| 744 | && langwell->hsm.a_bus_suspend) { | ||
| 745 | |||
| 746 | if (langwell->client_ops) { | ||
| 747 | langwell->client_ops->suspend(langwell->pdev, | ||
| 748 | PMSG_FREEZE); | ||
| 749 | } else | ||
| 750 | otg_dbg("client driver has been removed.\n"); | ||
| 751 | |||
| 752 | langwell_otg_HAAR(1); | ||
| 753 | langwell->hsm.a_conn = 0; | ||
| 754 | |||
| 755 | if (langwell->host_ops) { | ||
| 756 | langwell->host_ops->probe(langwell->pdev, | ||
| 757 | langwell->host_ops->id_table); | ||
| 758 | langwell->otg.state = OTG_STATE_B_WAIT_ACON; | ||
| 759 | } else | ||
| 760 | otg_dbg("host driver not loaded.\n"); | ||
| 761 | |||
| 762 | langwell->hsm.a_bus_resume = 0; | ||
| 763 | langwell->hsm.b_ase0_brst_tmout = 0; | ||
| 764 | langwell_otg_add_timer(b_ase0_brst_tmr); | ||
| 765 | } | ||
| 766 | break; | ||
| 767 | |||
| 768 | case OTG_STATE_B_WAIT_ACON: | ||
| 769 | if (!langwell->hsm.id) { | ||
| 770 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
| 771 | langwell->otg.default_a = 1; | ||
| 772 | langwell->hsm.a_srp_det = 0; | ||
| 773 | |||
| 774 | langwell_otg_drv_vbus(0); | ||
| 775 | langwell_otg_chrg_vbus(0); | ||
| 776 | set_host_mode(); | ||
| 777 | |||
| 778 | langwell_otg_HAAR(0); | ||
| 779 | if (langwell->host_ops) | ||
| 780 | langwell->host_ops->remove(langwell->pdev); | ||
| 781 | else | ||
| 782 | otg_dbg("host driver has been removed.\n"); | ||
| 783 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 784 | queue_work(langwell->qwork, &langwell->work); | ||
| 785 | } else if (!langwell->hsm.b_sess_vld) { | ||
| 786 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
| 787 | langwell->hsm.b_hnp_enable = 0; | ||
| 788 | langwell->hsm.b_bus_req = 0; | ||
| 789 | langwell_otg_chrg_vbus(0); | ||
| 790 | langwell_otg_HAAR(0); | ||
| 791 | |||
| 792 | if (langwell->host_ops) | ||
| 793 | langwell->host_ops->remove(langwell->pdev); | ||
| 794 | else | ||
| 795 | otg_dbg("host driver has been removed.\n"); | ||
| 796 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 797 | } else if (langwell->hsm.a_conn) { | ||
| 798 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
| 799 | langwell_otg_HAAR(0); | ||
| 800 | langwell->otg.state = OTG_STATE_B_HOST; | ||
| 801 | queue_work(langwell->qwork, &langwell->work); | ||
| 802 | } else if (langwell->hsm.a_bus_resume || | ||
| 803 | langwell->hsm.b_ase0_brst_tmout) { | ||
| 804 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
| 805 | langwell_otg_HAAR(0); | ||
| 806 | langwell_otg_nsf_msg(7); | ||
| 807 | |||
| 808 | if (langwell->host_ops) | ||
| 809 | langwell->host_ops->remove(langwell->pdev); | ||
| 810 | else | ||
| 811 | otg_dbg("host driver has been removed.\n"); | ||
| 812 | |||
| 813 | langwell->hsm.a_bus_suspend = 0; | ||
| 814 | langwell->hsm.b_bus_req = 0; | ||
| 815 | |||
| 816 | if (langwell->client_ops) | ||
| 817 | langwell->client_ops->resume(langwell->pdev); | ||
| 818 | else | ||
| 819 | otg_dbg("client driver not loaded.\n"); | ||
| 820 | |||
| 821 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 822 | } | ||
| 823 | break; | ||
| 824 | |||
| 825 | case OTG_STATE_B_HOST: | ||
| 826 | if (!langwell->hsm.id) { | ||
| 827 | langwell->otg.default_a = 1; | ||
| 828 | langwell->hsm.a_srp_det = 0; | ||
| 829 | |||
| 830 | langwell_otg_drv_vbus(0); | ||
| 831 | langwell_otg_chrg_vbus(0); | ||
| 832 | set_host_mode(); | ||
| 833 | if (langwell->host_ops) | ||
| 834 | langwell->host_ops->remove(langwell->pdev); | ||
| 835 | else | ||
| 836 | otg_dbg("host driver has been removed.\n"); | ||
| 837 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 838 | queue_work(langwell->qwork, &langwell->work); | ||
| 839 | } else if (!langwell->hsm.b_sess_vld) { | ||
| 840 | langwell->hsm.b_hnp_enable = 0; | ||
| 841 | langwell->hsm.b_bus_req = 0; | ||
| 842 | langwell_otg_chrg_vbus(0); | ||
| 843 | if (langwell->host_ops) | ||
| 844 | langwell->host_ops->remove(langwell->pdev); | ||
| 845 | else | ||
| 846 | otg_dbg("host driver has been removed.\n"); | ||
| 847 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 848 | } else if ((!langwell->hsm.b_bus_req) || | ||
| 849 | (!langwell->hsm.a_conn)) { | ||
| 850 | langwell->hsm.b_bus_req = 0; | ||
| 851 | langwell_otg_loc_sof(0); | ||
| 852 | if (langwell->host_ops) | ||
| 853 | langwell->host_ops->remove(langwell->pdev); | ||
| 854 | else | ||
| 855 | otg_dbg("host driver has been removed.\n"); | ||
| 856 | |||
| 857 | langwell->hsm.a_bus_suspend = 0; | ||
| 858 | |||
| 859 | if (langwell->client_ops) | ||
| 860 | langwell->client_ops->resume(langwell->pdev); | ||
| 861 | else | ||
| 862 | otg_dbg("client driver not loaded.\n"); | ||
| 863 | |||
| 864 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
| 865 | } | ||
| 866 | break; | ||
| 867 | |||
| 868 | case OTG_STATE_A_IDLE: | ||
| 869 | langwell->otg.default_a = 1; | ||
| 870 | if (langwell->hsm.id) { | ||
| 871 | langwell->otg.default_a = 0; | ||
| 872 | langwell->hsm.b_bus_req = 0; | ||
| 873 | langwell_otg_drv_vbus(0); | ||
| 874 | langwell_otg_chrg_vbus(0); | ||
| 875 | |||
| 876 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 877 | queue_work(langwell->qwork, &langwell->work); | ||
| 878 | } else if (langwell->hsm.a_sess_vld) { | ||
| 879 | langwell_otg_drv_vbus(1); | ||
| 880 | langwell->hsm.a_srp_det = 1; | ||
| 881 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
| 882 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 883 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 884 | queue_work(langwell->qwork, &langwell->work); | ||
| 885 | } else if (!langwell->hsm.a_bus_drop && | ||
| 886 | (langwell->hsm.a_srp_det || langwell->hsm.a_bus_req)) { | ||
| 887 | langwell_otg_drv_vbus(1); | ||
| 888 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
| 889 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 890 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 891 | queue_work(langwell->qwork, &langwell->work); | ||
| 892 | } | ||
| 893 | break; | ||
| 894 | case OTG_STATE_A_WAIT_VRISE: | ||
| 895 | if (langwell->hsm.id) { | ||
| 896 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 897 | langwell->hsm.b_bus_req = 0; | ||
| 898 | langwell->otg.default_a = 0; | ||
| 899 | langwell_otg_drv_vbus(0); | ||
| 900 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 901 | } else if (langwell->hsm.a_vbus_vld) { | ||
| 902 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 903 | if (langwell->host_ops) | ||
| 904 | langwell->host_ops->probe(langwell->pdev, | ||
| 905 | langwell->host_ops->id_table); | ||
| 906 | else | ||
| 907 | otg_dbg("host driver not loaded.\n"); | ||
| 908 | langwell->hsm.b_conn = 0; | ||
| 909 | langwell->hsm.a_set_b_hnp_en = 0; | ||
| 910 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
| 911 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 912 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 913 | } else if (langwell->hsm.a_wait_vrise_tmout) { | ||
| 914 | if (langwell->hsm.a_vbus_vld) { | ||
| 915 | if (langwell->host_ops) | ||
| 916 | langwell->host_ops->probe( | ||
| 917 | langwell->pdev, | ||
| 918 | langwell->host_ops->id_table); | ||
| 919 | else | ||
| 920 | otg_dbg("host driver not loaded.\n"); | ||
| 921 | langwell->hsm.b_conn = 0; | ||
| 922 | langwell->hsm.a_set_b_hnp_en = 0; | ||
| 923 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
| 924 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 925 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 926 | } else { | ||
| 927 | langwell_otg_drv_vbus(0); | ||
| 928 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 929 | } | ||
| 930 | } | ||
| 931 | break; | ||
| 932 | case OTG_STATE_A_WAIT_BCON: | ||
| 933 | if (langwell->hsm.id) { | ||
| 934 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
| 935 | |||
| 936 | langwell->otg.default_a = 0; | ||
| 937 | langwell->hsm.b_bus_req = 0; | ||
| 938 | if (langwell->host_ops) | ||
| 939 | langwell->host_ops->remove(langwell->pdev); | ||
| 940 | else | ||
| 941 | otg_dbg("host driver has been removed.\n"); | ||
| 942 | langwell_otg_drv_vbus(0); | ||
| 943 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 944 | queue_work(langwell->qwork, &langwell->work); | ||
| 945 | } else if (!langwell->hsm.a_vbus_vld) { | ||
| 946 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
| 947 | |||
| 948 | if (langwell->host_ops) | ||
| 949 | langwell->host_ops->remove(langwell->pdev); | ||
| 950 | else | ||
| 951 | otg_dbg("host driver has been removed.\n"); | ||
| 952 | langwell_otg_drv_vbus(0); | ||
| 953 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 954 | } else if (langwell->hsm.a_bus_drop || | ||
| 955 | (langwell->hsm.a_wait_bcon_tmout && | ||
| 956 | !langwell->hsm.a_bus_req)) { | ||
| 957 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
| 958 | |||
| 959 | if (langwell->host_ops) | ||
| 960 | langwell->host_ops->remove(langwell->pdev); | ||
| 961 | else | ||
| 962 | otg_dbg("host driver has been removed.\n"); | ||
| 963 | langwell_otg_drv_vbus(0); | ||
| 964 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 965 | } else if (langwell->hsm.b_conn) { | ||
| 966 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
| 967 | |||
| 968 | langwell->hsm.a_suspend_req = 0; | ||
| 969 | langwell->otg.state = OTG_STATE_A_HOST; | ||
| 970 | if (!langwell->hsm.a_bus_req && | ||
| 971 | langwell->hsm.a_set_b_hnp_en) { | ||
| 972 | /* It is not safe enough to do a fast | ||
| 973 | * transistion from A_WAIT_BCON to | ||
| 974 | * A_SUSPEND */ | ||
| 975 | msleep(10000); | ||
| 976 | if (langwell->hsm.a_bus_req) | ||
| 977 | break; | ||
| 978 | |||
| 979 | if (request_irq(langwell->pdev->irq, | ||
| 980 | otg_dummy_irq, IRQF_SHARED, | ||
| 981 | driver_name, langwell->regs) != 0) { | ||
| 982 | otg_dbg("request interrupt %d fail\n", | ||
| 983 | langwell->pdev->irq); | ||
| 984 | } | ||
| 985 | |||
| 986 | langwell_otg_HABA(1); | ||
| 987 | langwell->hsm.b_bus_resume = 0; | ||
| 988 | langwell->hsm.a_aidl_bdis_tmout = 0; | ||
| 989 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
| 990 | |||
| 991 | langwell_otg_loc_sof(0); | ||
| 992 | langwell->otg.state = OTG_STATE_A_SUSPEND; | ||
| 993 | } else if (!langwell->hsm.a_bus_req && | ||
| 994 | !langwell->hsm.a_set_b_hnp_en) { | ||
| 995 | struct pci_dev *pdev = langwell->pdev; | ||
| 996 | if (langwell->host_ops) | ||
| 997 | langwell->host_ops->remove(pdev); | ||
| 998 | else | ||
| 999 | otg_dbg("host driver removed.\n"); | ||
| 1000 | langwell_otg_drv_vbus(0); | ||
| 1001 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | break; | ||
| 1005 | case OTG_STATE_A_HOST: | ||
| 1006 | if (langwell->hsm.id) { | ||
| 1007 | langwell->otg.default_a = 0; | ||
| 1008 | langwell->hsm.b_bus_req = 0; | ||
| 1009 | if (langwell->host_ops) | ||
| 1010 | langwell->host_ops->remove(langwell->pdev); | ||
| 1011 | else | ||
| 1012 | otg_dbg("host driver has been removed.\n"); | ||
| 1013 | langwell_otg_drv_vbus(0); | ||
| 1014 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1015 | queue_work(langwell->qwork, &langwell->work); | ||
| 1016 | } else if (langwell->hsm.a_bus_drop || | ||
| 1017 | (!langwell->hsm.a_set_b_hnp_en && !langwell->hsm.a_bus_req)) { | ||
| 1018 | if (langwell->host_ops) | ||
| 1019 | langwell->host_ops->remove(langwell->pdev); | ||
| 1020 | else | ||
| 1021 | otg_dbg("host driver has been removed.\n"); | ||
| 1022 | langwell_otg_drv_vbus(0); | ||
| 1023 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1024 | } else if (!langwell->hsm.a_vbus_vld) { | ||
| 1025 | if (langwell->host_ops) | ||
| 1026 | langwell->host_ops->remove(langwell->pdev); | ||
| 1027 | else | ||
| 1028 | otg_dbg("host driver has been removed.\n"); | ||
| 1029 | langwell_otg_drv_vbus(0); | ||
| 1030 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1031 | } else if (langwell->hsm.a_set_b_hnp_en | ||
| 1032 | && !langwell->hsm.a_bus_req) { | ||
| 1033 | /* Set HABA to enable hardware assistance to signal | ||
| 1034 | * A-connect after receiver B-disconnect. Hardware | ||
| 1035 | * will then set client mode and enable URE, SLE and | ||
| 1036 | * PCE after the assistance. otg_dummy_irq is used to | ||
| 1037 | * clean these ints when client driver is not resumed. | ||
| 1038 | */ | ||
| 1039 | if (request_irq(langwell->pdev->irq, | ||
| 1040 | otg_dummy_irq, IRQF_SHARED, driver_name, | ||
| 1041 | langwell->regs) != 0) { | ||
| 1042 | otg_dbg("request interrupt %d failed\n", | ||
| 1043 | langwell->pdev->irq); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* set HABA */ | ||
| 1047 | langwell_otg_HABA(1); | ||
| 1048 | langwell->hsm.b_bus_resume = 0; | ||
| 1049 | langwell->hsm.a_aidl_bdis_tmout = 0; | ||
| 1050 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
| 1051 | langwell_otg_loc_sof(0); | ||
| 1052 | langwell->otg.state = OTG_STATE_A_SUSPEND; | ||
| 1053 | } else if (!langwell->hsm.b_conn || !langwell->hsm.a_bus_req) { | ||
| 1054 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
| 1055 | langwell->hsm.a_set_b_hnp_en = 0; | ||
| 1056 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 1057 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1058 | } | ||
| 1059 | break; | ||
| 1060 | case OTG_STATE_A_SUSPEND: | ||
| 1061 | if (langwell->hsm.id) { | ||
| 1062 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1063 | langwell_otg_HABA(0); | ||
| 1064 | free_irq(langwell->pdev->irq, langwell->regs); | ||
| 1065 | langwell->otg.default_a = 0; | ||
| 1066 | langwell->hsm.b_bus_req = 0; | ||
| 1067 | if (langwell->host_ops) | ||
| 1068 | langwell->host_ops->remove(langwell->pdev); | ||
| 1069 | else | ||
| 1070 | otg_dbg("host driver has been removed.\n"); | ||
| 1071 | langwell_otg_drv_vbus(0); | ||
| 1072 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1073 | queue_work(langwell->qwork, &langwell->work); | ||
| 1074 | } else if (langwell->hsm.a_bus_req || | ||
| 1075 | langwell->hsm.b_bus_resume) { | ||
| 1076 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1077 | langwell_otg_HABA(0); | ||
| 1078 | free_irq(langwell->pdev->irq, langwell->regs); | ||
| 1079 | langwell->hsm.a_suspend_req = 0; | ||
| 1080 | langwell_otg_loc_sof(1); | ||
| 1081 | langwell->otg.state = OTG_STATE_A_HOST; | ||
| 1082 | } else if (langwell->hsm.a_aidl_bdis_tmout || | ||
| 1083 | langwell->hsm.a_bus_drop) { | ||
| 1084 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1085 | langwell_otg_HABA(0); | ||
| 1086 | free_irq(langwell->pdev->irq, langwell->regs); | ||
| 1087 | if (langwell->host_ops) | ||
| 1088 | langwell->host_ops->remove(langwell->pdev); | ||
| 1089 | else | ||
| 1090 | otg_dbg("host driver has been removed.\n"); | ||
| 1091 | langwell_otg_drv_vbus(0); | ||
| 1092 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1093 | } else if (!langwell->hsm.b_conn && | ||
| 1094 | langwell->hsm.a_set_b_hnp_en) { | ||
| 1095 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1096 | langwell_otg_HABA(0); | ||
| 1097 | free_irq(langwell->pdev->irq, langwell->regs); | ||
| 1098 | |||
| 1099 | if (langwell->host_ops) | ||
| 1100 | langwell->host_ops->remove(langwell->pdev); | ||
| 1101 | else | ||
| 1102 | otg_dbg("host driver has been removed.\n"); | ||
| 1103 | |||
| 1104 | langwell->hsm.b_bus_suspend = 0; | ||
| 1105 | langwell->hsm.b_bus_suspend_vld = 0; | ||
| 1106 | langwell->hsm.b_bus_suspend_tmout = 0; | ||
| 1107 | |||
| 1108 | /* msleep(200); */ | ||
| 1109 | if (langwell->client_ops) | ||
| 1110 | langwell->client_ops->resume(langwell->pdev); | ||
| 1111 | else | ||
| 1112 | otg_dbg("client driver not loaded.\n"); | ||
| 1113 | |||
| 1114 | langwell_otg_add_timer(b_bus_suspend_tmr); | ||
| 1115 | langwell->otg.state = OTG_STATE_A_PERIPHERAL; | ||
| 1116 | break; | ||
| 1117 | } else if (!langwell->hsm.a_vbus_vld) { | ||
| 1118 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1119 | langwell_otg_HABA(0); | ||
| 1120 | free_irq(langwell->pdev->irq, langwell->regs); | ||
| 1121 | if (langwell->host_ops) | ||
| 1122 | langwell->host_ops->remove(langwell->pdev); | ||
| 1123 | else | ||
| 1124 | otg_dbg("host driver has been removed.\n"); | ||
| 1125 | langwell_otg_drv_vbus(0); | ||
| 1126 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1127 | } | ||
| 1128 | break; | ||
| 1129 | case OTG_STATE_A_PERIPHERAL: | ||
| 1130 | if (langwell->hsm.id) { | ||
| 1131 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
| 1132 | langwell->otg.default_a = 0; | ||
| 1133 | langwell->hsm.b_bus_req = 0; | ||
| 1134 | if (langwell->client_ops) | ||
| 1135 | langwell->client_ops->suspend(langwell->pdev, | ||
| 1136 | PMSG_FREEZE); | ||
| 1137 | else | ||
| 1138 | otg_dbg("client driver has been removed.\n"); | ||
| 1139 | langwell_otg_drv_vbus(0); | ||
| 1140 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1141 | queue_work(langwell->qwork, &langwell->work); | ||
| 1142 | } else if (!langwell->hsm.a_vbus_vld) { | ||
| 1143 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
| 1144 | if (langwell->client_ops) | ||
| 1145 | langwell->client_ops->suspend(langwell->pdev, | ||
| 1146 | PMSG_FREEZE); | ||
| 1147 | else | ||
| 1148 | otg_dbg("client driver has been removed.\n"); | ||
| 1149 | langwell_otg_drv_vbus(0); | ||
| 1150 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
| 1151 | } else if (langwell->hsm.a_bus_drop) { | ||
| 1152 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
| 1153 | if (langwell->client_ops) | ||
| 1154 | langwell->client_ops->suspend(langwell->pdev, | ||
| 1155 | PMSG_FREEZE); | ||
| 1156 | else | ||
| 1157 | otg_dbg("client driver has been removed.\n"); | ||
| 1158 | langwell_otg_drv_vbus(0); | ||
| 1159 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1160 | } else if (langwell->hsm.b_bus_suspend) { | ||
| 1161 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
| 1162 | if (langwell->client_ops) | ||
| 1163 | langwell->client_ops->suspend(langwell->pdev, | ||
| 1164 | PMSG_FREEZE); | ||
| 1165 | else | ||
| 1166 | otg_dbg("client driver has been removed.\n"); | ||
| 1167 | |||
| 1168 | if (langwell->host_ops) | ||
| 1169 | langwell->host_ops->probe(langwell->pdev, | ||
| 1170 | langwell->host_ops->id_table); | ||
| 1171 | else | ||
| 1172 | otg_dbg("host driver not loaded.\n"); | ||
| 1173 | langwell->hsm.a_set_b_hnp_en = 0; | ||
| 1174 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
| 1175 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 1176 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1177 | } else if (langwell->hsm.b_bus_suspend_tmout) { | ||
| 1178 | u32 val; | ||
| 1179 | val = readl(langwell->regs + CI_PORTSC1); | ||
| 1180 | if (!(val & PORTSC_SUSP)) | ||
| 1181 | break; | ||
| 1182 | if (langwell->client_ops) | ||
| 1183 | langwell->client_ops->suspend(langwell->pdev, | ||
| 1184 | PMSG_FREEZE); | ||
| 1185 | else | ||
| 1186 | otg_dbg("client driver has been removed.\n"); | ||
| 1187 | if (langwell->host_ops) | ||
| 1188 | langwell->host_ops->probe(langwell->pdev, | ||
| 1189 | langwell->host_ops->id_table); | ||
| 1190 | else | ||
| 1191 | otg_dbg("host driver not loaded.\n"); | ||
| 1192 | langwell->hsm.a_set_b_hnp_en = 0; | ||
| 1193 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
| 1194 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 1195 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
| 1196 | } | ||
| 1197 | break; | ||
| 1198 | case OTG_STATE_A_VBUS_ERR: | ||
| 1199 | if (langwell->hsm.id) { | ||
| 1200 | langwell->otg.default_a = 0; | ||
| 1201 | langwell->hsm.a_clr_err = 0; | ||
| 1202 | langwell->hsm.a_srp_det = 0; | ||
| 1203 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1204 | queue_work(langwell->qwork, &langwell->work); | ||
| 1205 | } else if (langwell->hsm.a_clr_err) { | ||
| 1206 | langwell->hsm.a_clr_err = 0; | ||
| 1207 | langwell->hsm.a_srp_det = 0; | ||
| 1208 | reset_otg(); | ||
| 1209 | init_hsm(); | ||
| 1210 | if (langwell->otg.state == OTG_STATE_A_IDLE) | ||
| 1211 | queue_work(langwell->qwork, &langwell->work); | ||
| 1212 | } | ||
| 1213 | break; | ||
| 1214 | case OTG_STATE_A_WAIT_VFALL: | ||
| 1215 | if (langwell->hsm.id) { | ||
| 1216 | langwell->otg.default_a = 0; | ||
| 1217 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1218 | queue_work(langwell->qwork, &langwell->work); | ||
| 1219 | } else if (langwell->hsm.a_bus_req) { | ||
| 1220 | langwell_otg_drv_vbus(1); | ||
| 1221 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
| 1222 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
| 1223 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
| 1224 | } else if (!langwell->hsm.a_sess_vld) { | ||
| 1225 | langwell->hsm.a_srp_det = 0; | ||
| 1226 | langwell_otg_drv_vbus(0); | ||
| 1227 | set_host_mode(); | ||
| 1228 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 1229 | } | ||
| 1230 | break; | ||
| 1231 | default: | ||
| 1232 | ; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | otg_dbg("%s: new state = %s\n", __func__, | ||
| 1236 | state_string(langwell->otg.state)); | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static ssize_t | ||
| 1240 | show_registers(struct device *_dev, struct device_attribute *attr, char *buf) | ||
| 1241 | { | ||
| 1242 | struct langwell_otg *langwell; | ||
| 1243 | char *next; | ||
| 1244 | unsigned size; | ||
| 1245 | unsigned t; | ||
| 1246 | |||
| 1247 | langwell = the_transceiver; | ||
| 1248 | next = buf; | ||
| 1249 | size = PAGE_SIZE; | ||
| 1250 | |||
| 1251 | t = scnprintf(next, size, | ||
| 1252 | "\n" | ||
| 1253 | "USBCMD = 0x%08x \n" | ||
| 1254 | "USBSTS = 0x%08x \n" | ||
| 1255 | "USBINTR = 0x%08x \n" | ||
| 1256 | "ASYNCLISTADDR = 0x%08x \n" | ||
| 1257 | "PORTSC1 = 0x%08x \n" | ||
| 1258 | "HOSTPC1 = 0x%08x \n" | ||
| 1259 | "OTGSC = 0x%08x \n" | ||
| 1260 | "USBMODE = 0x%08x \n", | ||
| 1261 | readl(langwell->regs + 0x30), | ||
| 1262 | readl(langwell->regs + 0x34), | ||
| 1263 | readl(langwell->regs + 0x38), | ||
| 1264 | readl(langwell->regs + 0x48), | ||
| 1265 | readl(langwell->regs + 0x74), | ||
| 1266 | readl(langwell->regs + 0xb4), | ||
| 1267 | readl(langwell->regs + 0xf4), | ||
| 1268 | readl(langwell->regs + 0xf8) | ||
| 1269 | ); | ||
| 1270 | size -= t; | ||
| 1271 | next += t; | ||
| 1272 | |||
| 1273 | return PAGE_SIZE - size; | ||
| 1274 | } | ||
| 1275 | static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); | ||
| 1276 | |||
| 1277 | static ssize_t | ||
| 1278 | show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) | ||
| 1279 | { | ||
| 1280 | struct langwell_otg *langwell; | ||
| 1281 | char *next; | ||
| 1282 | unsigned size; | ||
| 1283 | unsigned t; | ||
| 1284 | |||
| 1285 | langwell = the_transceiver; | ||
| 1286 | next = buf; | ||
| 1287 | size = PAGE_SIZE; | ||
| 1288 | |||
| 1289 | t = scnprintf(next, size, | ||
| 1290 | "\n" | ||
| 1291 | "current state = %s\n" | ||
| 1292 | "a_bus_resume = \t%d\n" | ||
| 1293 | "a_bus_suspend = \t%d\n" | ||
| 1294 | "a_conn = \t%d\n" | ||
| 1295 | "a_sess_vld = \t%d\n" | ||
| 1296 | "a_srp_det = \t%d\n" | ||
| 1297 | "a_vbus_vld = \t%d\n" | ||
| 1298 | "b_bus_resume = \t%d\n" | ||
| 1299 | "b_bus_suspend = \t%d\n" | ||
| 1300 | "b_conn = \t%d\n" | ||
| 1301 | "b_se0_srp = \t%d\n" | ||
| 1302 | "b_sess_end = \t%d\n" | ||
| 1303 | "b_sess_vld = \t%d\n" | ||
| 1304 | "id = \t%d\n" | ||
| 1305 | "a_set_b_hnp_en = \t%d\n" | ||
| 1306 | "b_srp_done = \t%d\n" | ||
| 1307 | "b_hnp_enable = \t%d\n" | ||
| 1308 | "a_wait_vrise_tmout = \t%d\n" | ||
| 1309 | "a_wait_bcon_tmout = \t%d\n" | ||
| 1310 | "a_aidl_bdis_tmout = \t%d\n" | ||
| 1311 | "b_ase0_brst_tmout = \t%d\n" | ||
| 1312 | "a_bus_drop = \t%d\n" | ||
| 1313 | "a_bus_req = \t%d\n" | ||
| 1314 | "a_clr_err = \t%d\n" | ||
| 1315 | "a_suspend_req = \t%d\n" | ||
| 1316 | "b_bus_req = \t%d\n" | ||
| 1317 | "b_bus_suspend_tmout = \t%d\n" | ||
| 1318 | "b_bus_suspend_vld = \t%d\n", | ||
| 1319 | state_string(langwell->otg.state), | ||
| 1320 | langwell->hsm.a_bus_resume, | ||
| 1321 | langwell->hsm.a_bus_suspend, | ||
| 1322 | langwell->hsm.a_conn, | ||
| 1323 | langwell->hsm.a_sess_vld, | ||
| 1324 | langwell->hsm.a_srp_det, | ||
| 1325 | langwell->hsm.a_vbus_vld, | ||
| 1326 | langwell->hsm.b_bus_resume, | ||
| 1327 | langwell->hsm.b_bus_suspend, | ||
| 1328 | langwell->hsm.b_conn, | ||
| 1329 | langwell->hsm.b_se0_srp, | ||
| 1330 | langwell->hsm.b_sess_end, | ||
| 1331 | langwell->hsm.b_sess_vld, | ||
| 1332 | langwell->hsm.id, | ||
| 1333 | langwell->hsm.a_set_b_hnp_en, | ||
| 1334 | langwell->hsm.b_srp_done, | ||
| 1335 | langwell->hsm.b_hnp_enable, | ||
| 1336 | langwell->hsm.a_wait_vrise_tmout, | ||
| 1337 | langwell->hsm.a_wait_bcon_tmout, | ||
| 1338 | langwell->hsm.a_aidl_bdis_tmout, | ||
| 1339 | langwell->hsm.b_ase0_brst_tmout, | ||
| 1340 | langwell->hsm.a_bus_drop, | ||
| 1341 | langwell->hsm.a_bus_req, | ||
| 1342 | langwell->hsm.a_clr_err, | ||
| 1343 | langwell->hsm.a_suspend_req, | ||
| 1344 | langwell->hsm.b_bus_req, | ||
| 1345 | langwell->hsm.b_bus_suspend_tmout, | ||
| 1346 | langwell->hsm.b_bus_suspend_vld | ||
| 1347 | ); | ||
| 1348 | size -= t; | ||
| 1349 | next += t; | ||
| 1350 | |||
| 1351 | return PAGE_SIZE - size; | ||
| 1352 | } | ||
| 1353 | static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); | ||
| 1354 | |||
| 1355 | static ssize_t | ||
| 1356 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1357 | { | ||
| 1358 | struct langwell_otg *langwell; | ||
| 1359 | char *next; | ||
| 1360 | unsigned size; | ||
| 1361 | unsigned t; | ||
| 1362 | |||
| 1363 | langwell = the_transceiver; | ||
| 1364 | next = buf; | ||
| 1365 | size = PAGE_SIZE; | ||
| 1366 | |||
| 1367 | t = scnprintf(next, size, "%d", langwell->hsm.a_bus_req); | ||
| 1368 | size -= t; | ||
| 1369 | next += t; | ||
| 1370 | |||
| 1371 | return PAGE_SIZE - size; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | static ssize_t | ||
| 1375 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
| 1376 | const char *buf, size_t count) | ||
| 1377 | { | ||
| 1378 | struct langwell_otg *langwell; | ||
| 1379 | langwell = the_transceiver; | ||
| 1380 | if (!langwell->otg.default_a) | ||
| 1381 | return -1; | ||
| 1382 | if (count > 2) | ||
| 1383 | return -1; | ||
| 1384 | |||
| 1385 | if (buf[0] == '0') { | ||
| 1386 | langwell->hsm.a_bus_req = 0; | ||
| 1387 | otg_dbg("a_bus_req = 0\n"); | ||
| 1388 | } else if (buf[0] == '1') { | ||
| 1389 | /* If a_bus_drop is TRUE, a_bus_req can't be set */ | ||
| 1390 | if (langwell->hsm.a_bus_drop) | ||
| 1391 | return -1; | ||
| 1392 | langwell->hsm.a_bus_req = 1; | ||
| 1393 | otg_dbg("a_bus_req = 1\n"); | ||
| 1394 | } | ||
| 1395 | if (spin_trylock(&langwell->wq_lock)) { | ||
| 1396 | queue_work(langwell->qwork, &langwell->work); | ||
| 1397 | spin_unlock(&langwell->wq_lock); | ||
| 1398 | } | ||
| 1399 | return count; | ||
| 1400 | } | ||
| 1401 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req); | ||
| 1402 | |||
| 1403 | static ssize_t | ||
| 1404 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1405 | { | ||
| 1406 | struct langwell_otg *langwell; | ||
| 1407 | char *next; | ||
| 1408 | unsigned size; | ||
| 1409 | unsigned t; | ||
| 1410 | |||
| 1411 | langwell = the_transceiver; | ||
| 1412 | next = buf; | ||
| 1413 | size = PAGE_SIZE; | ||
| 1414 | |||
| 1415 | t = scnprintf(next, size, "%d", langwell->hsm.a_bus_drop); | ||
| 1416 | size -= t; | ||
| 1417 | next += t; | ||
| 1418 | |||
| 1419 | return PAGE_SIZE - size; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | static ssize_t | ||
| 1423 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
| 1424 | const char *buf, size_t count) | ||
| 1425 | { | ||
| 1426 | struct langwell_otg *langwell; | ||
| 1427 | langwell = the_transceiver; | ||
| 1428 | if (!langwell->otg.default_a) | ||
| 1429 | return -1; | ||
| 1430 | if (count > 2) | ||
| 1431 | return -1; | ||
| 1432 | |||
| 1433 | if (buf[0] == '0') { | ||
| 1434 | langwell->hsm.a_bus_drop = 0; | ||
| 1435 | otg_dbg("a_bus_drop = 0\n"); | ||
| 1436 | } else if (buf[0] == '1') { | ||
| 1437 | langwell->hsm.a_bus_drop = 1; | ||
| 1438 | langwell->hsm.a_bus_req = 0; | ||
| 1439 | otg_dbg("a_bus_drop = 1, then a_bus_req = 0\n"); | ||
| 1440 | } | ||
| 1441 | if (spin_trylock(&langwell->wq_lock)) { | ||
| 1442 | queue_work(langwell->qwork, &langwell->work); | ||
| 1443 | spin_unlock(&langwell->wq_lock); | ||
| 1444 | } | ||
| 1445 | return count; | ||
| 1446 | } | ||
| 1447 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO, | ||
| 1448 | get_a_bus_drop, set_a_bus_drop); | ||
| 1449 | |||
| 1450 | static ssize_t | ||
| 1451 | get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1452 | { | ||
| 1453 | struct langwell_otg *langwell; | ||
| 1454 | char *next; | ||
| 1455 | unsigned size; | ||
| 1456 | unsigned t; | ||
| 1457 | |||
| 1458 | langwell = the_transceiver; | ||
| 1459 | next = buf; | ||
| 1460 | size = PAGE_SIZE; | ||
| 1461 | |||
| 1462 | t = scnprintf(next, size, "%d", langwell->hsm.b_bus_req); | ||
| 1463 | size -= t; | ||
| 1464 | next += t; | ||
| 1465 | |||
| 1466 | return PAGE_SIZE - size; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | static ssize_t | ||
| 1470 | set_b_bus_req(struct device *dev, struct device_attribute *attr, | ||
| 1471 | const char *buf, size_t count) | ||
| 1472 | { | ||
| 1473 | struct langwell_otg *langwell; | ||
| 1474 | langwell = the_transceiver; | ||
| 1475 | |||
| 1476 | if (langwell->otg.default_a) | ||
| 1477 | return -1; | ||
| 1478 | |||
| 1479 | if (count > 2) | ||
| 1480 | return -1; | ||
| 1481 | |||
| 1482 | if (buf[0] == '0') { | ||
| 1483 | langwell->hsm.b_bus_req = 0; | ||
| 1484 | otg_dbg("b_bus_req = 0\n"); | ||
| 1485 | } else if (buf[0] == '1') { | ||
| 1486 | langwell->hsm.b_bus_req = 1; | ||
| 1487 | otg_dbg("b_bus_req = 1\n"); | ||
| 1488 | } | ||
| 1489 | if (spin_trylock(&langwell->wq_lock)) { | ||
| 1490 | queue_work(langwell->qwork, &langwell->work); | ||
| 1491 | spin_unlock(&langwell->wq_lock); | ||
| 1492 | } | ||
| 1493 | return count; | ||
| 1494 | } | ||
| 1495 | static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req); | ||
| 1496 | |||
| 1497 | static ssize_t | ||
| 1498 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
| 1499 | const char *buf, size_t count) | ||
| 1500 | { | ||
| 1501 | struct langwell_otg *langwell; | ||
| 1502 | langwell = the_transceiver; | ||
| 1503 | |||
| 1504 | if (!langwell->otg.default_a) | ||
| 1505 | return -1; | ||
| 1506 | if (count > 2) | ||
| 1507 | return -1; | ||
| 1508 | |||
| 1509 | if (buf[0] == '1') { | ||
| 1510 | langwell->hsm.a_clr_err = 1; | ||
| 1511 | otg_dbg("a_clr_err = 1\n"); | ||
| 1512 | } | ||
| 1513 | if (spin_trylock(&langwell->wq_lock)) { | ||
| 1514 | queue_work(langwell->qwork, &langwell->work); | ||
| 1515 | spin_unlock(&langwell->wq_lock); | ||
| 1516 | } | ||
| 1517 | return count; | ||
| 1518 | } | ||
| 1519 | static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err); | ||
| 1520 | |||
| 1521 | static struct attribute *inputs_attrs[] = { | ||
| 1522 | &dev_attr_a_bus_req.attr, | ||
| 1523 | &dev_attr_a_bus_drop.attr, | ||
| 1524 | &dev_attr_b_bus_req.attr, | ||
| 1525 | &dev_attr_a_clr_err.attr, | ||
| 1526 | NULL, | ||
| 1527 | }; | ||
| 1528 | |||
| 1529 | static struct attribute_group debug_dev_attr_group = { | ||
| 1530 | .name = "inputs", | ||
| 1531 | .attrs = inputs_attrs, | ||
| 1532 | }; | ||
| 1533 | |||
| 1534 | int langwell_register_host(struct pci_driver *host_driver) | ||
| 1535 | { | ||
| 1536 | int ret = 0; | ||
| 1537 | |||
| 1538 | the_transceiver->host_ops = host_driver; | ||
| 1539 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
| 1540 | otg_dbg("host controller driver is registered\n"); | ||
| 1541 | |||
| 1542 | return ret; | ||
| 1543 | } | ||
| 1544 | EXPORT_SYMBOL(langwell_register_host); | ||
| 1545 | |||
| 1546 | void langwell_unregister_host(struct pci_driver *host_driver) | ||
| 1547 | { | ||
| 1548 | if (the_transceiver->host_ops) | ||
| 1549 | the_transceiver->host_ops->remove(the_transceiver->pdev); | ||
| 1550 | the_transceiver->host_ops = NULL; | ||
| 1551 | the_transceiver->hsm.a_bus_drop = 1; | ||
| 1552 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
| 1553 | otg_dbg("host controller driver is unregistered\n"); | ||
| 1554 | } | ||
| 1555 | EXPORT_SYMBOL(langwell_unregister_host); | ||
| 1556 | |||
| 1557 | int langwell_register_peripheral(struct pci_driver *client_driver) | ||
| 1558 | { | ||
| 1559 | int ret = 0; | ||
| 1560 | |||
| 1561 | if (client_driver) | ||
| 1562 | ret = client_driver->probe(the_transceiver->pdev, | ||
| 1563 | client_driver->id_table); | ||
| 1564 | if (!ret) { | ||
| 1565 | the_transceiver->client_ops = client_driver; | ||
| 1566 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
| 1567 | otg_dbg("client controller driver is registered\n"); | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | return ret; | ||
| 1571 | } | ||
| 1572 | EXPORT_SYMBOL(langwell_register_peripheral); | ||
| 1573 | |||
| 1574 | void langwell_unregister_peripheral(struct pci_driver *client_driver) | ||
| 1575 | { | ||
| 1576 | if (the_transceiver->client_ops) | ||
| 1577 | the_transceiver->client_ops->remove(the_transceiver->pdev); | ||
| 1578 | the_transceiver->client_ops = NULL; | ||
| 1579 | the_transceiver->hsm.b_bus_req = 0; | ||
| 1580 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
| 1581 | otg_dbg("client controller driver is unregistered\n"); | ||
| 1582 | } | ||
| 1583 | EXPORT_SYMBOL(langwell_unregister_peripheral); | ||
| 1584 | |||
| 1585 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
| 1586 | const struct pci_device_id *id) | ||
| 1587 | { | ||
| 1588 | unsigned long resource, len; | ||
| 1589 | void __iomem *base = NULL; | ||
| 1590 | int retval; | ||
| 1591 | u32 val32; | ||
| 1592 | struct langwell_otg *langwell; | ||
| 1593 | char qname[] = "langwell_otg_queue"; | ||
| 1594 | |||
| 1595 | retval = 0; | ||
| 1596 | otg_dbg("\notg controller is detected.\n"); | ||
| 1597 | if (pci_enable_device(pdev) < 0) { | ||
| 1598 | retval = -ENODEV; | ||
| 1599 | goto done; | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | langwell = kzalloc(sizeof *langwell, GFP_KERNEL); | ||
| 1603 | if (langwell == NULL) { | ||
| 1604 | retval = -ENOMEM; | ||
| 1605 | goto done; | ||
| 1606 | } | ||
| 1607 | the_transceiver = langwell; | ||
| 1608 | |||
| 1609 | /* control register: BAR 0 */ | ||
| 1610 | resource = pci_resource_start(pdev, 0); | ||
| 1611 | len = pci_resource_len(pdev, 0); | ||
| 1612 | if (!request_mem_region(resource, len, driver_name)) { | ||
| 1613 | retval = -EBUSY; | ||
| 1614 | goto err; | ||
| 1615 | } | ||
| 1616 | langwell->region = 1; | ||
| 1617 | |||
| 1618 | base = ioremap_nocache(resource, len); | ||
| 1619 | if (base == NULL) { | ||
| 1620 | retval = -EFAULT; | ||
| 1621 | goto err; | ||
| 1622 | } | ||
| 1623 | langwell->regs = base; | ||
| 1624 | |||
| 1625 | if (!pdev->irq) { | ||
| 1626 | otg_dbg("No IRQ.\n"); | ||
| 1627 | retval = -ENODEV; | ||
| 1628 | goto err; | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | langwell->qwork = create_workqueue(qname); | ||
| 1632 | if (!langwell->qwork) { | ||
| 1633 | otg_dbg("cannot create workqueue %s\n", qname); | ||
| 1634 | retval = -ENOMEM; | ||
| 1635 | goto err; | ||
| 1636 | } | ||
| 1637 | INIT_WORK(&langwell->work, langwell_otg_work); | ||
| 1638 | |||
| 1639 | /* OTG common part */ | ||
| 1640 | langwell->pdev = pdev; | ||
| 1641 | langwell->otg.dev = &pdev->dev; | ||
| 1642 | langwell->otg.label = driver_name; | ||
| 1643 | langwell->otg.set_host = langwell_otg_set_host; | ||
| 1644 | langwell->otg.set_peripheral = langwell_otg_set_peripheral; | ||
| 1645 | langwell->otg.set_power = langwell_otg_set_power; | ||
| 1646 | langwell->otg.start_srp = langwell_otg_start_srp; | ||
| 1647 | langwell->otg.state = OTG_STATE_UNDEFINED; | ||
| 1648 | if (otg_set_transceiver(&langwell->otg)) { | ||
| 1649 | otg_dbg("can't set transceiver\n"); | ||
| 1650 | retval = -EBUSY; | ||
| 1651 | goto err; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | reset_otg(); | ||
| 1655 | init_hsm(); | ||
| 1656 | |||
| 1657 | spin_lock_init(&langwell->lock); | ||
| 1658 | spin_lock_init(&langwell->wq_lock); | ||
| 1659 | INIT_LIST_HEAD(&active_timers); | ||
| 1660 | langwell_otg_init_timers(&langwell->hsm); | ||
| 1661 | |||
| 1662 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
| 1663 | driver_name, langwell) != 0) { | ||
| 1664 | otg_dbg("request interrupt %d failed\n", pdev->irq); | ||
| 1665 | retval = -EBUSY; | ||
| 1666 | goto err; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | /* enable OTGSC int */ | ||
| 1670 | val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | | ||
| 1671 | OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; | ||
| 1672 | writel(val32, langwell->regs + CI_OTGSC); | ||
| 1673 | |||
| 1674 | retval = device_create_file(&pdev->dev, &dev_attr_registers); | ||
| 1675 | if (retval < 0) { | ||
| 1676 | otg_dbg("Can't register sysfs attribute: %d\n", retval); | ||
| 1677 | goto err; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | retval = device_create_file(&pdev->dev, &dev_attr_hsm); | ||
| 1681 | if (retval < 0) { | ||
| 1682 | otg_dbg("Can't hsm sysfs attribute: %d\n", retval); | ||
| 1683 | goto err; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
| 1687 | if (retval < 0) { | ||
| 1688 | otg_dbg("Can't register sysfs attr group: %d\n", retval); | ||
| 1689 | goto err; | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | if (langwell->otg.state == OTG_STATE_A_IDLE) | ||
| 1693 | queue_work(langwell->qwork, &langwell->work); | ||
| 1694 | |||
| 1695 | return 0; | ||
| 1696 | |||
| 1697 | err: | ||
| 1698 | if (the_transceiver) | ||
| 1699 | langwell_otg_remove(pdev); | ||
| 1700 | done: | ||
| 1701 | return retval; | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | static void langwell_otg_remove(struct pci_dev *pdev) | ||
| 1705 | { | ||
| 1706 | struct langwell_otg *langwell; | ||
| 1707 | |||
| 1708 | langwell = the_transceiver; | ||
| 1709 | |||
| 1710 | if (langwell->qwork) { | ||
| 1711 | flush_workqueue(langwell->qwork); | ||
| 1712 | destroy_workqueue(langwell->qwork); | ||
| 1713 | } | ||
| 1714 | langwell_otg_free_timers(); | ||
| 1715 | |||
| 1716 | /* disable OTGSC interrupt as OTGSC doesn't change in reset */ | ||
| 1717 | writel(0, langwell->regs + CI_OTGSC); | ||
| 1718 | |||
| 1719 | if (pdev->irq) | ||
| 1720 | free_irq(pdev->irq, langwell); | ||
| 1721 | if (langwell->regs) | ||
| 1722 | iounmap(langwell->regs); | ||
| 1723 | if (langwell->region) | ||
| 1724 | release_mem_region(pci_resource_start(pdev, 0), | ||
| 1725 | pci_resource_len(pdev, 0)); | ||
| 1726 | |||
| 1727 | otg_set_transceiver(NULL); | ||
| 1728 | pci_disable_device(pdev); | ||
| 1729 | sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
| 1730 | device_remove_file(&pdev->dev, &dev_attr_hsm); | ||
| 1731 | device_remove_file(&pdev->dev, &dev_attr_registers); | ||
| 1732 | kfree(langwell); | ||
| 1733 | langwell = NULL; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | static void transceiver_suspend(struct pci_dev *pdev) | ||
| 1737 | { | ||
| 1738 | pci_save_state(pdev); | ||
| 1739 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 1740 | langwell_otg_phy_low_power(1); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) | ||
| 1744 | { | ||
| 1745 | int ret = 0; | ||
| 1746 | struct langwell_otg *langwell; | ||
| 1747 | |||
| 1748 | langwell = the_transceiver; | ||
| 1749 | |||
| 1750 | /* Disbale OTG interrupts */ | ||
| 1751 | langwell_otg_intr(0); | ||
| 1752 | |||
| 1753 | if (pdev->irq) | ||
| 1754 | free_irq(pdev->irq, langwell); | ||
| 1755 | |||
| 1756 | /* Prevent more otg_work */ | ||
| 1757 | flush_workqueue(langwell->qwork); | ||
| 1758 | spin_lock(&langwell->wq_lock); | ||
| 1759 | |||
| 1760 | /* start actions */ | ||
| 1761 | switch (langwell->otg.state) { | ||
| 1762 | case OTG_STATE_A_IDLE: | ||
| 1763 | case OTG_STATE_B_IDLE: | ||
| 1764 | case OTG_STATE_A_WAIT_VFALL: | ||
| 1765 | case OTG_STATE_A_VBUS_ERR: | ||
| 1766 | transceiver_suspend(pdev); | ||
| 1767 | break; | ||
| 1768 | case OTG_STATE_A_WAIT_VRISE: | ||
| 1769 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
| 1770 | langwell->hsm.a_srp_det = 0; | ||
| 1771 | langwell_otg_drv_vbus(0); | ||
| 1772 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
| 1773 | transceiver_suspend(pdev); | ||
| 1774 | break; | ||
| 1775 | case OTG_STATE_A_WAIT_BCON: | ||
| 1776 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
| 1777 | if (langwell->host_ops) | ||
| 1778 | ret = langwell->host_ops->suspend(pdev, message); | ||
| 1779 | langwell_otg_drv_vbus(0); | ||
| 1780 | break; | ||
| 1781 | case OTG_STATE_A_HOST: | ||
| 1782 | if (langwell->host_ops) | ||
| 1783 | ret = langwell->host_ops->suspend(pdev, message); | ||
| 1784 | langwell_otg_drv_vbus(0); | ||
| 1785 | langwell_otg_phy_low_power(1); | ||
| 1786 | break; | ||
| 1787 | case OTG_STATE_A_SUSPEND: | ||
| 1788 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
| 1789 | langwell_otg_HABA(0); | ||
| 1790 | if (langwell->host_ops) | ||
| 1791 | langwell->host_ops->remove(pdev); | ||
| 1792 | else | ||
| 1793 | otg_dbg("host driver has been removed.\n"); | ||
| 1794 | langwell_otg_drv_vbus(0); | ||
| 1795 | transceiver_suspend(pdev); | ||
| 1796 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1797 | break; | ||
| 1798 | case OTG_STATE_A_PERIPHERAL: | ||
| 1799 | if (langwell->client_ops) | ||
| 1800 | ret = langwell->client_ops->suspend(pdev, message); | ||
| 1801 | else | ||
| 1802 | otg_dbg("client driver has been removed.\n"); | ||
| 1803 | langwell_otg_drv_vbus(0); | ||
| 1804 | transceiver_suspend(pdev); | ||
| 1805 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
| 1806 | break; | ||
| 1807 | case OTG_STATE_B_HOST: | ||
| 1808 | if (langwell->host_ops) | ||
| 1809 | langwell->host_ops->remove(pdev); | ||
| 1810 | else | ||
| 1811 | otg_dbg("host driver has been removed.\n"); | ||
| 1812 | langwell->hsm.b_bus_req = 0; | ||
| 1813 | transceiver_suspend(pdev); | ||
| 1814 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1815 | break; | ||
| 1816 | case OTG_STATE_B_PERIPHERAL: | ||
| 1817 | if (langwell->client_ops) | ||
| 1818 | ret = langwell->client_ops->suspend(pdev, message); | ||
| 1819 | else | ||
| 1820 | otg_dbg("client driver has been removed.\n"); | ||
| 1821 | break; | ||
| 1822 | case OTG_STATE_B_WAIT_ACON: | ||
| 1823 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
| 1824 | langwell_otg_HAAR(0); | ||
| 1825 | if (langwell->host_ops) | ||
| 1826 | langwell->host_ops->remove(pdev); | ||
| 1827 | else | ||
| 1828 | otg_dbg("host driver has been removed.\n"); | ||
| 1829 | langwell->hsm.b_bus_req = 0; | ||
| 1830 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
| 1831 | transceiver_suspend(pdev); | ||
| 1832 | break; | ||
| 1833 | default: | ||
| 1834 | otg_dbg("error state before suspend\n "); | ||
| 1835 | break; | ||
| 1836 | } | ||
| 1837 | spin_unlock(&langwell->wq_lock); | ||
| 1838 | |||
| 1839 | return ret; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | static void transceiver_resume(struct pci_dev *pdev) | ||
| 1843 | { | ||
| 1844 | pci_restore_state(pdev); | ||
| 1845 | pci_set_power_state(pdev, PCI_D0); | ||
| 1846 | langwell_otg_phy_low_power(0); | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | static int langwell_otg_resume(struct pci_dev *pdev) | ||
| 1850 | { | ||
| 1851 | int ret = 0; | ||
| 1852 | struct langwell_otg *langwell; | ||
| 1853 | |||
| 1854 | langwell = the_transceiver; | ||
| 1855 | |||
| 1856 | spin_lock(&langwell->wq_lock); | ||
| 1857 | |||
| 1858 | switch (langwell->otg.state) { | ||
| 1859 | case OTG_STATE_A_IDLE: | ||
| 1860 | case OTG_STATE_B_IDLE: | ||
| 1861 | case OTG_STATE_A_WAIT_VFALL: | ||
| 1862 | case OTG_STATE_A_VBUS_ERR: | ||
| 1863 | transceiver_resume(pdev); | ||
| 1864 | break; | ||
| 1865 | case OTG_STATE_A_WAIT_BCON: | ||
| 1866 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
| 1867 | langwell_otg_drv_vbus(1); | ||
| 1868 | if (langwell->host_ops) | ||
| 1869 | ret = langwell->host_ops->resume(pdev); | ||
| 1870 | break; | ||
| 1871 | case OTG_STATE_A_HOST: | ||
| 1872 | langwell_otg_drv_vbus(1); | ||
| 1873 | langwell_otg_phy_low_power(0); | ||
| 1874 | if (langwell->host_ops) | ||
| 1875 | ret = langwell->host_ops->resume(pdev); | ||
| 1876 | break; | ||
| 1877 | case OTG_STATE_B_PERIPHERAL: | ||
| 1878 | if (langwell->client_ops) | ||
| 1879 | ret = langwell->client_ops->resume(pdev); | ||
| 1880 | else | ||
| 1881 | otg_dbg("client driver not loaded.\n"); | ||
| 1882 | break; | ||
| 1883 | default: | ||
| 1884 | otg_dbg("error state before suspend\n "); | ||
| 1885 | break; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
| 1889 | driver_name, the_transceiver) != 0) { | ||
| 1890 | otg_dbg("request interrupt %d failed\n", pdev->irq); | ||
| 1891 | ret = -EBUSY; | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | /* enable OTG interrupts */ | ||
| 1895 | langwell_otg_intr(1); | ||
| 1896 | |||
| 1897 | spin_unlock(&langwell->wq_lock); | ||
| 1898 | |||
| 1899 | queue_work(langwell->qwork, &langwell->work); | ||
| 1900 | |||
| 1901 | |||
| 1902 | return ret; | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | static int __init langwell_otg_init(void) | ||
| 1906 | { | ||
| 1907 | return pci_register_driver(&otg_pci_driver); | ||
| 1908 | } | ||
| 1909 | module_init(langwell_otg_init); | ||
| 1910 | |||
| 1911 | static void __exit langwell_otg_cleanup(void) | ||
| 1912 | { | ||
| 1913 | pci_unregister_driver(&otg_pci_driver); | ||
| 1914 | } | ||
| 1915 | module_exit(langwell_otg_cleanup); | ||
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 9ed5ea568679..af456b48985f 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c | |||
| @@ -53,6 +53,7 @@ EXPORT_SYMBOL(usb_nop_xceiv_register); | |||
| 53 | void usb_nop_xceiv_unregister(void) | 53 | void usb_nop_xceiv_unregister(void) |
| 54 | { | 54 | { |
| 55 | platform_device_unregister(pd); | 55 | platform_device_unregister(pd); |
| 56 | pd = NULL; | ||
| 56 | } | 57 | } |
| 57 | EXPORT_SYMBOL(usb_nop_xceiv_unregister); | 58 | EXPORT_SYMBOL(usb_nop_xceiv_unregister); |
| 58 | 59 | ||
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 247b61bfb7f4..0e4f2e41ace5 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
| @@ -169,9 +169,11 @@ static int usb_console_setup(struct console *co, char *options) | |||
| 169 | kfree(tty); | 169 | kfree(tty); |
| 170 | } | 170 | } |
| 171 | } | 171 | } |
| 172 | /* So we know not to kill the hardware on a hangup on this | 172 | /* Now that any required fake tty operations are completed restore |
| 173 | port. We have also bumped the use count by one so it won't go | 173 | * the tty port count */ |
| 174 | idle */ | 174 | --port->port.count; |
| 175 | /* The console is special in terms of closing the device so | ||
| 176 | * indicate this port is now acting as a system console. */ | ||
| 175 | port->console = 1; | 177 | port->console = 1; |
| 176 | retval = 0; | 178 | retval = 0; |
| 177 | 179 | ||
| @@ -204,7 +206,7 @@ static void usb_console_write(struct console *co, | |||
| 204 | 206 | ||
| 205 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); | 207 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); |
| 206 | 208 | ||
| 207 | if (!port->port.count) { | 209 | if (!port->console) { |
| 208 | dbg("%s - port not opened", __func__); | 210 | dbg("%s - port not opened", __func__); |
| 209 | return; | 211 | return; |
| 210 | } | 212 | } |
| @@ -300,8 +302,7 @@ void usb_serial_console_exit(void) | |||
| 300 | { | 302 | { |
| 301 | if (usbcons_info.port) { | 303 | if (usbcons_info.port) { |
| 302 | unregister_console(&usbcons); | 304 | unregister_console(&usbcons); |
| 303 | if (usbcons_info.port->port.count) | 305 | usbcons_info.port->console = 0; |
| 304 | usbcons_info.port->port.count--; | ||
| 305 | usbcons_info.port = NULL; | 306 | usbcons_info.port = NULL; |
| 306 | } | 307 | } |
| 307 | } | 308 | } |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2b9eeda62bfe..e9a40b820fd4 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
| @@ -67,6 +67,8 @@ static struct usb_device_id id_table [] = { | |||
| 67 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 67 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
| 68 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 68 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
| 69 | { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ | 69 | { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ |
| 70 | { USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */ | ||
| 71 | { USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */ | ||
| 70 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ | 72 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ |
| 71 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 73 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
| 72 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ | 74 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 9734085fd2fe..59adfe123110 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
| @@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb) | |||
| 1228 | /* precursor to disconnect so just go away */ | 1228 | /* precursor to disconnect so just go away */ |
| 1229 | return; | 1229 | return; |
| 1230 | case -EPIPE: | 1230 | case -EPIPE: |
| 1231 | usb_clear_halt(port->serial->dev, 0x81); | 1231 | /* Can't call usb_clear_halt while in_interrupt */ |
| 1232 | break; | 1232 | /* FALLS THROUGH */ |
| 1233 | default: | 1233 | default: |
| 1234 | /* something ugly is going on... */ | 1234 | /* something ugly is going on... */ |
| 1235 | dev_err(&urb->dev->dev, | 1235 | dev_err(&urb->dev->dev, |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3dc3768ca71c..60c64cc5be2a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/smp_lock.h> | ||
| 36 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
| 37 | #include <linux/tty_driver.h> | 38 | #include <linux/tty_driver.h> |
| 38 | #include <linux/tty_flip.h> | 39 | #include <linux/tty_flip.h> |
| @@ -107,6 +108,7 @@ struct ftdi_sio_quirk { | |||
| 107 | 108 | ||
| 108 | static int ftdi_jtag_probe(struct usb_serial *serial); | 109 | static int ftdi_jtag_probe(struct usb_serial *serial); |
| 109 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); | 110 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); |
| 111 | static int ftdi_NDI_device_setup(struct usb_serial *serial); | ||
| 110 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); | 112 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); |
| 111 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); | 113 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); |
| 112 | 114 | ||
| @@ -118,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = { | |||
| 118 | .probe = ftdi_mtxorb_hack_setup, | 120 | .probe = ftdi_mtxorb_hack_setup, |
| 119 | }; | 121 | }; |
| 120 | 122 | ||
| 123 | static struct ftdi_sio_quirk ftdi_NDI_device_quirk = { | ||
| 124 | .probe = ftdi_NDI_device_setup, | ||
| 125 | }; | ||
| 126 | |||
| 121 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { | 127 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { |
| 122 | .port_probe = ftdi_USB_UIRT_setup, | 128 | .port_probe = ftdi_USB_UIRT_setup, |
| 123 | }; | 129 | }; |
| @@ -191,6 +197,7 @@ static struct usb_device_id id_table_combined [] = { | |||
| 191 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, | 197 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, |
| 192 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, | 198 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, |
| 193 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, | 199 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, |
| 200 | { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, | ||
| 194 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, | 201 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, |
| 195 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, | 202 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, |
| 196 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, | 203 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, |
| @@ -579,6 +586,9 @@ static struct usb_device_id id_table_combined [] = { | |||
| 579 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, | 586 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, |
| 580 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, | 587 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, |
| 581 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, | 588 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, |
| 589 | { USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) }, | ||
| 590 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) }, | ||
| 591 | { USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) }, | ||
| 582 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, | 592 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, |
| 583 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, | 593 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, |
| 584 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, | 594 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, |
| @@ -644,6 +654,16 @@ static struct usb_device_id id_table_combined [] = { | |||
| 644 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | 654 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, |
| 645 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | 655 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, |
| 646 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, | 656 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, |
| 657 | { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID), | ||
| 658 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
| 659 | { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID), | ||
| 660 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
| 661 | { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID), | ||
| 662 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
| 663 | { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID), | ||
| 664 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
| 665 | { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), | ||
| 666 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
| 647 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, | 667 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, |
| 648 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, | 668 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, |
| 649 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, | 669 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, |
| @@ -660,6 +680,8 @@ static struct usb_device_id id_table_combined [] = { | |||
| 660 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 680 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
| 661 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), | 681 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), |
| 662 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 682 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
| 683 | { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), | ||
| 684 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
| 663 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, | 685 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, |
| 664 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, | 686 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, |
| 665 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, | 687 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, |
| @@ -667,7 +689,6 @@ static struct usb_device_id id_table_combined [] = { | |||
| 667 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, | 689 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, |
| 668 | { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, | 690 | { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, |
| 669 | { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, | 691 | { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, |
| 670 | { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, | ||
| 671 | { USB_DEVICE(ATMEL_VID, STK541_PID) }, | 692 | { USB_DEVICE(ATMEL_VID, STK541_PID) }, |
| 672 | { USB_DEVICE(DE_VID, STB_PID) }, | 693 | { USB_DEVICE(DE_VID, STB_PID) }, |
| 673 | { USB_DEVICE(DE_VID, WHT_PID) }, | 694 | { USB_DEVICE(DE_VID, WHT_PID) }, |
| @@ -1023,6 +1044,16 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, | |||
| 1023 | case FT2232C: /* FT2232C chip */ | 1044 | case FT2232C: /* FT2232C chip */ |
| 1024 | case FT232RL: | 1045 | case FT232RL: |
| 1025 | if (baud <= 3000000) { | 1046 | if (baud <= 3000000) { |
| 1047 | __u16 product_id = le16_to_cpu( | ||
| 1048 | port->serial->dev->descriptor.idProduct); | ||
| 1049 | if (((FTDI_NDI_HUC_PID == product_id) || | ||
| 1050 | (FTDI_NDI_SPECTRA_SCU_PID == product_id) || | ||
| 1051 | (FTDI_NDI_FUTURE_2_PID == product_id) || | ||
| 1052 | (FTDI_NDI_FUTURE_3_PID == product_id) || | ||
| 1053 | (FTDI_NDI_AURORA_SCU_PID == product_id)) && | ||
| 1054 | (baud == 19200)) { | ||
| 1055 | baud = 1200000; | ||
| 1056 | } | ||
| 1026 | div_value = ftdi_232bm_baud_to_divisor(baud); | 1057 | div_value = ftdi_232bm_baud_to_divisor(baud); |
| 1027 | } else { | 1058 | } else { |
| 1028 | dbg("%s - Baud rate too high!", __func__); | 1059 | dbg("%s - Baud rate too high!", __func__); |
| @@ -1554,6 +1585,39 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) | |||
| 1554 | } /* ftdi_HE_TIRA1_setup */ | 1585 | } /* ftdi_HE_TIRA1_setup */ |
| 1555 | 1586 | ||
| 1556 | /* | 1587 | /* |
| 1588 | * Module parameter to control latency timer for NDI FTDI-based USB devices. | ||
| 1589 | * If this value is not set in modprobe.conf.local its value will be set to 1ms. | ||
| 1590 | */ | ||
| 1591 | static int ndi_latency_timer = 1; | ||
| 1592 | |||
| 1593 | /* Setup for the NDI FTDI-based USB devices, which requires hardwired | ||
| 1594 | * baudrate (19200 gets mapped to 1200000). | ||
| 1595 | * | ||
| 1596 | * Called from usbserial:serial_probe. | ||
| 1597 | */ | ||
| 1598 | static int ftdi_NDI_device_setup(struct usb_serial *serial) | ||
| 1599 | { | ||
| 1600 | struct usb_device *udev = serial->dev; | ||
| 1601 | int latency = ndi_latency_timer; | ||
| 1602 | int rv = 0; | ||
| 1603 | char buf[1]; | ||
| 1604 | |||
| 1605 | if (latency == 0) | ||
| 1606 | latency = 1; | ||
| 1607 | if (latency > 99) | ||
| 1608 | latency = 99; | ||
| 1609 | |||
| 1610 | dbg("%s setting NDI device latency to %d", __func__, latency); | ||
| 1611 | dev_info(&udev->dev, "NDI device with a latency value of %d", latency); | ||
| 1612 | |||
| 1613 | rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 1614 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
| 1615 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
| 1616 | latency, 0, buf, 0, WDR_TIMEOUT); | ||
| 1617 | return 0; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | /* | ||
| 1557 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko | 1621 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko |
| 1558 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from | 1622 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from |
| 1559 | * userspace using openocd. | 1623 | * userspace using openocd. |
| @@ -2121,7 +2185,7 @@ static void ftdi_process_read(struct work_struct *work) | |||
| 2121 | /* Note that the error flag is duplicated for | 2185 | /* Note that the error flag is duplicated for |
| 2122 | every character received since we don't know | 2186 | every character received since we don't know |
| 2123 | which character it applied to */ | 2187 | which character it applied to */ |
| 2124 | if (!usb_serial_handle_sysrq_char(port, | 2188 | if (!usb_serial_handle_sysrq_char(tty, port, |
| 2125 | data[packet_offset + i])) | 2189 | data[packet_offset + i])) |
| 2126 | tty_insert_flip_char(tty, | 2190 | tty_insert_flip_char(tty, |
| 2127 | data[packet_offset + i], | 2191 | data[packet_offset + i], |
| @@ -2622,3 +2686,5 @@ MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" | |||
| 2622 | module_param(product, ushort, 0); | 2686 | module_param(product, ushort, 0); |
| 2623 | MODULE_PARM_DESC(product, "User specified product ID"); | 2687 | MODULE_PARM_DESC(product, "User specified product ID"); |
| 2624 | 2688 | ||
| 2689 | module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR); | ||
| 2690 | MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override"); | ||
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f1d440a728a3..c9fbd7415092 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
| @@ -506,6 +506,7 @@ | |||
| 506 | * | 506 | * |
| 507 | * Armin Laeuger originally sent the PID for the UM 100 module. | 507 | * Armin Laeuger originally sent the PID for the UM 100 module. |
| 508 | */ | 508 | */ |
| 509 | #define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */ | ||
| 509 | #define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ | 510 | #define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ |
| 510 | #define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ | 511 | #define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ |
| 511 | #define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ | 512 | #define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ |
| @@ -614,6 +615,9 @@ | |||
| 614 | #define FTDI_CCSICDU20_0_PID 0xF9D0 | 615 | #define FTDI_CCSICDU20_0_PID 0xF9D0 |
| 615 | #define FTDI_CCSICDU40_1_PID 0xF9D1 | 616 | #define FTDI_CCSICDU40_1_PID 0xF9D1 |
| 616 | #define FTDI_CCSMACHX_2_PID 0xF9D2 | 617 | #define FTDI_CCSMACHX_2_PID 0xF9D2 |
| 618 | #define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 | ||
| 619 | #define FTDI_CCSICDU64_4_PID 0xF9D4 | ||
| 620 | #define FTDI_CCSPRIME8_5_PID 0xF9D5 | ||
| 617 | 621 | ||
| 618 | /* Inside Accesso contactless reader (http://www.insidefr.com) */ | 622 | /* Inside Accesso contactless reader (http://www.insidefr.com) */ |
| 619 | #define INSIDE_ACCESSO 0xFAD0 | 623 | #define INSIDE_ACCESSO 0xFAD0 |
| @@ -736,6 +740,15 @@ | |||
| 736 | #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ | 740 | #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ |
| 737 | 741 | ||
| 738 | /* | 742 | /* |
| 743 | * NDI (www.ndigital.com) product ids | ||
| 744 | */ | ||
| 745 | #define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ | ||
| 746 | #define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ | ||
| 747 | #define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ | ||
| 748 | #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ | ||
| 749 | #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ | ||
| 750 | |||
| 751 | /* | ||
| 739 | * Posiflex inc retail equipment (http://www.posiflex.com.tw) | 752 | * Posiflex inc retail equipment (http://www.posiflex.com.tw) |
| 740 | */ | 753 | */ |
| 741 | #define POSIFLEX_VID 0x0d3a /* Vendor ID */ | 754 | #define POSIFLEX_VID 0x0d3a /* Vendor ID */ |
| @@ -848,9 +861,6 @@ | |||
| 848 | #define TML_VID 0x1B91 /* Vendor ID */ | 861 | #define TML_VID 0x1B91 /* Vendor ID */ |
| 849 | #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ | 862 | #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ |
| 850 | 863 | ||
| 851 | /* NDI Polaris System */ | ||
| 852 | #define FTDI_NDI_HUC_PID 0xDA70 | ||
| 853 | |||
| 854 | /* Propox devices */ | 864 | /* Propox devices */ |
| 855 | #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 | 865 | #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 |
| 856 | 866 | ||
| @@ -934,6 +944,8 @@ | |||
| 934 | #define MARVELL_VID 0x9e88 | 944 | #define MARVELL_VID 0x9e88 |
| 935 | #define MARVELL_SHEEVAPLUG_PID 0x9e8f | 945 | #define MARVELL_SHEEVAPLUG_PID 0x9e8f |
| 936 | 946 | ||
| 947 | #define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ | ||
| 948 | |||
| 937 | /* | 949 | /* |
| 938 | * BmRequestType: 1100 0000b | 950 | * BmRequestType: 1100 0000b |
| 939 | * bRequest: FTDI_E2_READ | 951 | * bRequest: FTDI_E2_READ |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 932d6241b787..ce57f6a32bdf 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
| @@ -424,10 +424,17 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | |||
| 424 | if (!tty) | 424 | if (!tty) |
| 425 | goto done; | 425 | goto done; |
| 426 | 426 | ||
| 427 | /* Push data to tty */ | 427 | /* The per character mucking around with sysrq path it too slow for |
| 428 | for (i = 0; i < urb->actual_length; i++, ch++) { | 428 | stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases |
| 429 | if (!usb_serial_handle_sysrq_char(port, *ch)) | 429 | where the USB serial is not a console anyway */ |
| 430 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); | 430 | if (!port->console || !port->sysrq) |
| 431 | tty_insert_flip_string(tty, ch, urb->actual_length); | ||
| 432 | else { | ||
| 433 | /* Push data to tty */ | ||
| 434 | for (i = 0; i < urb->actual_length; i++, ch++) { | ||
| 435 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | ||
| 436 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); | ||
| 437 | } | ||
| 431 | } | 438 | } |
| 432 | tty_flip_buffer_push(tty); | 439 | tty_flip_buffer_push(tty); |
| 433 | tty_kref_put(tty); | 440 | tty_kref_put(tty); |
| @@ -527,11 +534,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) | |||
| 527 | } | 534 | } |
| 528 | } | 535 | } |
| 529 | 536 | ||
| 530 | int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) | 537 | int usb_serial_handle_sysrq_char(struct tty_struct *tty, |
| 538 | struct usb_serial_port *port, unsigned int ch) | ||
| 531 | { | 539 | { |
| 532 | if (port->sysrq && port->console) { | 540 | if (port->sysrq && port->console) { |
| 533 | if (ch && time_before(jiffies, port->sysrq)) { | 541 | if (ch && time_before(jiffies, port->sysrq)) { |
| 534 | handle_sysrq(ch, tty_port_tty_get(&port->port)); | 542 | handle_sysrq(ch, tty); |
| 535 | port->sysrq = 0; | 543 | port->sysrq = 0; |
| 536 | return 1; | 544 | return 1; |
| 537 | } | 545 | } |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c40f95c1951c..c31940a307f8 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
| 30 | #include <linux/tty_driver.h> | 31 | #include <linux/tty_driver.h> |
| 31 | #include <linux/tty_flip.h> | 32 | #include <linux/tty_flip.h> |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 575816e6ba37..98262dd552bb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -206,6 +206,7 @@ static int option_resume(struct usb_serial *serial); | |||
| 206 | #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 | 206 | #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 |
| 207 | #define NOVATELWIRELESS_PRODUCT_U727 0x5010 | 207 | #define NOVATELWIRELESS_PRODUCT_U727 0x5010 |
| 208 | #define NOVATELWIRELESS_PRODUCT_MC760 0x6000 | 208 | #define NOVATELWIRELESS_PRODUCT_MC760 0x6000 |
| 209 | #define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002 | ||
| 209 | 210 | ||
| 210 | /* FUTURE NOVATEL PRODUCTS */ | 211 | /* FUTURE NOVATEL PRODUCTS */ |
| 211 | #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 | 212 | #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 |
| @@ -307,11 +308,20 @@ static int option_resume(struct usb_serial *serial); | |||
| 307 | #define DLINK_VENDOR_ID 0x1186 | 308 | #define DLINK_VENDOR_ID 0x1186 |
| 308 | #define DLINK_PRODUCT_DWM_652 0x3e04 | 309 | #define DLINK_PRODUCT_DWM_652 0x3e04 |
| 309 | 310 | ||
| 311 | #define QISDA_VENDOR_ID 0x1da5 | ||
| 312 | #define QISDA_PRODUCT_H21_4512 0x4512 | ||
| 313 | #define QISDA_PRODUCT_H21_4523 0x4523 | ||
| 314 | #define QISDA_PRODUCT_H20_4515 0x4515 | ||
| 315 | #define QISDA_PRODUCT_H20_4519 0x4519 | ||
| 316 | |||
| 310 | 317 | ||
| 311 | /* TOSHIBA PRODUCTS */ | 318 | /* TOSHIBA PRODUCTS */ |
| 312 | #define TOSHIBA_VENDOR_ID 0x0930 | 319 | #define TOSHIBA_VENDOR_ID 0x0930 |
| 313 | #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 | 320 | #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 |
| 314 | 321 | ||
| 322 | #define ALINK_VENDOR_ID 0x1e0e | ||
| 323 | #define ALINK_PRODUCT_3GU 0x9200 | ||
| 324 | |||
| 315 | static struct usb_device_id option_ids[] = { | 325 | static struct usb_device_id option_ids[] = { |
| 316 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, | 326 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, |
| 317 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, | 327 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, |
| @@ -430,6 +440,7 @@ static struct usb_device_id option_ids[] = { | |||
| 430 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ | 440 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ |
| 431 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ | 441 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ |
| 432 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ | 442 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ |
| 443 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */ | ||
| 433 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ | 444 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ |
| 434 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ | 445 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ |
| 435 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ | 446 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ |
| @@ -529,8 +540,13 @@ static struct usb_device_id option_ids[] = { | |||
| 529 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, | 540 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, |
| 530 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, | 541 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, |
| 531 | { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, | 542 | { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, |
| 532 | { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ | 543 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, |
| 544 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, | ||
| 545 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, | ||
| 546 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, | ||
| 533 | { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ | 547 | { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ |
| 548 | { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, | ||
| 549 | { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, | ||
| 534 | { } /* Terminating entry */ | 550 | { } /* Terminating entry */ |
| 535 | }; | 551 | }; |
| 536 | MODULE_DEVICE_TABLE(usb, option_ids); | 552 | MODULE_DEVICE_TABLE(usb, option_ids); |
| @@ -732,7 +748,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 732 | memcpy(this_urb->transfer_buffer, buf, todo); | 748 | memcpy(this_urb->transfer_buffer, buf, todo); |
| 733 | this_urb->transfer_buffer_length = todo; | 749 | this_urb->transfer_buffer_length = todo; |
| 734 | 750 | ||
| 735 | this_urb->dev = port->serial->dev; | ||
| 736 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | 751 | err = usb_submit_urb(this_urb, GFP_ATOMIC); |
| 737 | if (err) { | 752 | if (err) { |
| 738 | dbg("usb_submit_urb %p (write bulk) failed " | 753 | dbg("usb_submit_urb %p (write bulk) failed " |
| @@ -860,7 +875,6 @@ static void option_instat_callback(struct urb *urb) | |||
| 860 | 875 | ||
| 861 | /* Resubmit urb so we continue receiving IRQ data */ | 876 | /* Resubmit urb so we continue receiving IRQ data */ |
| 862 | if (status != -ESHUTDOWN && status != -ENOENT) { | 877 | if (status != -ESHUTDOWN && status != -ENOENT) { |
| 863 | urb->dev = serial->dev; | ||
| 864 | err = usb_submit_urb(urb, GFP_ATOMIC); | 878 | err = usb_submit_urb(urb, GFP_ATOMIC); |
| 865 | if (err) | 879 | if (err) |
| 866 | dbg("%s: resubmit intr urb failed. (%d)", | 880 | dbg("%s: resubmit intr urb failed. (%d)", |
| @@ -921,23 +935,11 @@ static int option_open(struct tty_struct *tty, | |||
| 921 | 935 | ||
| 922 | dbg("%s", __func__); | 936 | dbg("%s", __func__); |
| 923 | 937 | ||
| 924 | /* Reset low level data toggle and start reading from endpoints */ | 938 | /* Start reading from the IN endpoint */ |
| 925 | for (i = 0; i < N_IN_URB; i++) { | 939 | for (i = 0; i < N_IN_URB; i++) { |
| 926 | urb = portdata->in_urbs[i]; | 940 | urb = portdata->in_urbs[i]; |
| 927 | if (!urb) | 941 | if (!urb) |
| 928 | continue; | 942 | continue; |
| 929 | if (urb->dev != serial->dev) { | ||
| 930 | dbg("%s: dev %p != %p", __func__, | ||
| 931 | urb->dev, serial->dev); | ||
| 932 | continue; | ||
| 933 | } | ||
| 934 | |||
| 935 | /* | ||
| 936 | * make sure endpoint data toggle is synchronized with the | ||
| 937 | * device | ||
| 938 | */ | ||
| 939 | usb_clear_halt(urb->dev, urb->pipe); | ||
| 940 | |||
| 941 | err = usb_submit_urb(urb, GFP_KERNEL); | 943 | err = usb_submit_urb(urb, GFP_KERNEL); |
| 942 | if (err) { | 944 | if (err) { |
| 943 | dbg("%s: submit urb %d failed (%d) %d", | 945 | dbg("%s: submit urb %d failed (%d) %d", |
| @@ -946,16 +948,6 @@ static int option_open(struct tty_struct *tty, | |||
| 946 | } | 948 | } |
| 947 | } | 949 | } |
| 948 | 950 | ||
| 949 | /* Reset low level data toggle on out endpoints */ | ||
| 950 | for (i = 0; i < N_OUT_URB; i++) { | ||
| 951 | urb = portdata->out_urbs[i]; | ||
| 952 | if (!urb) | ||
| 953 | continue; | ||
| 954 | urb->dev = serial->dev; | ||
| 955 | /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
| 956 | usb_pipeout(urb->pipe), 0); */ | ||
| 957 | } | ||
| 958 | |||
| 959 | option_send_setup(port); | 951 | option_send_setup(port); |
| 960 | 952 | ||
| 961 | return 0; | 953 | return 0; |
| @@ -1218,7 +1210,6 @@ static int option_resume(struct usb_serial *serial) | |||
| 1218 | dbg("%s: No interrupt URB for port %d\n", __func__, i); | 1210 | dbg("%s: No interrupt URB for port %d\n", __func__, i); |
| 1219 | continue; | 1211 | continue; |
| 1220 | } | 1212 | } |
| 1221 | port->interrupt_in_urb->dev = serial->dev; | ||
| 1222 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); | 1213 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); |
| 1223 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); | 1214 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); |
| 1224 | if (err < 0) { | 1215 | if (err < 0) { |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ec6c132a25b5..7d15bfa7c2db 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -94,6 +94,7 @@ static struct usb_device_id id_table [] = { | |||
| 94 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, | 94 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
| 95 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, | 95 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, |
| 96 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, | 96 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, |
| 97 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, | ||
| 97 | { } /* Terminating entry */ | 98 | { } /* Terminating entry */ |
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| @@ -971,18 +972,46 @@ exit: | |||
| 971 | __func__, retval); | 972 | __func__, retval); |
| 972 | } | 973 | } |
| 973 | 974 | ||
| 975 | static void pl2303_push_data(struct tty_struct *tty, | ||
| 976 | struct usb_serial_port *port, struct urb *urb, | ||
| 977 | u8 line_status) | ||
| 978 | { | ||
| 979 | unsigned char *data = urb->transfer_buffer; | ||
| 980 | /* get tty_flag from status */ | ||
| 981 | char tty_flag = TTY_NORMAL; | ||
| 982 | /* break takes precedence over parity, */ | ||
| 983 | /* which takes precedence over framing errors */ | ||
| 984 | if (line_status & UART_BREAK_ERROR) | ||
| 985 | tty_flag = TTY_BREAK; | ||
| 986 | else if (line_status & UART_PARITY_ERROR) | ||
| 987 | tty_flag = TTY_PARITY; | ||
| 988 | else if (line_status & UART_FRAME_ERROR) | ||
| 989 | tty_flag = TTY_FRAME; | ||
| 990 | dbg("%s - tty_flag = %d", __func__, tty_flag); | ||
| 991 | |||
| 992 | tty_buffer_request_room(tty, urb->actual_length + 1); | ||
| 993 | /* overrun is special, not associated with a char */ | ||
| 994 | if (line_status & UART_OVERRUN_ERROR) | ||
| 995 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
| 996 | if (port->console && port->sysrq) { | ||
| 997 | int i; | ||
| 998 | for (i = 0; i < urb->actual_length; ++i) | ||
| 999 | if (!usb_serial_handle_sysrq_char(tty, port, data[i])) | ||
| 1000 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
| 1001 | } else | ||
| 1002 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
| 1003 | tty_flip_buffer_push(tty); | ||
| 1004 | } | ||
| 1005 | |||
| 974 | static void pl2303_read_bulk_callback(struct urb *urb) | 1006 | static void pl2303_read_bulk_callback(struct urb *urb) |
| 975 | { | 1007 | { |
| 976 | struct usb_serial_port *port = urb->context; | 1008 | struct usb_serial_port *port = urb->context; |
| 977 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 1009 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
| 978 | struct tty_struct *tty; | 1010 | struct tty_struct *tty; |
| 979 | unsigned char *data = urb->transfer_buffer; | ||
| 980 | unsigned long flags; | 1011 | unsigned long flags; |
| 981 | int i; | ||
| 982 | int result; | 1012 | int result; |
| 983 | int status = urb->status; | 1013 | int status = urb->status; |
| 984 | u8 line_status; | 1014 | u8 line_status; |
| 985 | char tty_flag; | ||
| 986 | 1015 | ||
| 987 | dbg("%s - port %d", __func__, port->number); | 1016 | dbg("%s - port %d", __func__, port->number); |
| 988 | 1017 | ||
| @@ -1010,10 +1039,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
| 1010 | } | 1039 | } |
| 1011 | 1040 | ||
| 1012 | usb_serial_debug_data(debug, &port->dev, __func__, | 1041 | usb_serial_debug_data(debug, &port->dev, __func__, |
| 1013 | urb->actual_length, data); | 1042 | urb->actual_length, urb->transfer_buffer); |
| 1014 | |||
| 1015 | /* get tty_flag from status */ | ||
| 1016 | tty_flag = TTY_NORMAL; | ||
| 1017 | 1043 | ||
| 1018 | spin_lock_irqsave(&priv->lock, flags); | 1044 | spin_lock_irqsave(&priv->lock, flags); |
| 1019 | line_status = priv->line_status; | 1045 | line_status = priv->line_status; |
| @@ -1021,26 +1047,9 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
| 1021 | spin_unlock_irqrestore(&priv->lock, flags); | 1047 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1022 | wake_up_interruptible(&priv->delta_msr_wait); | 1048 | wake_up_interruptible(&priv->delta_msr_wait); |
| 1023 | 1049 | ||
| 1024 | /* break takes precedence over parity, */ | ||
| 1025 | /* which takes precedence over framing errors */ | ||
| 1026 | if (line_status & UART_BREAK_ERROR) | ||
| 1027 | tty_flag = TTY_BREAK; | ||
| 1028 | else if (line_status & UART_PARITY_ERROR) | ||
| 1029 | tty_flag = TTY_PARITY; | ||
| 1030 | else if (line_status & UART_FRAME_ERROR) | ||
| 1031 | tty_flag = TTY_FRAME; | ||
| 1032 | dbg("%s - tty_flag = %d", __func__, tty_flag); | ||
| 1033 | |||
| 1034 | tty = tty_port_tty_get(&port->port); | 1050 | tty = tty_port_tty_get(&port->port); |
| 1035 | if (tty && urb->actual_length) { | 1051 | if (tty && urb->actual_length) { |
| 1036 | tty_buffer_request_room(tty, urb->actual_length + 1); | 1052 | pl2303_push_data(tty, port, urb, line_status); |
| 1037 | /* overrun is special, not associated with a char */ | ||
| 1038 | if (line_status & UART_OVERRUN_ERROR) | ||
| 1039 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
| 1040 | for (i = 0; i < urb->actual_length; ++i) | ||
| 1041 | if (!usb_serial_handle_sysrq_char(port, data[i])) | ||
| 1042 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
| 1043 | tty_flip_buffer_push(tty); | ||
| 1044 | } | 1053 | } |
| 1045 | tty_kref_put(tty); | 1054 | tty_kref_put(tty); |
| 1046 | /* Schedule the next read _if_ we are still open */ | 1055 | /* Schedule the next read _if_ we are still open */ |
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 1d7a22e3a9fd..12aac7d2462d 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
| @@ -122,3 +122,7 @@ | |||
| 122 | /* Hewlett-Packard LD220-HP POS Pole Display */ | 122 | /* Hewlett-Packard LD220-HP POS Pole Display */ |
| 123 | #define HP_VENDOR_ID 0x03f0 | 123 | #define HP_VENDOR_ID 0x03f0 |
| 124 | #define HP_LD220_PRODUCT_ID 0x3524 | 124 | #define HP_LD220_PRODUCT_ID 0x3524 |
| 125 | |||
| 126 | /* Cressi Edy (diving computer) PC interface */ | ||
| 127 | #define CRESSI_VENDOR_ID 0x04b8 | ||
| 128 | #define CRESSI_EDY_PRODUCT_ID 0x0521 | ||
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 032f7aeb40a4..f48d05e0acc1 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
| @@ -181,35 +181,50 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = { | |||
| 181 | }; | 181 | }; |
| 182 | 182 | ||
| 183 | static struct usb_device_id id_table [] = { | 183 | static struct usb_device_id id_table [] = { |
| 184 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | ||
| 185 | { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */ | ||
| 186 | { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */ | ||
| 187 | |||
| 184 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 188 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
| 185 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | 189 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ |
| 186 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | 190 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ |
| 187 | { USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */ | ||
| 188 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ | 191 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ |
| 189 | { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ | ||
| 190 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ | 192 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ |
| 193 | { USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */ | ||
| 194 | { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ | ||
| 195 | { USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */ | ||
| 191 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ | 196 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ |
| 192 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ | 197 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ |
| 198 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | ||
| 193 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ | 199 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ |
| 194 | /* Sierra Wireless C597 */ | 200 | /* Sierra Wireless C597 */ |
| 195 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, | 201 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, |
| 196 | /* Sierra Wireless Device */ | 202 | /* Sierra Wireless T598 */ |
| 197 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, | 203 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, |
| 198 | { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */ | 204 | { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */ |
| 199 | { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */ | 205 | { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */ |
| 200 | { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */ | 206 | { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */ |
| 207 | { USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */ | ||
| 201 | 208 | ||
| 202 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ | 209 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ |
| 203 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | ||
| 204 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ | 210 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ |
| 211 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | ||
| 212 | { USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */ | ||
| 213 | { USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */ | ||
| 214 | { USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */ | ||
| 205 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ | 215 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ |
| 206 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */ | 216 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */ |
| 207 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ | 217 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ |
| 208 | { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */ | 218 | { USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */ |
| 209 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ | 219 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ |
| 210 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ | 220 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ |
| 221 | { USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */ | ||
| 211 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ | 222 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ |
| 212 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ | 223 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ |
| 224 | { USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */ | ||
| 225 | { USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */ | ||
| 226 | { USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */ | ||
| 227 | { USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */ | ||
| 213 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ | 228 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ |
| 214 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ | 229 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ |
| 215 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ | 230 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ |
| @@ -227,16 +242,13 @@ static struct usb_device_id id_table [] = { | |||
| 227 | { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ | 242 | { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ |
| 228 | /* Sierra Wireless C885 */ | 243 | /* Sierra Wireless C885 */ |
| 229 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, | 244 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, |
| 230 | /* Sierra Wireless Device */ | 245 | /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ |
| 231 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, | 246 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, |
| 232 | /* Sierra Wireless Device */ | 247 | /* Sierra Wireless C22/C33 */ |
| 233 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, | 248 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, |
| 234 | /* Sierra Wireless Device */ | 249 | /* Sierra Wireless HSPA Non-Composite Device */ |
| 235 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, | 250 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, |
| 236 | 251 | { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ | |
| 237 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | ||
| 238 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | ||
| 239 | |||
| 240 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ | 252 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ |
| 241 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | 253 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist |
| 242 | }, | 254 | }, |
| @@ -814,7 +826,7 @@ static int sierra_startup(struct usb_serial *serial) | |||
| 814 | return 0; | 826 | return 0; |
| 815 | } | 827 | } |
| 816 | 828 | ||
| 817 | static void sierra_disconnect(struct usb_serial *serial) | 829 | static void sierra_release(struct usb_serial *serial) |
| 818 | { | 830 | { |
| 819 | int i; | 831 | int i; |
| 820 | struct usb_serial_port *port; | 832 | struct usb_serial_port *port; |
| @@ -830,7 +842,6 @@ static void sierra_disconnect(struct usb_serial *serial) | |||
| 830 | if (!portdata) | 842 | if (!portdata) |
| 831 | continue; | 843 | continue; |
| 832 | kfree(portdata); | 844 | kfree(portdata); |
| 833 | usb_set_serial_port_data(port, NULL); | ||
| 834 | } | 845 | } |
| 835 | } | 846 | } |
| 836 | 847 | ||
| @@ -853,7 +864,7 @@ static struct usb_serial_driver sierra_device = { | |||
| 853 | .tiocmget = sierra_tiocmget, | 864 | .tiocmget = sierra_tiocmget, |
| 854 | .tiocmset = sierra_tiocmset, | 865 | .tiocmset = sierra_tiocmset, |
| 855 | .attach = sierra_startup, | 866 | .attach = sierra_startup, |
| 856 | .disconnect = sierra_disconnect, | 867 | .release = sierra_release, |
| 857 | .read_int_callback = sierra_instat_callback, | 868 | .read_int_callback = sierra_instat_callback, |
| 858 | }; | 869 | }; |
| 859 | 870 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 991d8232e376..14971a926990 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
| @@ -191,7 +191,6 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { | |||
| 191 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, | 191 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, |
| 192 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, | 192 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, |
| 193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, | 193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, |
| 194 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | ||
| 195 | }; | 194 | }; |
| 196 | 195 | ||
| 197 | static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = { | 196 | static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = { |
| @@ -1658,7 +1657,7 @@ static int ti_do_download(struct usb_device *dev, int pipe, | |||
| 1658 | u8 cs = 0; | 1657 | u8 cs = 0; |
| 1659 | int done; | 1658 | int done; |
| 1660 | struct ti_firmware_header *header; | 1659 | struct ti_firmware_header *header; |
| 1661 | int status; | 1660 | int status = 0; |
| 1662 | int len; | 1661 | int len; |
| 1663 | 1662 | ||
| 1664 | for (pos = sizeof(struct ti_firmware_header); pos < size; pos++) | 1663 | for (pos = sizeof(struct ti_firmware_header); pos < size; pos++) |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d595aa5586a7..bd7581b3a48a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/smp_lock.h> | ||
| 24 | #include <linux/tty.h> | 25 | #include <linux/tty.h> |
| 25 | #include <linux/tty_driver.h> | 26 | #include <linux/tty_driver.h> |
| 26 | #include <linux/tty_flip.h> | 27 | #include <linux/tty_flip.h> |
| @@ -220,7 +221,8 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
| 220 | tty->driver_data = port; | 221 | tty->driver_data = port; |
| 221 | tty_port_tty_set(&port->port, tty); | 222 | tty_port_tty_set(&port->port, tty); |
| 222 | 223 | ||
| 223 | if (port->port.count == 1) { | 224 | /* If the console is attached, the device is already open */ |
| 225 | if (port->port.count == 1 && !port->console) { | ||
| 224 | 226 | ||
| 225 | /* lock this module before we call it | 227 | /* lock this module before we call it |
| 226 | * this may fail, which means we must bail out, | 228 | * this may fail, which means we must bail out, |
| @@ -333,6 +335,9 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
| 333 | { | 335 | { |
| 334 | struct usb_serial_port *port = tty->driver_data; | 336 | struct usb_serial_port *port = tty->driver_data; |
| 335 | 337 | ||
| 338 | if (!port) | ||
| 339 | return; | ||
| 340 | |||
| 336 | dbg("%s - port %d", __func__, port->number); | 341 | dbg("%s - port %d", __func__, port->number); |
| 337 | 342 | ||
| 338 | 343 | ||
diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c index d41cc0a970f7..773a5cd38c5a 100644 --- a/drivers/usb/storage/option_ms.c +++ b/drivers/usb/storage/option_ms.c | |||
| @@ -118,6 +118,9 @@ static int option_inquiry(struct us_data *us) | |||
| 118 | 118 | ||
| 119 | result = memcmp(buffer+8, "Option", 6); | 119 | result = memcmp(buffer+8, "Option", 6); |
| 120 | 120 | ||
| 121 | if (result != 0) | ||
| 122 | result = memcmp(buffer+8, "ZCOPTION", 8); | ||
| 123 | |||
| 121 | /* Read the CSW */ | 124 | /* Read the CSW */ |
| 122 | usb_stor_bulk_transfer_buf(us, | 125 | usb_stor_bulk_transfer_buf(us, |
| 123 | us->recv_bulk_pipe, | 126 | us->recv_bulk_pipe, |
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 559f8784acf3..9052bcb4f528 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
| @@ -501,7 +501,7 @@ int hwarc_filter_event_WUSB_0100(struct uwb_rc *rc, struct uwb_rceb **header, | |||
| 501 | int result = -ENOANO; | 501 | int result = -ENOANO; |
| 502 | struct uwb_rceb *rceb = *header; | 502 | struct uwb_rceb *rceb = *header; |
| 503 | int event = le16_to_cpu(rceb->wEvent); | 503 | int event = le16_to_cpu(rceb->wEvent); |
| 504 | size_t event_size; | 504 | ssize_t event_size; |
| 505 | size_t core_size, offset; | 505 | size_t core_size, offset; |
| 506 | 506 | ||
| 507 | if (rceb->bEventType != UWB_RC_CET_GENERAL) | 507 | if (rceb->bEventType != UWB_RC_CET_GENERAL) |
diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c index cd2035768b47..86a853b84119 100644 --- a/drivers/uwb/wlp/txrx.c +++ b/drivers/uwb/wlp/txrx.c | |||
| @@ -326,7 +326,7 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, | |||
| 326 | int result = -EINVAL; | 326 | int result = -EINVAL; |
| 327 | struct ethhdr *eth_hdr = (void *) skb->data; | 327 | struct ethhdr *eth_hdr = (void *) skb->data; |
| 328 | 328 | ||
| 329 | if (is_broadcast_ether_addr(eth_hdr->h_dest)) { | 329 | if (is_multicast_ether_addr(eth_hdr->h_dest)) { |
| 330 | result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); | 330 | result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); |
| 331 | if (result < 0) { | 331 | if (result < 0) { |
| 332 | if (printk_ratelimit()) | 332 | if (printk_ratelimit()) |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d6d65ef85f54..3b54b3940178 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -616,6 +616,8 @@ config FB_STI | |||
| 616 | select FB_CFB_FILLRECT | 616 | select FB_CFB_FILLRECT |
| 617 | select FB_CFB_COPYAREA | 617 | select FB_CFB_COPYAREA |
| 618 | select FB_CFB_IMAGEBLIT | 618 | select FB_CFB_IMAGEBLIT |
| 619 | select STI_CONSOLE | ||
| 620 | select VT | ||
| 619 | default y | 621 | default y |
| 620 | ---help--- | 622 | ---help--- |
| 621 | STI refers to the HP "Standard Text Interface" which is a set of | 623 | STI refers to the HP "Standard Text Interface" which is a set of |
| @@ -1117,12 +1119,13 @@ config FB_CARILLO_RANCH | |||
| 1117 | 1119 | ||
| 1118 | config FB_INTEL | 1120 | config FB_INTEL |
| 1119 | tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" | 1121 | tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" |
| 1120 | depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL | 1122 | depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EMBEDDED |
| 1121 | select FB_MODE_HELPERS | 1123 | select FB_MODE_HELPERS |
| 1122 | select FB_CFB_FILLRECT | 1124 | select FB_CFB_FILLRECT |
| 1123 | select FB_CFB_COPYAREA | 1125 | select FB_CFB_COPYAREA |
| 1124 | select FB_CFB_IMAGEBLIT | 1126 | select FB_CFB_IMAGEBLIT |
| 1125 | select FB_BOOT_VESA_SUPPORT if FB_INTEL = y | 1127 | select FB_BOOT_VESA_SUPPORT if FB_INTEL = y |
| 1128 | depends on !DRM_I915 | ||
| 1126 | help | 1129 | help |
| 1127 | This driver supports the on-board graphics built in to the Intel | 1130 | This driver supports the on-board graphics built in to the Intel |
| 1128 | 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. | 1131 | 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index fb8163d181ab..a21efcd10b78 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
| @@ -226,9 +226,10 @@ static int clcdfb_set_par(struct fb_info *info) | |||
| 226 | clcdfb_enable(fb, regs.cntl); | 226 | clcdfb_enable(fb, regs.cntl); |
| 227 | 227 | ||
| 228 | #ifdef DEBUG | 228 | #ifdef DEBUG |
| 229 | printk(KERN_INFO "CLCD: Registers set to\n" | 229 | printk(KERN_INFO |
| 230 | KERN_INFO " %08x %08x %08x %08x\n" | 230 | "CLCD: Registers set to\n" |
| 231 | KERN_INFO " %08x %08x %08x %08x\n", | 231 | " %08x %08x %08x %08x\n" |
| 232 | " %08x %08x %08x %08x\n", | ||
| 232 | readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), | 233 | readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), |
| 233 | readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), | 234 | readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), |
| 234 | readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), | 235 | readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 018850c116c6..8cd279be74e5 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
| @@ -2405,6 +2405,9 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) | |||
| 2405 | return 0; | 2405 | return 0; |
| 2406 | } | 2406 | } |
| 2407 | 2407 | ||
| 2408 | /* fbhw->encode_fix() must be called with fb_info->mm_lock held | ||
| 2409 | * if it is called after the register_framebuffer() - not a case here | ||
| 2410 | */ | ||
| 2408 | static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | 2411 | static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) |
| 2409 | { | 2412 | { |
| 2410 | struct atafb_par par; | 2413 | struct atafb_par par; |
| @@ -2414,7 +2417,8 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
| 2414 | if (err) | 2417 | if (err) |
| 2415 | return err; | 2418 | return err; |
| 2416 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 2419 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
| 2417 | return fbhw->encode_fix(fix, &par); | 2420 | err = fbhw->encode_fix(fix, &par); |
| 2421 | return err; | ||
| 2418 | } | 2422 | } |
| 2419 | 2423 | ||
| 2420 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) | 2424 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) |
| @@ -2743,7 +2747,9 @@ static int atafb_set_par(struct fb_info *info) | |||
| 2743 | 2747 | ||
| 2744 | /* Decode wanted screen parameters */ | 2748 | /* Decode wanted screen parameters */ |
| 2745 | fbhw->decode_var(&info->var, par); | 2749 | fbhw->decode_var(&info->var, par); |
| 2750 | mutex_lock(&info->mm_lock); | ||
| 2746 | fbhw->encode_fix(&info->fix, par); | 2751 | fbhw->encode_fix(&info->fix, par); |
| 2752 | mutex_unlock(&info->mm_lock); | ||
| 2747 | 2753 | ||
| 2748 | /* Set new videomode */ | 2754 | /* Set new videomode */ |
| 2749 | ata_set_par(par); | 2755 | ata_set_par(par); |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5afd64482f55..da05f0801bb7 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
| @@ -261,6 +261,9 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) | |||
| 261 | /** | 261 | /** |
| 262 | * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory | 262 | * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory |
| 263 | * @sinfo: the frame buffer to allocate memory for | 263 | * @sinfo: the frame buffer to allocate memory for |
| 264 | * | ||
| 265 | * This function is called only from the atmel_lcdfb_probe() | ||
| 266 | * so no locking by fb_info->mm_lock around smem_len setting is needed. | ||
| 264 | */ | 267 | */ |
| 265 | static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | 268 | static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) |
| 266 | { | 269 | { |
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 7691e73823d3..1f39a62f899b 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h | |||
| @@ -187,6 +187,8 @@ struct atyfb_par { | |||
| 187 | int mtrr_reg; | 187 | int mtrr_reg; |
| 188 | #endif | 188 | #endif |
| 189 | u32 mem_cntl; | 189 | u32 mem_cntl; |
| 190 | struct crtc saved_crtc; | ||
| 191 | union aty_pll saved_pll; | ||
| 190 | }; | 192 | }; |
| 191 | 193 | ||
| 192 | /* | 194 | /* |
| @@ -217,6 +219,7 @@ struct atyfb_par { | |||
| 217 | #define M64F_XL_DLL 0x00080000 | 219 | #define M64F_XL_DLL 0x00080000 |
| 218 | #define M64F_MFB_FORCE_4 0x00100000 | 220 | #define M64F_MFB_FORCE_4 0x00100000 |
| 219 | #define M64F_HW_TRIPLE 0x00200000 | 221 | #define M64F_HW_TRIPLE 0x00200000 |
| 222 | #define M64F_XL_MEM 0x00400000 | ||
| 220 | /* | 223 | /* |
| 221 | * Register access | 224 | * Register access |
| 222 | */ | 225 | */ |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 1207c208a30b..63d3739d43a8 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -66,6 +66,8 @@ | |||
| 66 | #include <linux/spinlock.h> | 66 | #include <linux/spinlock.h> |
| 67 | #include <linux/wait.h> | 67 | #include <linux/wait.h> |
| 68 | #include <linux/backlight.h> | 68 | #include <linux/backlight.h> |
| 69 | #include <linux/reboot.h> | ||
| 70 | #include <linux/dmi.h> | ||
| 69 | 71 | ||
| 70 | #include <asm/io.h> | 72 | #include <asm/io.h> |
| 71 | #include <linux/uaccess.h> | 73 | #include <linux/uaccess.h> |
| @@ -249,8 +251,6 @@ static int aty_init(struct fb_info *info); | |||
| 249 | static int store_video_par(char *videopar, unsigned char m64_num); | 251 | static int store_video_par(char *videopar, unsigned char m64_num); |
| 250 | #endif | 252 | #endif |
| 251 | 253 | ||
| 252 | static struct crtc saved_crtc; | ||
| 253 | static union aty_pll saved_pll; | ||
| 254 | static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); | 254 | static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); |
| 255 | 255 | ||
| 256 | static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); | 256 | static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); |
| @@ -261,6 +261,8 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); | |||
| 261 | static int read_aty_sense(const struct atyfb_par *par); | 261 | static int read_aty_sense(const struct atyfb_par *par); |
| 262 | #endif | 262 | #endif |
| 263 | 263 | ||
| 264 | static DEFINE_MUTEX(reboot_lock); | ||
| 265 | static struct fb_info *reboot_info; | ||
| 264 | 266 | ||
| 265 | /* | 267 | /* |
| 266 | * Interface used by the world | 268 | * Interface used by the world |
| @@ -361,8 +363,8 @@ static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, }; | |||
| 361 | #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) | 363 | #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) |
| 362 | #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) | 364 | #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) |
| 363 | 365 | ||
| 364 | #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4) | 366 | #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM) |
| 365 | #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS) | 367 | #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS) |
| 366 | 368 | ||
| 367 | static struct { | 369 | static struct { |
| 368 | u16 pci_id; | 370 | u16 pci_id; |
| @@ -539,6 +541,7 @@ static char ram_edo[] __devinitdata = "EDO"; | |||
| 539 | static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; | 541 | static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; |
| 540 | static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; | 542 | static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; |
| 541 | static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; | 543 | static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; |
| 544 | static char ram_wram[] __devinitdata = "WRAM"; | ||
| 542 | static char ram_off[] __devinitdata = "OFF"; | 545 | static char ram_off[] __devinitdata = "OFF"; |
| 543 | #endif /* CONFIG_FB_ATY_CT */ | 546 | #endif /* CONFIG_FB_ATY_CT */ |
| 544 | 547 | ||
| @@ -553,6 +556,10 @@ static char *aty_gx_ram[8] __devinitdata = { | |||
| 553 | #ifdef CONFIG_FB_ATY_CT | 556 | #ifdef CONFIG_FB_ATY_CT |
| 554 | static char *aty_ct_ram[8] __devinitdata = { | 557 | static char *aty_ct_ram[8] __devinitdata = { |
| 555 | ram_off, ram_dram, ram_edo, ram_edo, | 558 | ram_off, ram_dram, ram_edo, ram_edo, |
| 559 | ram_sdram, ram_sgram, ram_wram, ram_resv | ||
| 560 | }; | ||
| 561 | static char *aty_xl_ram[8] __devinitdata = { | ||
| 562 | ram_off, ram_dram, ram_edo, ram_edo, | ||
| 556 | ram_sdram, ram_sgram, ram_sdram32, ram_resv | 563 | ram_sdram, ram_sgram, ram_sdram32, ram_resv |
| 557 | }; | 564 | }; |
| 558 | #endif /* CONFIG_FB_ATY_CT */ | 565 | #endif /* CONFIG_FB_ATY_CT */ |
| @@ -760,6 +767,17 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) | |||
| 760 | #endif /* CONFIG_FB_ATY_GENERIC_LCD */ | 767 | #endif /* CONFIG_FB_ATY_GENERIC_LCD */ |
| 761 | } | 768 | } |
| 762 | 769 | ||
| 770 | static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp) | ||
| 771 | { | ||
| 772 | u32 line_length = vxres * bpp / 8; | ||
| 773 | |||
| 774 | if (par->ram_type == SGRAM || | ||
| 775 | (!M64_HAS(XL_MEM) && par->ram_type == WRAM)) | ||
| 776 | line_length = (line_length + 63) & ~63; | ||
| 777 | |||
| 778 | return line_length; | ||
| 779 | } | ||
| 780 | |||
| 763 | static int aty_var_to_crtc(const struct fb_info *info, | 781 | static int aty_var_to_crtc(const struct fb_info *info, |
| 764 | const struct fb_var_screeninfo *var, struct crtc *crtc) | 782 | const struct fb_var_screeninfo *var, struct crtc *crtc) |
| 765 | { | 783 | { |
| @@ -769,13 +787,14 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
| 769 | u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; | 787 | u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; |
| 770 | u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; | 788 | u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; |
| 771 | u32 pix_width, dp_pix_width, dp_chain_mask; | 789 | u32 pix_width, dp_pix_width, dp_chain_mask; |
| 790 | u32 line_length; | ||
| 772 | 791 | ||
| 773 | /* input */ | 792 | /* input */ |
| 774 | xres = var->xres; | 793 | xres = (var->xres + 7) & ~7; |
| 775 | yres = var->yres; | 794 | yres = var->yres; |
| 776 | vxres = var->xres_virtual; | 795 | vxres = (var->xres_virtual + 7) & ~7; |
| 777 | vyres = var->yres_virtual; | 796 | vyres = var->yres_virtual; |
| 778 | xoffset = var->xoffset; | 797 | xoffset = (var->xoffset + 7) & ~7; |
| 779 | yoffset = var->yoffset; | 798 | yoffset = var->yoffset; |
| 780 | bpp = var->bits_per_pixel; | 799 | bpp = var->bits_per_pixel; |
| 781 | if (bpp == 16) | 800 | if (bpp == 16) |
| @@ -827,7 +846,9 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
| 827 | } else | 846 | } else |
| 828 | FAIL("invalid bpp"); | 847 | FAIL("invalid bpp"); |
| 829 | 848 | ||
| 830 | if (vxres * vyres * bpp / 8 > info->fix.smem_len) | 849 | line_length = calc_line_length(par, vxres, bpp); |
| 850 | |||
| 851 | if (vyres * line_length > info->fix.smem_len) | ||
| 831 | FAIL("not enough video RAM"); | 852 | FAIL("not enough video RAM"); |
| 832 | 853 | ||
| 833 | h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; | 854 | h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; |
| @@ -969,7 +990,9 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
| 969 | crtc->xoffset = xoffset; | 990 | crtc->xoffset = xoffset; |
| 970 | crtc->yoffset = yoffset; | 991 | crtc->yoffset = yoffset; |
| 971 | crtc->bpp = bpp; | 992 | crtc->bpp = bpp; |
| 972 | crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); | 993 | crtc->off_pitch = |
| 994 | ((yoffset * line_length + xoffset * bpp / 8) / 8) | | ||
| 995 | ((line_length / bpp) << 22); | ||
| 973 | crtc->vline_crnt_vline = 0; | 996 | crtc->vline_crnt_vline = 0; |
| 974 | 997 | ||
| 975 | crtc->h_tot_disp = h_total | (h_disp<<16); | 998 | crtc->h_tot_disp = h_total | (h_disp<<16); |
| @@ -1394,7 +1417,9 @@ static int atyfb_set_par(struct fb_info *info) | |||
| 1394 | } | 1417 | } |
| 1395 | aty_st_8(DAC_MASK, 0xff, par); | 1418 | aty_st_8(DAC_MASK, 0xff, par); |
| 1396 | 1419 | ||
| 1397 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8; | 1420 | info->fix.line_length = calc_line_length(par, var->xres_virtual, |
| 1421 | var->bits_per_pixel); | ||
| 1422 | |||
| 1398 | info->fix.visual = var->bits_per_pixel <= 8 ? | 1423 | info->fix.visual = var->bits_per_pixel <= 8 ? |
| 1399 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 1424 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
| 1400 | 1425 | ||
| @@ -1505,10 +1530,12 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info) | |||
| 1505 | { | 1530 | { |
| 1506 | u32 xoffset = info->var.xoffset; | 1531 | u32 xoffset = info->var.xoffset; |
| 1507 | u32 yoffset = info->var.yoffset; | 1532 | u32 yoffset = info->var.yoffset; |
| 1508 | u32 vxres = par->crtc.vxres; | 1533 | u32 line_length = info->fix.line_length; |
| 1509 | u32 bpp = info->var.bits_per_pixel; | 1534 | u32 bpp = info->var.bits_per_pixel; |
| 1510 | 1535 | ||
| 1511 | par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19); | 1536 | par->crtc.off_pitch = |
| 1537 | ((yoffset * line_length + xoffset * bpp / 8) / 8) | | ||
| 1538 | ((line_length / bpp) << 22); | ||
| 1512 | } | 1539 | } |
| 1513 | 1540 | ||
| 1514 | 1541 | ||
| @@ -2201,7 +2228,7 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) | |||
| 2201 | const int *refresh_tbl; | 2228 | const int *refresh_tbl; |
| 2202 | int i, size; | 2229 | int i, size; |
| 2203 | 2230 | ||
| 2204 | if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { | 2231 | if (M64_HAS(XL_MEM)) { |
| 2205 | refresh_tbl = ragexl_tbl; | 2232 | refresh_tbl = ragexl_tbl; |
| 2206 | size = ARRAY_SIZE(ragexl_tbl); | 2233 | size = ARRAY_SIZE(ragexl_tbl); |
| 2207 | } else { | 2234 | } else { |
| @@ -2335,7 +2362,10 @@ static int __devinit aty_init(struct fb_info *info) | |||
| 2335 | par->pll_ops = &aty_pll_ct; | 2362 | par->pll_ops = &aty_pll_ct; |
| 2336 | par->bus_type = PCI; | 2363 | par->bus_type = PCI; |
| 2337 | par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); | 2364 | par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); |
| 2338 | ramname = aty_ct_ram[par->ram_type]; | 2365 | if (M64_HAS(XL_MEM)) |
| 2366 | ramname = aty_xl_ram[par->ram_type]; | ||
| 2367 | else | ||
| 2368 | ramname = aty_ct_ram[par->ram_type]; | ||
| 2339 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ | 2369 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ |
| 2340 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) | 2370 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) |
| 2341 | par->pll_limits.mclk = 63; | 2371 | par->pll_limits.mclk = 63; |
| @@ -2390,9 +2420,9 @@ static int __devinit aty_init(struct fb_info *info) | |||
| 2390 | #endif /* CONFIG_FB_ATY_CT */ | 2420 | #endif /* CONFIG_FB_ATY_CT */ |
| 2391 | 2421 | ||
| 2392 | /* save previous video mode */ | 2422 | /* save previous video mode */ |
| 2393 | aty_get_crtc(par, &saved_crtc); | 2423 | aty_get_crtc(par, &par->saved_crtc); |
| 2394 | if(par->pll_ops->get_pll) | 2424 | if(par->pll_ops->get_pll) |
| 2395 | par->pll_ops->get_pll(info, &saved_pll); | 2425 | par->pll_ops->get_pll(info, &par->saved_pll); |
| 2396 | 2426 | ||
| 2397 | par->mem_cntl = aty_ld_le32(MEM_CNTL, par); | 2427 | par->mem_cntl = aty_ld_le32(MEM_CNTL, par); |
| 2398 | gtb_memsize = M64_HAS(GTB_DSP); | 2428 | gtb_memsize = M64_HAS(GTB_DSP); |
| @@ -2667,8 +2697,8 @@ static int __devinit aty_init(struct fb_info *info) | |||
| 2667 | 2697 | ||
| 2668 | aty_init_exit: | 2698 | aty_init_exit: |
| 2669 | /* restore video mode */ | 2699 | /* restore video mode */ |
| 2670 | aty_set_crtc(par, &saved_crtc); | 2700 | aty_set_crtc(par, &par->saved_crtc); |
| 2671 | par->pll_ops->set_pll(info, &saved_pll); | 2701 | par->pll_ops->set_pll(info, &par->saved_pll); |
| 2672 | 2702 | ||
| 2673 | #ifdef CONFIG_MTRR | 2703 | #ifdef CONFIG_MTRR |
| 2674 | if (par->mtrr_reg >= 0) { | 2704 | if (par->mtrr_reg >= 0) { |
| @@ -3502,6 +3532,11 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
| 3502 | par->mmap_map[1].prot_flag = _PAGE_E; | 3532 | par->mmap_map[1].prot_flag = _PAGE_E; |
| 3503 | #endif /* __sparc__ */ | 3533 | #endif /* __sparc__ */ |
| 3504 | 3534 | ||
| 3535 | mutex_lock(&reboot_lock); | ||
| 3536 | if (!reboot_info) | ||
| 3537 | reboot_info = info; | ||
| 3538 | mutex_unlock(&reboot_lock); | ||
| 3539 | |||
| 3505 | return 0; | 3540 | return 0; |
| 3506 | 3541 | ||
| 3507 | err_release_io: | 3542 | err_release_io: |
| @@ -3614,8 +3649,8 @@ static void __devexit atyfb_remove(struct fb_info *info) | |||
| 3614 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 3649 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
| 3615 | 3650 | ||
| 3616 | /* restore video mode */ | 3651 | /* restore video mode */ |
| 3617 | aty_set_crtc(par, &saved_crtc); | 3652 | aty_set_crtc(par, &par->saved_crtc); |
| 3618 | par->pll_ops->set_pll(info, &saved_pll); | 3653 | par->pll_ops->set_pll(info, &par->saved_pll); |
| 3619 | 3654 | ||
| 3620 | unregister_framebuffer(info); | 3655 | unregister_framebuffer(info); |
| 3621 | 3656 | ||
| @@ -3661,6 +3696,11 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev) | |||
| 3661 | { | 3696 | { |
| 3662 | struct fb_info *info = pci_get_drvdata(pdev); | 3697 | struct fb_info *info = pci_get_drvdata(pdev); |
| 3663 | 3698 | ||
| 3699 | mutex_lock(&reboot_lock); | ||
| 3700 | if (reboot_info == info) | ||
| 3701 | reboot_info = NULL; | ||
| 3702 | mutex_unlock(&reboot_lock); | ||
| 3703 | |||
| 3664 | atyfb_remove(info); | 3704 | atyfb_remove(info); |
| 3665 | } | 3705 | } |
| 3666 | 3706 | ||
| @@ -3808,6 +3848,56 @@ static int __init atyfb_setup(char *options) | |||
| 3808 | } | 3848 | } |
| 3809 | #endif /* MODULE */ | 3849 | #endif /* MODULE */ |
| 3810 | 3850 | ||
| 3851 | static int atyfb_reboot_notify(struct notifier_block *nb, | ||
| 3852 | unsigned long code, void *unused) | ||
| 3853 | { | ||
| 3854 | struct atyfb_par *par; | ||
| 3855 | |||
| 3856 | if (code != SYS_RESTART) | ||
| 3857 | return NOTIFY_DONE; | ||
| 3858 | |||
| 3859 | mutex_lock(&reboot_lock); | ||
| 3860 | |||
| 3861 | if (!reboot_info) | ||
| 3862 | goto out; | ||
| 3863 | |||
| 3864 | if (!lock_fb_info(reboot_info)) | ||
| 3865 | goto out; | ||
| 3866 | |||
| 3867 | par = reboot_info->par; | ||
| 3868 | |||
| 3869 | /* | ||
| 3870 | * HP OmniBook 500's BIOS doesn't like the state of the | ||
| 3871 | * hardware after atyfb has been used. Restore the hardware | ||
| 3872 | * to the original state to allow successful reboots. | ||
| 3873 | */ | ||
| 3874 | aty_set_crtc(par, &par->saved_crtc); | ||
| 3875 | par->pll_ops->set_pll(reboot_info, &par->saved_pll); | ||
| 3876 | |||
| 3877 | unlock_fb_info(reboot_info); | ||
| 3878 | out: | ||
| 3879 | mutex_unlock(&reboot_lock); | ||
| 3880 | |||
| 3881 | return NOTIFY_DONE; | ||
| 3882 | } | ||
| 3883 | |||
| 3884 | static struct notifier_block atyfb_reboot_notifier = { | ||
| 3885 | .notifier_call = atyfb_reboot_notify, | ||
| 3886 | }; | ||
| 3887 | |||
| 3888 | static const struct dmi_system_id atyfb_reboot_ids[] = { | ||
| 3889 | { | ||
| 3890 | .ident = "HP OmniBook 500", | ||
| 3891 | .matches = { | ||
| 3892 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 3893 | DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), | ||
| 3894 | DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"), | ||
| 3895 | }, | ||
| 3896 | }, | ||
| 3897 | |||
| 3898 | { } | ||
| 3899 | }; | ||
| 3900 | |||
| 3811 | static int __init atyfb_init(void) | 3901 | static int __init atyfb_init(void) |
| 3812 | { | 3902 | { |
| 3813 | int err1 = 1, err2 = 1; | 3903 | int err1 = 1, err2 = 1; |
| @@ -3826,11 +3916,20 @@ static int __init atyfb_init(void) | |||
| 3826 | err2 = atyfb_atari_probe(); | 3916 | err2 = atyfb_atari_probe(); |
| 3827 | #endif | 3917 | #endif |
| 3828 | 3918 | ||
| 3829 | return (err1 && err2) ? -ENODEV : 0; | 3919 | if (err1 && err2) |
| 3920 | return -ENODEV; | ||
| 3921 | |||
| 3922 | if (dmi_check_system(atyfb_reboot_ids)) | ||
| 3923 | register_reboot_notifier(&atyfb_reboot_notifier); | ||
| 3924 | |||
| 3925 | return 0; | ||
| 3830 | } | 3926 | } |
| 3831 | 3927 | ||
| 3832 | static void __exit atyfb_exit(void) | 3928 | static void __exit atyfb_exit(void) |
| 3833 | { | 3929 | { |
| 3930 | if (dmi_check_system(atyfb_reboot_ids)) | ||
| 3931 | unregister_reboot_notifier(&atyfb_reboot_notifier); | ||
| 3932 | |||
| 3834 | #ifdef CONFIG_PCI | 3933 | #ifdef CONFIG_PCI |
| 3835 | pci_unregister_driver(&atyfb_driver); | 3934 | pci_unregister_driver(&atyfb_driver); |
| 3836 | #endif | 3935 | #endif |
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index 0cc9724e61a2..51fcc0a2c94a 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c | |||
| @@ -63,14 +63,17 @@ static void reset_GTC_3D_engine(const struct atyfb_par *par) | |||
| 63 | void aty_init_engine(struct atyfb_par *par, struct fb_info *info) | 63 | void aty_init_engine(struct atyfb_par *par, struct fb_info *info) |
| 64 | { | 64 | { |
| 65 | u32 pitch_value; | 65 | u32 pitch_value; |
| 66 | u32 vxres; | ||
| 66 | 67 | ||
| 67 | /* determine modal information from global mode structure */ | 68 | /* determine modal information from global mode structure */ |
| 68 | pitch_value = info->var.xres_virtual; | 69 | pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8); |
| 70 | vxres = info->var.xres_virtual; | ||
| 69 | 71 | ||
| 70 | if (info->var.bits_per_pixel == 24) { | 72 | if (info->var.bits_per_pixel == 24) { |
| 71 | /* In 24 bpp, the engine is in 8 bpp - this requires that all */ | 73 | /* In 24 bpp, the engine is in 8 bpp - this requires that all */ |
| 72 | /* horizontal coordinates and widths must be adjusted */ | 74 | /* horizontal coordinates and widths must be adjusted */ |
| 73 | pitch_value *= 3; | 75 | pitch_value *= 3; |
| 76 | vxres *= 3; | ||
| 74 | } | 77 | } |
| 75 | 78 | ||
| 76 | /* On GTC (RagePro), we need to reset the 3D engine before */ | 79 | /* On GTC (RagePro), we need to reset the 3D engine before */ |
| @@ -133,7 +136,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info) | |||
| 133 | aty_st_le32(SC_LEFT, 0, par); | 136 | aty_st_le32(SC_LEFT, 0, par); |
| 134 | aty_st_le32(SC_TOP, 0, par); | 137 | aty_st_le32(SC_TOP, 0, par); |
| 135 | aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); | 138 | aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); |
| 136 | aty_st_le32(SC_RIGHT, pitch_value - 1, par); | 139 | aty_st_le32(SC_RIGHT, vxres - 1, par); |
| 137 | 140 | ||
| 138 | /* set background color to minimum value (usually BLACK) */ | 141 | /* set background color to minimum value (usually BLACK) */ |
| 139 | aty_st_le32(DP_BKGD_CLR, 0, par); | 142 | aty_st_le32(DP_BKGD_CLR, 0, par); |
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 1dae7f8f3c6b..51422fc4f606 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c | |||
| @@ -356,7 +356,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi) | |||
| 356 | lcd->power = FB_BLANK_POWERDOWN; | 356 | lcd->power = FB_BLANK_POWERDOWN; |
| 357 | lcd->mode = MODE_VGA; /* default to VGA */ | 357 | lcd->mode = MODE_VGA; /* default to VGA */ |
| 358 | 358 | ||
| 359 | lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL)); | 359 | lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL); |
| 360 | if (lcd->buf == NULL) { | 360 | if (lcd->buf == NULL) { |
| 361 | kfree(lcd); | 361 | kfree(lcd); |
| 362 | return -ENOMEM; | 362 | return -ENOMEM; |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 7bad24ed04ef..108b89e09a80 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Cobalt server LCD frame buffer driver. | 2 | * Cobalt server LCD frame buffer driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.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 |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index f8a09bf8d0cd..a85c818be945 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/compat.h> | 16 | #include <linux/compat.h> |
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <linux/smp_lock.h> | ||
| 20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 21 | #include <linux/major.h> | 20 | #include <linux/major.h> |
| 22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| @@ -1310,8 +1309,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 1310 | 1309 | ||
| 1311 | static int | 1310 | static int |
| 1312 | fb_mmap(struct file *file, struct vm_area_struct * vma) | 1311 | fb_mmap(struct file *file, struct vm_area_struct * vma) |
| 1313 | __acquires(&info->lock) | ||
| 1314 | __releases(&info->lock) | ||
| 1315 | { | 1312 | { |
| 1316 | int fbidx = iminor(file->f_path.dentry->d_inode); | 1313 | int fbidx = iminor(file->f_path.dentry->d_inode); |
| 1317 | struct fb_info *info = registered_fb[fbidx]; | 1314 | struct fb_info *info = registered_fb[fbidx]; |
| @@ -1325,16 +1322,14 @@ __releases(&info->lock) | |||
| 1325 | off = vma->vm_pgoff << PAGE_SHIFT; | 1322 | off = vma->vm_pgoff << PAGE_SHIFT; |
| 1326 | if (!fb) | 1323 | if (!fb) |
| 1327 | return -ENODEV; | 1324 | return -ENODEV; |
| 1325 | mutex_lock(&info->mm_lock); | ||
| 1328 | if (fb->fb_mmap) { | 1326 | if (fb->fb_mmap) { |
| 1329 | int res; | 1327 | int res; |
| 1330 | mutex_lock(&info->lock); | ||
| 1331 | res = fb->fb_mmap(info, vma); | 1328 | res = fb->fb_mmap(info, vma); |
| 1332 | mutex_unlock(&info->lock); | 1329 | mutex_unlock(&info->mm_lock); |
| 1333 | return res; | 1330 | return res; |
| 1334 | } | 1331 | } |
| 1335 | 1332 | ||
| 1336 | mutex_lock(&info->lock); | ||
| 1337 | |||
| 1338 | /* frame buffer memory */ | 1333 | /* frame buffer memory */ |
| 1339 | start = info->fix.smem_start; | 1334 | start = info->fix.smem_start; |
| 1340 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); | 1335 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); |
| @@ -1342,13 +1337,13 @@ __releases(&info->lock) | |||
| 1342 | /* memory mapped io */ | 1337 | /* memory mapped io */ |
| 1343 | off -= len; | 1338 | off -= len; |
| 1344 | if (info->var.accel_flags) { | 1339 | if (info->var.accel_flags) { |
| 1345 | mutex_unlock(&info->lock); | 1340 | mutex_unlock(&info->mm_lock); |
| 1346 | return -EINVAL; | 1341 | return -EINVAL; |
| 1347 | } | 1342 | } |
| 1348 | start = info->fix.mmio_start; | 1343 | start = info->fix.mmio_start; |
| 1349 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); | 1344 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); |
| 1350 | } | 1345 | } |
| 1351 | mutex_unlock(&info->lock); | 1346 | mutex_unlock(&info->mm_lock); |
| 1352 | start &= PAGE_MASK; | 1347 | start &= PAGE_MASK; |
| 1353 | if ((vma->vm_end - vma->vm_start + off) > len) | 1348 | if ((vma->vm_end - vma->vm_start + off) > len) |
| 1354 | return -EINVAL; | 1349 | return -EINVAL; |
| @@ -1518,6 +1513,7 @@ register_framebuffer(struct fb_info *fb_info) | |||
| 1518 | break; | 1513 | break; |
| 1519 | fb_info->node = i; | 1514 | fb_info->node = i; |
| 1520 | mutex_init(&fb_info->lock); | 1515 | mutex_init(&fb_info->lock); |
| 1516 | mutex_init(&fb_info->mm_lock); | ||
| 1521 | 1517 | ||
| 1522 | fb_info->dev = device_create(fb_class, fb_info->device, | 1518 | fb_info->dev = device_create(fb_class, fb_info->device, |
| 1523 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); | 1519 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index f153c581cbd7..72d68b3dc478 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
| @@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info) | |||
| 750 | static int map_video_memory(struct fb_info *info) | 750 | static int map_video_memory(struct fb_info *info) |
| 751 | { | 751 | { |
| 752 | phys_addr_t phys; | 752 | phys_addr_t phys; |
| 753 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; | ||
| 753 | 754 | ||
| 754 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | 755 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); |
| 755 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | 756 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); |
| 756 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | 757 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); |
| 758 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); | ||
| 757 | 759 | ||
| 758 | info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; | 760 | info->screen_base = fsl_diu_alloc(smem_len, &phys); |
| 759 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); | ||
| 760 | info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); | ||
| 761 | if (info->screen_base == NULL) { | 761 | if (info->screen_base == NULL) { |
| 762 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 762 | printk(KERN_ERR "Unable to allocate fb memory\n"); |
| 763 | return -ENOMEM; | 763 | return -ENOMEM; |
| 764 | } | 764 | } |
| 765 | mutex_lock(&info->mm_lock); | ||
| 765 | info->fix.smem_start = (unsigned long) phys; | 766 | info->fix.smem_start = (unsigned long) phys; |
| 767 | info->fix.smem_len = smem_len; | ||
| 768 | mutex_unlock(&info->mm_lock); | ||
| 766 | info->screen_size = info->fix.smem_len; | 769 | info->screen_size = info->fix.smem_len; |
| 767 | 770 | ||
| 768 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | 771 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", |
| 769 | info->fix.smem_start, | 772 | info->fix.smem_start, info->fix.smem_len); |
| 770 | info->fix.smem_len); | ||
| 771 | pr_debug("screen base %p\n", info->screen_base); | 773 | pr_debug("screen base %p\n", info->screen_base); |
| 772 | 774 | ||
| 773 | return 0; | 775 | return 0; |
| @@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info) | |||
| 776 | static void unmap_video_memory(struct fb_info *info) | 778 | static void unmap_video_memory(struct fb_info *info) |
| 777 | { | 779 | { |
| 778 | fsl_diu_free(info->screen_base, info->fix.smem_len); | 780 | fsl_diu_free(info->screen_base, info->fix.smem_len); |
| 781 | mutex_lock(&info->mm_lock); | ||
| 779 | info->screen_base = NULL; | 782 | info->screen_base = NULL; |
| 780 | info->fix.smem_start = 0; | 783 | info->fix.smem_start = 0; |
| 781 | info->fix.smem_len = 0; | 784 | info->fix.smem_len = 0; |
| 785 | mutex_unlock(&info->mm_lock); | ||
| 782 | } | 786 | } |
| 783 | 787 | ||
| 784 | /* | 788 | /* |
| @@ -1219,12 +1223,6 @@ static int __devinit install_fb(struct fb_info *info) | |||
| 1219 | return -EINVAL; | 1223 | return -EINVAL; |
| 1220 | } | 1224 | } |
| 1221 | 1225 | ||
| 1222 | if (fsl_diu_set_par(info)) { | ||
| 1223 | printk(KERN_ERR "fb_set_par failed"); | ||
| 1224 | fb_dealloc_cmap(&info->cmap); | ||
| 1225 | return -EINVAL; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | if (register_framebuffer(info) < 0) { | 1226 | if (register_framebuffer(info) < 0) { |
| 1229 | printk(KERN_ERR "register_framebuffer failed"); | 1227 | printk(KERN_ERR "register_framebuffer failed"); |
| 1230 | unmap_video_memory(info); | 1228 | unmap_video_memory(info); |
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 020db7fc9153..e7116a6d82d3 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c | |||
| @@ -44,9 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = { | |||
| 44 | .accel = FB_ACCEL_NONE, | 44 | .accel = FB_ACCEL_NONE, |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | static u32 pseudo_palette[16]; | ||
| 48 | static struct fb_info fb_info; | ||
| 49 | |||
| 50 | static inline void hitfb_accel_wait(void) | 47 | static inline void hitfb_accel_wait(void) |
| 51 | { | 48 | { |
| 52 | while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; | 49 | while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; |
| @@ -331,6 +328,8 @@ static struct fb_ops hitfb_ops = { | |||
| 331 | static int __init hitfb_probe(struct platform_device *dev) | 328 | static int __init hitfb_probe(struct platform_device *dev) |
| 332 | { | 329 | { |
| 333 | unsigned short lcdclor, ldr3, ldvndr; | 330 | unsigned short lcdclor, ldr3, ldvndr; |
| 331 | struct fb_info *info; | ||
| 332 | int ret; | ||
| 334 | 333 | ||
| 335 | if (fb_get_options("hitfb", NULL)) | 334 | if (fb_get_options("hitfb", NULL)) |
| 336 | return -ENODEV; | 335 | return -ENODEV; |
| @@ -384,32 +383,53 @@ static int __init hitfb_probe(struct platform_device *dev) | |||
| 384 | break; | 383 | break; |
| 385 | } | 384 | } |
| 386 | 385 | ||
| 387 | fb_info.fbops = &hitfb_ops; | 386 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); |
| 388 | fb_info.var = hitfb_var; | 387 | if (unlikely(!info)) |
| 389 | fb_info.fix = hitfb_fix; | 388 | return -ENOMEM; |
| 390 | fb_info.pseudo_palette = pseudo_palette; | 389 | |
| 391 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | | 390 | info->fbops = &hitfb_ops; |
| 391 | info->var = hitfb_var; | ||
| 392 | info->fix = hitfb_fix; | ||
| 393 | info->pseudo_palette = info->par; | ||
| 394 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | | ||
| 392 | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; | 395 | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; |
| 393 | 396 | ||
| 394 | fb_info.screen_base = (void *)hitfb_fix.smem_start; | 397 | info->screen_base = (void *)hitfb_fix.smem_start; |
| 395 | 398 | ||
| 396 | fb_alloc_cmap(&fb_info.cmap, 256, 0); | 399 | ret = fb_alloc_cmap(&info->cmap, 256, 0); |
| 400 | if (unlikely(ret < 0)) | ||
| 401 | goto err_fb; | ||
| 397 | 402 | ||
| 398 | if (register_framebuffer(&fb_info) < 0) | 403 | ret = register_framebuffer(info); |
| 399 | return -EINVAL; | 404 | if (unlikely(ret < 0)) |
| 405 | goto err; | ||
| 406 | |||
| 407 | platform_set_drvdata(dev, info); | ||
| 400 | 408 | ||
| 401 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 409 | printk(KERN_INFO "fb%d: %s frame buffer device\n", |
| 402 | fb_info.node, fb_info.fix.id); | 410 | info->node, info->fix.id); |
| 411 | |||
| 403 | return 0; | 412 | return 0; |
| 413 | |||
| 414 | err: | ||
| 415 | fb_dealloc_cmap(&info->cmap); | ||
| 416 | err_fb: | ||
| 417 | framebuffer_release(info); | ||
| 418 | return ret; | ||
| 404 | } | 419 | } |
| 405 | 420 | ||
| 406 | static int __exit hitfb_remove(struct platform_device *dev) | 421 | static int __exit hitfb_remove(struct platform_device *dev) |
| 407 | { | 422 | { |
| 408 | return unregister_framebuffer(&fb_info); | 423 | struct fb_info *info = platform_get_drvdata(dev); |
| 424 | |||
| 425 | unregister_framebuffer(info); | ||
| 426 | fb_dealloc_cmap(&info->cmap); | ||
| 427 | framebuffer_release(info); | ||
| 428 | |||
| 429 | return 0; | ||
| 409 | } | 430 | } |
| 410 | 431 | ||
| 411 | #ifdef CONFIG_PM | 432 | static int hitfb_suspend(struct device *dev) |
| 412 | static int hitfb_suspend(struct platform_device *dev, pm_message_t state) | ||
| 413 | { | 433 | { |
| 414 | u16 v; | 434 | u16 v; |
| 415 | 435 | ||
| @@ -421,7 +441,7 @@ static int hitfb_suspend(struct platform_device *dev, pm_message_t state) | |||
| 421 | return 0; | 441 | return 0; |
| 422 | } | 442 | } |
| 423 | 443 | ||
| 424 | static int hitfb_resume(struct platform_device *dev) | 444 | static int hitfb_resume(struct device *dev) |
| 425 | { | 445 | { |
| 426 | u16 v; | 446 | u16 v; |
| 427 | 447 | ||
| @@ -435,17 +455,19 @@ static int hitfb_resume(struct platform_device *dev) | |||
| 435 | 455 | ||
| 436 | return 0; | 456 | return 0; |
| 437 | } | 457 | } |
| 438 | #endif | 458 | |
| 459 | static struct dev_pm_ops hitfb_dev_pm_ops = { | ||
| 460 | .suspend = hitfb_suspend, | ||
| 461 | .resume = hitfb_resume, | ||
| 462 | }; | ||
| 439 | 463 | ||
| 440 | static struct platform_driver hitfb_driver = { | 464 | static struct platform_driver hitfb_driver = { |
| 441 | .probe = hitfb_probe, | 465 | .probe = hitfb_probe, |
| 442 | .remove = __exit_p(hitfb_remove), | 466 | .remove = __exit_p(hitfb_remove), |
| 443 | #ifdef CONFIG_PM | ||
| 444 | .suspend = hitfb_suspend, | ||
| 445 | .resume = hitfb_resume, | ||
| 446 | #endif | ||
| 447 | .driver = { | 467 | .driver = { |
| 448 | .name = "hitfb", | 468 | .name = "hitfb", |
| 469 | .owner = THIS_MODULE, | ||
| 470 | .pm = &hitfb_dev_pm_ops, | ||
| 449 | }, | 471 | }, |
| 450 | }; | 472 | }; |
| 451 | 473 | ||
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 2e940199fc89..5743ea25e818 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
| @@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
| 1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
| 1091 | 1091 | ||
| 1092 | strcpy(fix->id, "I810"); | 1092 | strcpy(fix->id, "I810"); |
| 1093 | mutex_lock(&info->mm_lock); | ||
| 1093 | fix->smem_start = par->fb.physical; | 1094 | fix->smem_start = par->fb.physical; |
| 1094 | fix->smem_len = par->fb.size; | 1095 | fix->smem_len = par->fb.size; |
| 1096 | mutex_unlock(&info->mm_lock); | ||
| 1095 | fix->type = FB_TYPE_PACKED_PIXELS; | 1097 | fix->type = FB_TYPE_PACKED_PIXELS; |
| 1096 | fix->type_aux = 0; | 1098 | fix->type_aux = 0; |
| 1097 | fix->xpanstep = 8; | 1099 | fix->xpanstep = 8; |
| @@ -2058,8 +2060,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
| 2058 | 2060 | ||
| 2059 | fb_var_to_videomode(&mode, &info->var); | 2061 | fb_var_to_videomode(&mode, &info->var); |
| 2060 | fb_add_videomode(&mode, &info->modelist); | 2062 | fb_add_videomode(&mode, &info->modelist); |
| 2061 | encode_fix(&info->fix, info); | 2063 | |
| 2062 | |||
| 2063 | i810fb_init_ringbuffer(info); | 2064 | i810fb_init_ringbuffer(info); |
| 2064 | err = register_framebuffer(info); | 2065 | err = register_framebuffer(info); |
| 2065 | 2066 | ||
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 0ce3b0a89798..a74e5da17aa0 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c | |||
| @@ -454,9 +454,9 @@ static void DAC1064_restore_2(WPMINFO2) { | |||
| 454 | dprintk(KERN_DEBUG "DAC1064regs "); | 454 | dprintk(KERN_DEBUG "DAC1064regs "); |
| 455 | for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { | 455 | for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { |
| 456 | dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); | 456 | dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); |
| 457 | if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); | 457 | if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); |
| 458 | } | 458 | } |
| 459 | dprintk("\n" KERN_DEBUG "DAC1064clk "); | 459 | dprintk(KERN_DEBUG "DAC1064clk "); |
| 460 | for (i = 0; i < 6; i++) | 460 | for (i = 0; i < 6; i++) |
| 461 | dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); | 461 | dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); |
| 462 | dprintk("\n"); | 462 | dprintk("\n"); |
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 13524821e242..4e825112a601 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c | |||
| @@ -651,9 +651,9 @@ static void Ti3026_restore(WPMINFO2) { | |||
| 651 | dprintk(KERN_DEBUG "3026DACregs "); | 651 | dprintk(KERN_DEBUG "3026DACregs "); |
| 652 | for (i = 0; i < 21; i++) { | 652 | for (i = 0; i < 21; i++) { |
| 653 | dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); | 653 | dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); |
| 654 | if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); | 654 | if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); |
| 655 | } | 655 | } |
| 656 | dprintk("\n" KERN_DEBUG "DACclk "); | 656 | dprintk(KERN_DEBUG "DACclk "); |
| 657 | for (i = 0; i < 6; i++) | 657 | for (i = 0; i < 6; i++) |
| 658 | dprintk("C%02X=%02X ", i, hw->DACclk[i]); | 658 | dprintk("C%02X=%02X ", i, hw->DACclk[i]); |
| 659 | dprintk("\n"); | 659 | dprintk("\n"); |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 8e7a275df50c..0c1049b308bf 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
| @@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2) | |||
| 724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; | 724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; |
| 725 | DBG(__func__) | 725 | DBG(__func__) |
| 726 | 726 | ||
| 727 | mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
| 727 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); | 728 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); |
| 728 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); | 729 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); |
| 730 | mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
| 729 | } | 731 | } |
| 730 | 732 | ||
| 731 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 733 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
| @@ -1874,7 +1876,6 @@ static int initMatrox2(WPMINFO struct board* b){ | |||
| 1874 | } | 1876 | } |
| 1875 | matroxfb_init_fix(PMINFO2); | 1877 | matroxfb_init_fix(PMINFO2); |
| 1876 | ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); | 1878 | ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); |
| 1877 | matroxfb_update_fix(PMINFO2); | ||
| 1878 | /* Normalize values (namely yres_virtual) */ | 1879 | /* Normalize values (namely yres_virtual) */ |
| 1879 | matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); | 1880 | matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); |
| 1880 | /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over | 1881 | /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over |
| @@ -2081,6 +2082,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm | |||
| 2081 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); | 2082 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); |
| 2082 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); | 2083 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); |
| 2083 | init_rwsem(&ACCESS_FBINFO(altout.lock)); | 2084 | init_rwsem(&ACCESS_FBINFO(altout.lock)); |
| 2085 | mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); | ||
| 2084 | ACCESS_FBINFO(irq_flags) = 0; | 2086 | ACCESS_FBINFO(irq_flags) = 0; |
| 2085 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); | 2087 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); |
| 2086 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); | 2088 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); |
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 7ac4c5f6145d..ebcb5c6b4962 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c | |||
| @@ -289,7 +289,12 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { | |||
| 289 | #undef m2info | 289 | #undef m2info |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { | 292 | /* |
| 293 | * This function is called before the register_framebuffer so | ||
| 294 | * no locking is needed. | ||
| 295 | */ | ||
| 296 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) | ||
| 297 | { | ||
| 293 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; | 298 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; |
| 294 | 299 | ||
| 295 | strcpy(fix->id, "MATROX DH"); | 300 | strcpy(fix->id, "MATROX DH"); |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index b7af5256e887..f8778cde2183 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
| @@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp) | |||
| 669 | } | 669 | } |
| 670 | 670 | ||
| 671 | static int mx3fb_blank(int blank, struct fb_info *fbi); | 671 | static int mx3fb_blank(int blank, struct fb_info *fbi); |
| 672 | static int mx3fb_map_video_memory(struct fb_info *fbi); | 672 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len); |
| 673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); | 673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); |
| 674 | 674 | ||
| 675 | /** | 675 | /** |
| @@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi) | |||
| 742 | if (fbi->fix.smem_start) | 742 | if (fbi->fix.smem_start) |
| 743 | mx3fb_unmap_video_memory(fbi); | 743 | mx3fb_unmap_video_memory(fbi); |
| 744 | 744 | ||
| 745 | fbi->fix.smem_len = mem_len; | 745 | if (mx3fb_map_video_memory(fbi, mem_len) < 0) { |
| 746 | if (mx3fb_map_video_memory(fbi) < 0) { | ||
| 747 | mutex_unlock(&mx3_fbi->mutex); | 746 | mutex_unlock(&mx3_fbi->mutex); |
| 748 | return -ENOMEM; | 747 | return -ENOMEM; |
| 749 | } | 748 | } |
| @@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
| 1198 | /** | 1197 | /** |
| 1199 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. | 1198 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. |
| 1200 | * @fbi: framebuffer information pointer | 1199 | * @fbi: framebuffer information pointer |
| 1200 | * @mem_len: length of mapped memory | ||
| 1201 | * @return: Error code indicating success or failure | 1201 | * @return: Error code indicating success or failure |
| 1202 | * | 1202 | * |
| 1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to | 1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to |
| @@ -1205,23 +1205,26 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
| 1205 | * area is remapped, all virtual memory access to the video memory should occur | 1205 | * area is remapped, all virtual memory access to the video memory should occur |
| 1206 | * at the new region. | 1206 | * at the new region. |
| 1207 | */ | 1207 | */ |
| 1208 | static int mx3fb_map_video_memory(struct fb_info *fbi) | 1208 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) |
| 1209 | { | 1209 | { |
| 1210 | int retval = 0; | 1210 | int retval = 0; |
| 1211 | dma_addr_t addr; | 1211 | dma_addr_t addr; |
| 1212 | 1212 | ||
| 1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, | 1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, |
| 1214 | fbi->fix.smem_len, | 1214 | mem_len, |
| 1215 | &addr, GFP_DMA); | 1215 | &addr, GFP_DMA); |
| 1216 | 1216 | ||
| 1217 | if (!fbi->screen_base) { | 1217 | if (!fbi->screen_base) { |
| 1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", | 1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", |
| 1219 | fbi->fix.smem_len); | 1219 | mem_len); |
| 1220 | retval = -EBUSY; | 1220 | retval = -EBUSY; |
| 1221 | goto err0; | 1221 | goto err0; |
| 1222 | } | 1222 | } |
| 1223 | 1223 | ||
| 1224 | mutex_lock(&fbi->mm_lock); | ||
| 1224 | fbi->fix.smem_start = addr; | 1225 | fbi->fix.smem_start = addr; |
| 1226 | fbi->fix.smem_len = mem_len; | ||
| 1227 | mutex_unlock(&fbi->mm_lock); | ||
| 1225 | 1228 | ||
| 1226 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", | 1229 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", |
| 1227 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); | 1230 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); |
| @@ -1251,8 +1254,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi) | |||
| 1251 | fbi->screen_base, fbi->fix.smem_start); | 1254 | fbi->screen_base, fbi->fix.smem_start); |
| 1252 | 1255 | ||
| 1253 | fbi->screen_base = 0; | 1256 | fbi->screen_base = 0; |
| 1257 | mutex_lock(&fbi->mm_lock); | ||
| 1254 | fbi->fix.smem_start = 0; | 1258 | fbi->fix.smem_start = 0; |
| 1255 | fbi->fix.smem_len = 0; | 1259 | fbi->fix.smem_len = 0; |
| 1260 | mutex_unlock(&fbi->mm_lock); | ||
| 1256 | return 0; | 1261 | return 0; |
| 1257 | } | 1262 | } |
| 1258 | 1263 | ||
| @@ -1360,11 +1365,6 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) | |||
| 1360 | init_completion(&mx3fbi->flip_cmpl); | 1365 | init_completion(&mx3fbi->flip_cmpl); |
| 1361 | disable_irq(ichan->eof_irq); | 1366 | disable_irq(ichan->eof_irq); |
| 1362 | dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); | 1367 | dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); |
| 1363 | ret = mx3fb_set_par(fbi); | ||
| 1364 | if (ret < 0) | ||
| 1365 | goto esetpar; | ||
| 1366 | |||
| 1367 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); | ||
| 1368 | 1368 | ||
| 1369 | dev_info(dev, "registered, using mode %s\n", fb_mode); | 1369 | dev_info(dev, "registered, using mode %s\n", fb_mode); |
| 1370 | 1370 | ||
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 060d72fe57cb..8862233d57b6 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
| @@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi) | |||
| 393 | 393 | ||
| 394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; | 394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; |
| 395 | fbi->screen_base = rg->vaddr; | 395 | fbi->screen_base = rg->vaddr; |
| 396 | mutex_lock(&fbi->mm_lock); | ||
| 396 | fix->smem_start = rg->paddr; | 397 | fix->smem_start = rg->paddr; |
| 397 | fix->smem_len = rg->size; | 398 | fix->smem_len = rg->size; |
| 399 | mutex_unlock(&fbi->mm_lock); | ||
| 398 | 400 | ||
| 399 | fix->type = FB_TYPE_PACKED_PIXELS; | 401 | fix->type = FB_TYPE_PACKED_PIXELS; |
| 400 | bpp = var->bits_per_pixel; | 402 | bpp = var->bits_per_pixel; |
| @@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
| 886 | * plane memory is dealloce'd, the other | 888 | * plane memory is dealloce'd, the other |
| 887 | * screen parameters in var / fix are invalid. | 889 | * screen parameters in var / fix are invalid. |
| 888 | */ | 890 | */ |
| 891 | mutex_lock(&fbi->mm_lock); | ||
| 889 | fbi->fix.smem_start = 0; | 892 | fbi->fix.smem_start = 0; |
| 890 | fbi->fix.smem_len = 0; | 893 | fbi->fix.smem_len = 0; |
| 894 | mutex_unlock(&fbi->mm_lock); | ||
| 891 | } | 895 | } |
| 892 | } | 896 | } |
| 893 | } | 897 | } |
| @@ -1250,7 +1254,7 @@ static struct fb_ops omapfb_ops = { | |||
| 1250 | static ssize_t omapfb_show_caps_num(struct device *dev, | 1254 | static ssize_t omapfb_show_caps_num(struct device *dev, |
| 1251 | struct device_attribute *attr, char *buf) | 1255 | struct device_attribute *attr, char *buf) |
| 1252 | { | 1256 | { |
| 1253 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1257 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1254 | int plane; | 1258 | int plane; |
| 1255 | size_t size; | 1259 | size_t size; |
| 1256 | struct omapfb_caps caps; | 1260 | struct omapfb_caps caps; |
| @@ -1270,7 +1274,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev, | |||
| 1270 | static ssize_t omapfb_show_caps_text(struct device *dev, | 1274 | static ssize_t omapfb_show_caps_text(struct device *dev, |
| 1271 | struct device_attribute *attr, char *buf) | 1275 | struct device_attribute *attr, char *buf) |
| 1272 | { | 1276 | { |
| 1273 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1277 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1274 | int i; | 1278 | int i; |
| 1275 | struct omapfb_caps caps; | 1279 | struct omapfb_caps caps; |
| 1276 | int plane; | 1280 | int plane; |
| @@ -1317,7 +1321,7 @@ static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL); | |||
| 1317 | static ssize_t omapfb_show_panel_name(struct device *dev, | 1321 | static ssize_t omapfb_show_panel_name(struct device *dev, |
| 1318 | struct device_attribute *attr, char *buf) | 1322 | struct device_attribute *attr, char *buf) |
| 1319 | { | 1323 | { |
| 1320 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1324 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1321 | 1325 | ||
| 1322 | return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name); | 1326 | return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name); |
| 1323 | } | 1327 | } |
| @@ -1326,7 +1330,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev, | |||
| 1326 | struct device_attribute *attr, | 1330 | struct device_attribute *attr, |
| 1327 | char *buf) | 1331 | char *buf) |
| 1328 | { | 1332 | { |
| 1329 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1333 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1330 | int r; | 1334 | int r; |
| 1331 | 1335 | ||
| 1332 | if (fbdev->panel->get_bklight_level) { | 1336 | if (fbdev->panel->get_bklight_level) { |
| @@ -1341,7 +1345,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev, | |||
| 1341 | struct device_attribute *attr, | 1345 | struct device_attribute *attr, |
| 1342 | const char *buf, size_t size) | 1346 | const char *buf, size_t size) |
| 1343 | { | 1347 | { |
| 1344 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1348 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1345 | int r; | 1349 | int r; |
| 1346 | 1350 | ||
| 1347 | if (fbdev->panel->set_bklight_level) { | 1351 | if (fbdev->panel->set_bklight_level) { |
| @@ -1360,7 +1364,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev, | |||
| 1360 | static ssize_t omapfb_show_bklight_max(struct device *dev, | 1364 | static ssize_t omapfb_show_bklight_max(struct device *dev, |
| 1361 | struct device_attribute *attr, char *buf) | 1365 | struct device_attribute *attr, char *buf) |
| 1362 | { | 1366 | { |
| 1363 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1367 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1364 | int r; | 1368 | int r; |
| 1365 | 1369 | ||
| 1366 | if (fbdev->panel->get_bklight_level) { | 1370 | if (fbdev->panel->get_bklight_level) { |
| @@ -1393,7 +1397,7 @@ static struct attribute_group panel_attr_grp = { | |||
| 1393 | static ssize_t omapfb_show_ctrl_name(struct device *dev, | 1397 | static ssize_t omapfb_show_ctrl_name(struct device *dev, |
| 1394 | struct device_attribute *attr, char *buf) | 1398 | struct device_attribute *attr, char *buf) |
| 1395 | { | 1399 | { |
| 1396 | struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; | 1400 | struct omapfb_device *fbdev = dev_get_drvdata(dev); |
| 1397 | 1401 | ||
| 1398 | return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name); | 1402 | return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name); |
| 1399 | } | 1403 | } |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 03b3670130a0..bacfabd9ce16 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
| @@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info) | |||
| 141 | offset = 0x10; | 141 | offset = 0x10; |
| 142 | 142 | ||
| 143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; | 143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; |
| 144 | mutex_lock(&info->mm_lock); | ||
| 144 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; | 145 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; |
| 146 | mutex_unlock(&info->mm_lock); | ||
| 145 | info->fix.visual = (pinfo->cmode == CMODE_8) ? | 147 | info->fix.visual = (pinfo->cmode == CMODE_8) ? |
| 146 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 148 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
| 147 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) | 149 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0889d50c3288..6506117c134b 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) | |||
| 815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); | 815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); |
| 816 | ofb->video_mem_size = size; | 816 | ofb->video_mem_size = size; |
| 817 | 817 | ||
| 818 | mutex_lock(&ofb->fb.mm_lock); | ||
| 818 | ofb->fb.fix.smem_start = ofb->video_mem_phys; | 819 | ofb->fb.fix.smem_start = ofb->video_mem_phys; |
| 819 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; | 820 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; |
| 821 | mutex_unlock(&ofb->fb.mm_lock); | ||
| 820 | ofb->fb.screen_base = ofb->video_mem; | 822 | ofb->fb.screen_base = ofb->video_mem; |
| 821 | return 0; | 823 | return 0; |
| 822 | } | 824 | } |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 43680e545427..bb63c07e13de 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
| @@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
| 211 | 211 | ||
| 212 | /** | 212 | /** |
| 213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. | 213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. |
| 214 | * @id: window id. | ||
| 214 | * @sfb: The hardware state. | 215 | * @sfb: The hardware state. |
| 215 | * @pixclock: The pixel clock wanted, in picoseconds. | 216 | * @pixclock: The pixel clock wanted, in picoseconds. |
| 216 | * | 217 | * |
| 217 | * Given the specified pixel clock, work out the necessary divider to get | 218 | * Given the specified pixel clock, work out the necessary divider to get |
| 218 | * close to the output frequency. | 219 | * close to the output frequency. |
| 219 | */ | 220 | */ |
| 220 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | 221 | static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) |
| 221 | { | 222 | { |
| 223 | struct s3c_fb_pd_win *win = sfb->pdata->win[id]; | ||
| 222 | unsigned long clk = clk_get_rate(sfb->bus_clk); | 224 | unsigned long clk = clk_get_rate(sfb->bus_clk); |
| 223 | unsigned long long tmp; | ||
| 224 | unsigned int result; | 225 | unsigned int result; |
| 225 | 226 | ||
| 226 | tmp = (unsigned long long)clk; | 227 | pixclk *= win->win_mode.refresh; |
| 227 | tmp *= pixclk; | 228 | result = clk / pixclk; |
| 228 | |||
| 229 | do_div(tmp, 1000000000UL); | ||
| 230 | result = (unsigned int)tmp / 1000; | ||
| 231 | 229 | ||
| 232 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", | 230 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", |
| 233 | pixclk, clk, result, clk / result); | 231 | pixclk, clk, result, clk / result); |
| @@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
| 267 | struct s3c_fb *sfb = win->parent; | 265 | struct s3c_fb *sfb = win->parent; |
| 268 | void __iomem *regs = sfb->regs; | 266 | void __iomem *regs = sfb->regs; |
| 269 | int win_no = win->index; | 267 | int win_no = win->index; |
| 268 | u32 osdc_data = 0; | ||
| 270 | u32 data; | 269 | u32 data; |
| 271 | u32 pagewidth; | 270 | u32 pagewidth; |
| 272 | int clkdiv; | 271 | int clkdiv; |
| @@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
| 302 | /* use window 0 as the basis for the lcd output timings */ | 301 | /* use window 0 as the basis for the lcd output timings */ |
| 303 | 302 | ||
| 304 | if (win_no == 0) { | 303 | if (win_no == 0) { |
| 305 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | 304 | clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); |
| 306 | 305 | ||
| 307 | data = sfb->pdata->vidcon0; | 306 | data = sfb->pdata->vidcon0; |
| 308 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | 307 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); |
| @@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
| 359 | 358 | ||
| 360 | data = var->xres * var->yres; | 359 | data = var->xres * var->yres; |
| 361 | 360 | ||
| 362 | u32 osdc_data = 0; | ||
| 363 | |||
| 364 | osdc_data = VIDISD14C_ALPHA1_R(0xf) | | 361 | osdc_data = VIDISD14C_ALPHA1_R(0xf) | |
| 365 | VIDISD14C_ALPHA1_G(0xf) | | 362 | VIDISD14C_ALPHA1_G(0xf) | |
| 366 | VIDISD14C_ALPHA1_B(0xf); | 363 | VIDISD14C_ALPHA1_B(0xf); |
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index 653bdfee3057..9f6d6e61f0cc 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c | |||
| @@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno, | |||
| 120 | return 0; | 120 | return 0; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info, | ||
| 124 | unsigned long stride) | ||
| 125 | { | ||
| 126 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
| 127 | strcpy(fix->id, "sh7760-lcdc"); | ||
| 128 | |||
| 129 | fix->smem_start = (unsigned long)info->screen_base; | ||
| 130 | fix->smem_len = info->screen_size; | ||
| 131 | |||
| 132 | fix->line_length = stride; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int sh7760fb_get_color_info(struct device *dev, | 123 | static int sh7760fb_get_color_info(struct device *dev, |
| 136 | u16 lddfr, int *bpp, int *gray) | 124 | u16 lddfr, int *bpp, int *gray) |
| 137 | { | 125 | { |
| @@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info) | |||
| 334 | 322 | ||
| 335 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ | 323 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ |
| 336 | 324 | ||
| 337 | encode_fix(&info->fix, info, stride); | 325 | info->fix.line_length = stride; |
| 326 | |||
| 338 | sh7760fb_check_var(&info->var, info); | 327 | sh7760fb_check_var(&info->var, info); |
| 339 | 328 | ||
| 340 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ | 329 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ |
| @@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info) | |||
| 435 | 424 | ||
| 436 | info->screen_base = fbmem; | 425 | info->screen_base = fbmem; |
| 437 | info->screen_size = vram; | 426 | info->screen_size = vram; |
| 427 | info->fix.smem_start = (unsigned long)info->screen_base; | ||
| 428 | info->fix.smem_len = info->screen_size; | ||
| 438 | 429 | ||
| 439 | return 0; | 430 | return 0; |
| 440 | } | 431 | } |
| @@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) | |||
| 520 | info->var.transp.length = 0; | 511 | info->var.transp.length = 0; |
| 521 | info->var.transp.msb_right = 0; | 512 | info->var.transp.msb_right = 0; |
| 522 | 513 | ||
| 514 | strcpy(info->fix.id, "sh7760-lcdc"); | ||
| 515 | |||
| 523 | /* set the DON2 bit now, before cmap allocation, as it will randomize | 516 | /* set the DON2 bit now, before cmap allocation, as it will randomize |
| 524 | * palette memory. | 517 | * palette memory. |
| 525 | */ | 518 | */ |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index f10d2fbeda06..8f24564f77b0 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/vmalloc.h> | ||
| 20 | #include <video/sh_mobile_lcdc.h> | 21 | #include <video/sh_mobile_lcdc.h> |
| 21 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
| 22 | 23 | ||
| @@ -30,9 +31,10 @@ struct sh_mobile_lcdc_chan { | |||
| 30 | unsigned long enabled; /* ME and SE in LDCNT2R */ | 31 | unsigned long enabled; /* ME and SE in LDCNT2R */ |
| 31 | struct sh_mobile_lcdc_chan_cfg cfg; | 32 | struct sh_mobile_lcdc_chan_cfg cfg; |
| 32 | u32 pseudo_palette[PALETTE_NR]; | 33 | u32 pseudo_palette[PALETTE_NR]; |
| 33 | struct fb_info info; | 34 | struct fb_info *info; |
| 34 | dma_addr_t dma_handle; | 35 | dma_addr_t dma_handle; |
| 35 | struct fb_deferred_io defio; | 36 | struct fb_deferred_io defio; |
| 37 | struct scatterlist *sglist; | ||
| 36 | unsigned long frame_end; | 38 | unsigned long frame_end; |
| 37 | wait_queue_head_t frame_end_wait; | 39 | wait_queue_head_t frame_end_wait; |
| 38 | }; | 40 | }; |
| @@ -206,16 +208,38 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} | |||
| 206 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} | 208 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} |
| 207 | #endif | 209 | #endif |
| 208 | 210 | ||
| 211 | static int sh_mobile_lcdc_sginit(struct fb_info *info, | ||
| 212 | struct list_head *pagelist) | ||
| 213 | { | ||
| 214 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
| 215 | unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; | ||
| 216 | struct page *page; | ||
| 217 | int nr_pages = 0; | ||
| 218 | |||
| 219 | sg_init_table(ch->sglist, nr_pages_max); | ||
| 220 | |||
| 221 | list_for_each_entry(page, pagelist, lru) | ||
| 222 | sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0); | ||
| 223 | |||
| 224 | return nr_pages; | ||
| 225 | } | ||
| 226 | |||
| 209 | static void sh_mobile_lcdc_deferred_io(struct fb_info *info, | 227 | static void sh_mobile_lcdc_deferred_io(struct fb_info *info, |
| 210 | struct list_head *pagelist) | 228 | struct list_head *pagelist) |
| 211 | { | 229 | { |
| 212 | struct sh_mobile_lcdc_chan *ch = info->par; | 230 | struct sh_mobile_lcdc_chan *ch = info->par; |
| 231 | unsigned int nr_pages; | ||
| 213 | 232 | ||
| 214 | /* enable clocks before accessing hardware */ | 233 | /* enable clocks before accessing hardware */ |
| 215 | sh_mobile_lcdc_clk_on(ch->lcdc); | 234 | sh_mobile_lcdc_clk_on(ch->lcdc); |
| 216 | 235 | ||
| 236 | nr_pages = sh_mobile_lcdc_sginit(info, pagelist); | ||
| 237 | dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | ||
| 238 | |||
| 217 | /* trigger panel update */ | 239 | /* trigger panel update */ |
| 218 | lcdc_write_chan(ch, LDSM2R, 1); | 240 | lcdc_write_chan(ch, LDSM2R, 1); |
| 241 | |||
| 242 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | ||
| 219 | } | 243 | } |
| 220 | 244 | ||
| 221 | static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) | 245 | static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) |
| @@ -418,22 +442,22 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
| 418 | /* set bpp format in PKF[4:0] */ | 442 | /* set bpp format in PKF[4:0] */ |
| 419 | tmp = lcdc_read_chan(ch, LDDFR); | 443 | tmp = lcdc_read_chan(ch, LDDFR); |
| 420 | tmp &= ~(0x0001001f); | 444 | tmp &= ~(0x0001001f); |
| 421 | tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0; | 445 | tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; |
| 422 | lcdc_write_chan(ch, LDDFR, tmp); | 446 | lcdc_write_chan(ch, LDDFR, tmp); |
| 423 | 447 | ||
| 424 | /* point out our frame buffer */ | 448 | /* point out our frame buffer */ |
| 425 | lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start); | 449 | lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); |
| 426 | 450 | ||
| 427 | /* set line size */ | 451 | /* set line size */ |
| 428 | lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length); | 452 | lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); |
| 429 | 453 | ||
| 430 | /* setup deferred io if SYS bus */ | 454 | /* setup deferred io if SYS bus */ |
| 431 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | 455 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; |
| 432 | if (ch->ldmt1r_value & (1 << 12) && tmp) { | 456 | if (ch->ldmt1r_value & (1 << 12) && tmp) { |
| 433 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; | 457 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; |
| 434 | ch->defio.delay = msecs_to_jiffies(tmp); | 458 | ch->defio.delay = msecs_to_jiffies(tmp); |
| 435 | ch->info.fbdefio = &ch->defio; | 459 | ch->info->fbdefio = &ch->defio; |
| 436 | fb_deferred_io_init(&ch->info); | 460 | fb_deferred_io_init(ch->info); |
| 437 | 461 | ||
| 438 | /* one-shot mode */ | 462 | /* one-shot mode */ |
| 439 | lcdc_write_chan(ch, LDSM1R, 1); | 463 | lcdc_write_chan(ch, LDSM1R, 1); |
| @@ -479,12 +503,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
| 479 | * flush frame, and wait for frame end interrupt | 503 | * flush frame, and wait for frame end interrupt |
| 480 | * clean up deferred io and enable clock | 504 | * clean up deferred io and enable clock |
| 481 | */ | 505 | */ |
| 482 | if (ch->info.fbdefio) { | 506 | if (ch->info->fbdefio) { |
| 483 | ch->frame_end = 0; | 507 | ch->frame_end = 0; |
| 484 | schedule_delayed_work(&ch->info.deferred_work, 0); | 508 | schedule_delayed_work(&ch->info->deferred_work, 0); |
| 485 | wait_event(ch->frame_end_wait, ch->frame_end); | 509 | wait_event(ch->frame_end_wait, ch->frame_end); |
| 486 | fb_deferred_io_cleanup(&ch->info); | 510 | fb_deferred_io_cleanup(ch->info); |
| 487 | ch->info.fbdefio = NULL; | 511 | ch->info->fbdefio = NULL; |
| 488 | sh_mobile_lcdc_clk_on(priv); | 512 | sh_mobile_lcdc_clk_on(priv); |
| 489 | } | 513 | } |
| 490 | 514 | ||
| @@ -793,9 +817,16 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 793 | priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); | 817 | priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); |
| 794 | 818 | ||
| 795 | for (i = 0; i < j; i++) { | 819 | for (i = 0; i < j; i++) { |
| 796 | info = &priv->ch[i].info; | ||
| 797 | cfg = &priv->ch[i].cfg; | 820 | cfg = &priv->ch[i].cfg; |
| 798 | 821 | ||
| 822 | priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); | ||
| 823 | if (!priv->ch[i].info) { | ||
| 824 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); | ||
| 825 | error = -ENOMEM; | ||
| 826 | break; | ||
| 827 | } | ||
| 828 | |||
| 829 | info = priv->ch[i].info; | ||
| 799 | info->fbops = &sh_mobile_lcdc_ops; | 830 | info->fbops = &sh_mobile_lcdc_ops; |
| 800 | info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; | 831 | info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; |
| 801 | info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; | 832 | info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; |
| @@ -846,21 +877,31 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 846 | } | 877 | } |
| 847 | 878 | ||
| 848 | for (i = 0; i < j; i++) { | 879 | for (i = 0; i < j; i++) { |
| 849 | error = register_framebuffer(&priv->ch[i].info); | 880 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
| 881 | |||
| 882 | info = ch->info; | ||
| 883 | |||
| 884 | if (info->fbdefio) { | ||
| 885 | priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * | ||
| 886 | info->fix.smem_len >> PAGE_SHIFT); | ||
| 887 | if (!priv->ch->sglist) { | ||
| 888 | dev_err(&pdev->dev, "cannot allocate sglist\n"); | ||
| 889 | goto err1; | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 893 | error = register_framebuffer(info); | ||
| 850 | if (error < 0) | 894 | if (error < 0) |
| 851 | goto err1; | 895 | goto err1; |
| 852 | } | ||
| 853 | 896 | ||
| 854 | for (i = 0; i < j; i++) { | ||
| 855 | info = &priv->ch[i].info; | ||
| 856 | dev_info(info->dev, | 897 | dev_info(info->dev, |
| 857 | "registered %s/%s as %dx%d %dbpp.\n", | 898 | "registered %s/%s as %dx%d %dbpp.\n", |
| 858 | pdev->name, | 899 | pdev->name, |
| 859 | (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? | 900 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? |
| 860 | "mainlcd" : "sublcd", | 901 | "mainlcd" : "sublcd", |
| 861 | (int) priv->ch[i].cfg.lcd_cfg.xres, | 902 | (int) ch->cfg.lcd_cfg.xres, |
| 862 | (int) priv->ch[i].cfg.lcd_cfg.yres, | 903 | (int) ch->cfg.lcd_cfg.yres, |
| 863 | priv->ch[i].cfg.bpp); | 904 | ch->cfg.bpp); |
| 864 | 905 | ||
| 865 | /* deferred io mode: disable clock to save power */ | 906 | /* deferred io mode: disable clock to save power */ |
| 866 | if (info->fbdefio) | 907 | if (info->fbdefio) |
| @@ -881,20 +922,24 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) | |||
| 881 | int i; | 922 | int i; |
| 882 | 923 | ||
| 883 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | 924 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) |
| 884 | if (priv->ch[i].info.dev) | 925 | if (priv->ch[i].info->dev) |
| 885 | unregister_framebuffer(&priv->ch[i].info); | 926 | unregister_framebuffer(priv->ch[i].info); |
| 886 | 927 | ||
| 887 | sh_mobile_lcdc_stop(priv); | 928 | sh_mobile_lcdc_stop(priv); |
| 888 | 929 | ||
| 889 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | 930 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { |
| 890 | info = &priv->ch[i].info; | 931 | info = priv->ch[i].info; |
| 891 | 932 | ||
| 892 | if (!info->device) | 933 | if (!info || !info->device) |
| 893 | continue; | 934 | continue; |
| 894 | 935 | ||
| 936 | if (priv->ch[i].sglist) | ||
| 937 | vfree(priv->ch[i].sglist); | ||
| 938 | |||
| 895 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | 939 | dma_free_coherent(&pdev->dev, info->fix.smem_len, |
| 896 | info->screen_base, priv->ch[i].dma_handle); | 940 | info->screen_base, priv->ch[i].dma_handle); |
| 897 | fb_dealloc_cmap(&info->cmap); | 941 | fb_dealloc_cmap(&info->cmap); |
| 942 | framebuffer_release(info); | ||
| 898 | } | 943 | } |
| 899 | 944 | ||
| 900 | #ifdef CONFIG_HAVE_CLK | 945 | #ifdef CONFIG_HAVE_CLK |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 7072d19080d5..4a067f0d0ceb 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
| @@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | |||
| 1847 | 1847 | ||
| 1848 | strcpy(fix->id, ivideo->myid); | 1848 | strcpy(fix->id, ivideo->myid); |
| 1849 | 1849 | ||
| 1850 | mutex_lock(&info->mm_lock); | ||
| 1850 | fix->smem_start = ivideo->video_base + ivideo->video_offset; | 1851 | fix->smem_start = ivideo->video_base + ivideo->video_offset; |
| 1851 | fix->smem_len = ivideo->sisfb_mem; | 1852 | fix->smem_len = ivideo->sisfb_mem; |
| 1853 | mutex_unlock(&info->mm_lock); | ||
| 1852 | fix->type = FB_TYPE_PACKED_PIXELS; | 1854 | fix->type = FB_TYPE_PACKED_PIXELS; |
| 1853 | fix->type_aux = 0; | 1855 | fix->type_aux = 0; |
| 1854 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 1856 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
| @@ -6365,7 +6367,6 @@ error_3: vfree(ivideo->bios_abase); | |||
| 6365 | sis_fb_info->fix = ivideo->sisfb_fix; | 6367 | sis_fb_info->fix = ivideo->sisfb_fix; |
| 6366 | sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; | 6368 | sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; |
| 6367 | sis_fb_info->fbops = &sisfb_ops; | 6369 | sis_fb_info->fbops = &sisfb_ops; |
| 6368 | sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); | ||
| 6369 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; | 6370 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; |
| 6370 | 6371 | ||
| 6371 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); | 6372 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index eb5d73a06702..924d79462780 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
| @@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
| 145 | #define SM501_MEMF_ACCEL (8) | 145 | #define SM501_MEMF_ACCEL (8) |
| 146 | 146 | ||
| 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, |
| 148 | unsigned int why, size_t size) | 148 | unsigned int why, size_t size, u32 smem_len) |
| 149 | { | 149 | { |
| 150 | struct sm501fb_par *par; | 150 | struct sm501fb_par *par; |
| 151 | struct fb_info *fbi; | 151 | struct fb_info *fbi; |
| @@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
| 172 | if (ptr > 0) | 172 | if (ptr > 0) |
| 173 | ptr &= ~(PAGE_SIZE - 1); | 173 | ptr &= ~(PAGE_SIZE - 1); |
| 174 | 174 | ||
| 175 | if (fbi && ptr < fbi->fix.smem_len) | 175 | if (fbi && ptr < smem_len) |
| 176 | return -ENOMEM; | 176 | return -ENOMEM; |
| 177 | 177 | ||
| 178 | break; | 178 | break; |
| @@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
| 197 | 197 | ||
| 198 | case SM501_MEMF_ACCEL: | 198 | case SM501_MEMF_ACCEL: |
| 199 | fbi = inf->fb[HEAD_CRT]; | 199 | fbi = inf->fb[HEAD_CRT]; |
| 200 | ptr = fbi ? fbi->fix.smem_len : 0; | 200 | ptr = fbi ? smem_len : 0; |
| 201 | 201 | ||
| 202 | fbi = inf->fb[HEAD_PANEL]; | 202 | fbi = inf->fb[HEAD_PANEL]; |
| 203 | if (fbi) { | 203 | if (fbi) { |
| @@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
| 413 | unsigned int mem_type; | 413 | unsigned int mem_type; |
| 414 | unsigned int clock_type; | 414 | unsigned int clock_type; |
| 415 | unsigned int head_addr; | 415 | unsigned int head_addr; |
| 416 | unsigned int smem_len; | ||
| 416 | 417 | ||
| 417 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", | 418 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", |
| 418 | __func__, var->xres, var->yres, var->bits_per_pixel, | 419 | __func__, var->xres, var->yres, var->bits_per_pixel, |
| @@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
| 453 | 454 | ||
| 454 | /* allocate fb memory within 501 */ | 455 | /* allocate fb memory within 501 */ |
| 455 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; | 456 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; |
| 456 | info->fix.smem_len = info->fix.line_length * var->yres_virtual; | 457 | smem_len = info->fix.line_length * var->yres_virtual; |
| 457 | 458 | ||
| 458 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, | 459 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, |
| 459 | info->fix.line_length); | 460 | info->fix.line_length); |
| 460 | 461 | ||
| 461 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, | 462 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) { |
| 462 | info->fix.smem_len)) { | ||
| 463 | dev_err(fbi->dev, "no memory available\n"); | 463 | dev_err(fbi->dev, "no memory available\n"); |
| 464 | return -ENOMEM; | 464 | return -ENOMEM; |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | mutex_lock(&info->mm_lock); | ||
| 467 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; | 468 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; |
| 469 | info->fix.smem_len = smem_len; | ||
| 470 | mutex_unlock(&info->mm_lock); | ||
| 468 | 471 | ||
| 469 | info->screen_base = fbi->fbmem + par->screen.sm_addr; | 472 | info->screen_base = fbi->fbmem + par->screen.sm_addr; |
| 470 | info->screen_size = info->fix.smem_len; | 473 | info->screen_size = info->fix.smem_len; |
| @@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info) | |||
| 637 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { | 640 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { |
| 638 | /* the head is displaying panel data... */ | 641 | /* the head is displaying panel data... */ |
| 639 | 642 | ||
| 640 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); | 643 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0, |
| 644 | info->fix.smem_len); | ||
| 641 | goto out_update; | 645 | goto out_update; |
| 642 | } | 646 | } |
| 643 | 647 | ||
| @@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) | |||
| 1289 | 1293 | ||
| 1290 | par->cursor_regs = info->regs + reg_base; | 1294 | par->cursor_regs = info->regs + reg_base; |
| 1291 | 1295 | ||
| 1292 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); | 1296 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024, |
| 1297 | fbi->fix.smem_len); | ||
| 1293 | if (ret < 0) | 1298 | if (ret < 0) |
| 1294 | return ret; | 1299 | return ret; |
| 1295 | 1300 | ||
| @@ -1535,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
| 1535 | if (ret) | 1540 | if (ret) |
| 1536 | dev_err(info->dev, "check_var() failed on initial setup?\n"); | 1541 | dev_err(info->dev, "check_var() failed on initial setup?\n"); |
| 1537 | 1542 | ||
| 1538 | /* ensure we've activated our new configuration */ | ||
| 1539 | (fb->fbops->fb_set_par)(fb); | ||
| 1540 | |||
| 1541 | return 0; | 1543 | return 0; |
| 1542 | } | 1544 | } |
| 1543 | 1545 | ||
| @@ -1619,6 +1621,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info, | |||
| 1619 | if (!fbi) | 1621 | if (!fbi) |
| 1620 | return 0; | 1622 | return 0; |
| 1621 | 1623 | ||
| 1624 | mutex_init(&info->fb[head]->mm_lock); | ||
| 1625 | |||
| 1622 | ret = sm501fb_init_fb(info->fb[head], head, drvname); | 1626 | ret = sm501fb_init_fb(info->fb[head], head, drvname); |
| 1623 | if (ret) { | 1627 | if (ret) { |
| 1624 | dev_err(info->dev, "cannot initialise fb %s\n", drvname); | 1628 | dev_err(info->dev, "cannot initialise fb %s\n", drvname); |
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index eec9dcb7f599..6120f0c526fe 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
| @@ -1115,10 +1115,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
| 1115 | if the device name contains the string "DX" and tell the | 1115 | if the device name contains the string "DX" and tell the |
| 1116 | user how to reconfigure the card. */ | 1116 | user how to reconfigure the card. */ |
| 1117 | if (strstr(sti->outptr.dev_name, "DX")) { | 1117 | if (strstr(sti->outptr.dev_name, "DX")) { |
| 1118 | printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " | 1118 | printk(KERN_WARNING |
| 1119 | "support '%s' in double-buffer mode.\n" | 1119 | "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" |
| 1120 | KERN_WARNING "WARNING: Please disable the double-buffer mode " | 1120 | "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", |
| 1121 | "in IPL menu (the PARISC-BIOS).\n", | ||
| 1122 | sti->outptr.dev_name); | 1121 | sti->outptr.dev_name); |
| 1123 | goto out_err0; | 1122 | goto out_err0; |
| 1124 | } | 1123 | } |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index d0674f1e3f10..2376f688ec8b 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
| @@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
| 523 | info->fix.ywrapstep = 0; | 523 | info->fix.ywrapstep = 0; |
| 524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; | 524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; |
| 525 | 525 | ||
| 526 | mutex_lock(&info->mm_lock); | ||
| 526 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { | 527 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { |
| 527 | par->extmem_active = 1; | 528 | par->extmem_active = 1; |
| 528 | info->fix.smem_len = par->mach->mem->size+1; | 529 | info->fix.smem_len = par->mach->mem->size+1; |
| @@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
| 530 | par->extmem_active = 0; | 531 | par->extmem_active = 0; |
| 531 | info->fix.smem_len = MEM_INT_SIZE+1; | 532 | info->fix.smem_len = MEM_INT_SIZE+1; |
| 532 | } | 533 | } |
| 534 | mutex_unlock(&info->mm_lock); | ||
| 533 | 535 | ||
| 534 | w100fb_activate_var(par); | 536 | w100fb_activate_var(par); |
| 535 | } | 537 | } |
| @@ -746,8 +748,6 @@ int __init w100fb_probe(struct platform_device *pdev) | |||
| 746 | goto out; | 748 | goto out; |
| 747 | } | 749 | } |
| 748 | 750 | ||
| 749 | w100fb_set_par(info); | ||
| 750 | |||
| 751 | if (register_framebuffer(info) < 0) { | 751 | if (register_framebuffer(info) < 0) { |
| 752 | err = -EINVAL; | 752 | err = -EINVAL; |
| 753 | goto out; | 753 | goto out; |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 193c8f0e5cc5..bcec78ffc765 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -669,7 +669,7 @@ static int __init virtio_pci_init(void) | |||
| 669 | 669 | ||
| 670 | err = pci_register_driver(&virtio_pci_driver); | 670 | err = pci_register_driver(&virtio_pci_driver); |
| 671 | if (err) | 671 | if (err) |
| 672 | device_unregister(virtio_pci_root); | 672 | root_device_unregister(virtio_pci_root); |
| 673 | 673 | ||
| 674 | return err; | 674 | return err; |
| 675 | } | 675 | } |
diff --git a/drivers/vlynq/Kconfig b/drivers/vlynq/Kconfig index f6542211db48..a9efb1625321 100644 --- a/drivers/vlynq/Kconfig +++ b/drivers/vlynq/Kconfig | |||
| @@ -13,7 +13,7 @@ config VLYNQ | |||
| 13 | 13 | ||
| 14 | config VLYNQ_DEBUG | 14 | config VLYNQ_DEBUG |
| 15 | bool "VLYNQ bus debug" | 15 | bool "VLYNQ bus debug" |
| 16 | depends on VLYNQ && KERNEL_DEBUG | 16 | depends on VLYNQ && DEBUG_KERNEL |
| 17 | help | 17 | help |
| 18 | Turn on VLYNQ bus debugging. | 18 | Turn on VLYNQ bus debugging. |
| 19 | 19 | ||
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index 7335433b067b..f05d2a368367 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c | |||
| @@ -76,7 +76,7 @@ struct vlynq_regs { | |||
| 76 | u32 int_device[8]; | 76 | u32 int_device[8]; |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | #ifdef VLYNQ_DEBUG | 79 | #ifdef CONFIG_VLYNQ_DEBUG |
| 80 | static void vlynq_dump_regs(struct vlynq_device *dev) | 80 | static void vlynq_dump_regs(struct vlynq_device *dev) |
| 81 | { | 81 | { |
| 82 | int i; | 82 | int i; |
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index 1f09d4e4144c..59f708efe25f 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c | |||
| @@ -68,6 +68,34 @@ int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count) | |||
| 68 | return w1_ds2760_io(dev, buf, addr, count, 1); | 68 | return w1_ds2760_io(dev, buf, addr, count, 1); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) | ||
| 72 | { | ||
| 73 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
| 74 | |||
| 75 | if (!dev) | ||
| 76 | return -EINVAL; | ||
| 77 | |||
| 78 | mutex_lock(&sl->master->mutex); | ||
| 79 | |||
| 80 | if (w1_reset_select_slave(sl) == 0) { | ||
| 81 | w1_write_8(sl->master, cmd); | ||
| 82 | w1_write_8(sl->master, addr); | ||
| 83 | } | ||
| 84 | |||
| 85 | mutex_unlock(&sl->master->mutex); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | int w1_ds2760_store_eeprom(struct device *dev, int addr) | ||
| 90 | { | ||
| 91 | return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA); | ||
| 92 | } | ||
| 93 | |||
| 94 | int w1_ds2760_recall_eeprom(struct device *dev, int addr) | ||
| 95 | { | ||
| 96 | return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA); | ||
| 97 | } | ||
| 98 | |||
| 71 | static ssize_t w1_ds2760_read_bin(struct kobject *kobj, | 99 | static ssize_t w1_ds2760_read_bin(struct kobject *kobj, |
| 72 | struct bin_attribute *bin_attr, | 100 | struct bin_attribute *bin_attr, |
| 73 | char *buf, loff_t off, size_t count) | 101 | char *buf, loff_t off, size_t count) |
| @@ -200,6 +228,8 @@ static void __exit w1_ds2760_exit(void) | |||
| 200 | 228 | ||
| 201 | EXPORT_SYMBOL(w1_ds2760_read); | 229 | EXPORT_SYMBOL(w1_ds2760_read); |
| 202 | EXPORT_SYMBOL(w1_ds2760_write); | 230 | EXPORT_SYMBOL(w1_ds2760_write); |
| 231 | EXPORT_SYMBOL(w1_ds2760_store_eeprom); | ||
| 232 | EXPORT_SYMBOL(w1_ds2760_recall_eeprom); | ||
| 203 | 233 | ||
| 204 | module_init(w1_ds2760_init); | 234 | module_init(w1_ds2760_init); |
| 205 | module_exit(w1_ds2760_exit); | 235 | module_exit(w1_ds2760_exit); |
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h index f1302429cb02..58e774141568 100644 --- a/drivers/w1/slaves/w1_ds2760.h +++ b/drivers/w1/slaves/w1_ds2760.h | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | 25 | ||
| 26 | #define DS2760_PROTECTION_REG 0x00 | 26 | #define DS2760_PROTECTION_REG 0x00 |
| 27 | #define DS2760_STATUS_REG 0x01 | 27 | #define DS2760_STATUS_REG 0x01 |
| 28 | #define DS2760_STATUS_IE (1 << 2) | ||
| 29 | #define DS2760_STATUS_SWEN (1 << 3) | ||
| 30 | #define DS2760_STATUS_RNAOP (1 << 4) | ||
| 31 | #define DS2760_STATUS_PMOD (1 << 5) | ||
| 28 | #define DS2760_EEPROM_REG 0x07 | 32 | #define DS2760_EEPROM_REG 0x07 |
| 29 | #define DS2760_SPECIAL_FEATURE_REG 0x08 | 33 | #define DS2760_SPECIAL_FEATURE_REG 0x08 |
| 30 | #define DS2760_VOLTAGE_MSB 0x0c | 34 | #define DS2760_VOLTAGE_MSB 0x0c |
| @@ -38,6 +42,7 @@ | |||
| 38 | #define DS2760_EEPROM_BLOCK0 0x20 | 42 | #define DS2760_EEPROM_BLOCK0 0x20 |
| 39 | #define DS2760_ACTIVE_FULL 0x20 | 43 | #define DS2760_ACTIVE_FULL 0x20 |
| 40 | #define DS2760_EEPROM_BLOCK1 0x30 | 44 | #define DS2760_EEPROM_BLOCK1 0x30 |
| 45 | #define DS2760_STATUS_WRITE_REG 0x31 | ||
| 41 | #define DS2760_RATED_CAPACITY 0x32 | 46 | #define DS2760_RATED_CAPACITY 0x32 |
| 42 | #define DS2760_CURRENT_OFFSET_BIAS 0x33 | 47 | #define DS2760_CURRENT_OFFSET_BIAS 0x33 |
| 43 | #define DS2760_ACTIVE_EMPTY 0x3b | 48 | #define DS2760_ACTIVE_EMPTY 0x3b |
| @@ -46,5 +51,7 @@ extern int w1_ds2760_read(struct device *dev, char *buf, int addr, | |||
| 46 | size_t count); | 51 | size_t count); |
| 47 | extern int w1_ds2760_write(struct device *dev, char *buf, int addr, | 52 | extern int w1_ds2760_write(struct device *dev, char *buf, int addr, |
| 48 | size_t count); | 53 | size_t count); |
| 54 | extern int w1_ds2760_store_eeprom(struct device *dev, int addr); | ||
| 55 | extern int w1_ds2760_recall_eeprom(struct device *dev, int addr); | ||
| 49 | 56 | ||
| 50 | #endif /* !__w1_ds2760_h__ */ | 57 | #endif /* !__w1_ds2760_h__ */ |
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 5c7011cda6a6..751c003864ad 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c | |||
| @@ -161,7 +161,7 @@ static long bcm47xx_wdt_ioctl(struct file *file, | |||
| 161 | { | 161 | { |
| 162 | void __user *argp = (void __user *)arg; | 162 | void __user *argp = (void __user *)arg; |
| 163 | int __user *p = argp; | 163 | int __user *p = argp; |
| 164 | int new_value, retval = -EINVAL;; | 164 | int new_value, retval = -EINVAL; |
| 165 | 165 | ||
| 166 | switch (cmd) { | 166 | switch (cmd) { |
| 167 | case WDIOC_GETSUPPORT: | 167 | case WDIOC_GETSUPPORT: |
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index ee1caae4d33b..016245419fad 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | static unsigned long oscr_freq; | 39 | static unsigned long oscr_freq; |
| 40 | static unsigned long sa1100wdt_users; | 40 | static unsigned long sa1100wdt_users; |
| 41 | static int pre_margin; | 41 | static unsigned int pre_margin; |
| 42 | static int boot_status; | 42 | static int boot_status; |
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| @@ -84,6 +84,7 @@ static const struct watchdog_info ident = { | |||
| 84 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | 84 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT |
| 85 | | WDIOF_KEEPALIVEPING, | 85 | | WDIOF_KEEPALIVEPING, |
| 86 | .identity = "SA1100/PXA255 Watchdog", | 86 | .identity = "SA1100/PXA255 Watchdog", |
| 87 | .firmware_version = 1, | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | static long sa1100dog_ioctl(struct file *file, unsigned int cmd, | 90 | static long sa1100dog_ioctl(struct file *file, unsigned int cmd, |
| @@ -118,7 +119,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, | |||
| 118 | if (ret) | 119 | if (ret) |
| 119 | break; | 120 | break; |
| 120 | 121 | ||
| 121 | if (time <= 0 || time > 255) { | 122 | if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { |
| 122 | ret = -EINVAL; | 123 | ret = -EINVAL; |
| 123 | break; | 124 | break; |
| 124 | } | 125 | } |
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 916890abffdd..f201accc4e3d 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c | |||
| @@ -89,6 +89,11 @@ static void w83627hf_select_wd_register(void) | |||
| 89 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ | 89 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ |
| 90 | outb_p(0x2b, WDT_EFER); | 90 | outb_p(0x2b, WDT_EFER); |
| 91 | outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ | 91 | outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ |
| 92 | } else if (c == 0x88) { /* W83627EHF */ | ||
| 93 | outb_p(0x2d, WDT_EFER); /* select GPIO5 */ | ||
| 94 | c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ | ||
| 95 | outb_p(0x2d, WDT_EFER); | ||
| 96 | outb_p(c, WDT_EFDR); /* set GPIO5 to WDT0 */ | ||
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | outb_p(0x07, WDT_EFER); /* point to logical device number reg */ | 99 | outb_p(0x07, WDT_EFER); /* point to logical device number reg */ |
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index 883b5f79673a..a6c12dec91a1 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c | |||
| @@ -149,8 +149,10 @@ static void wdt_ctrl(int timeout) | |||
| 149 | { | 149 | { |
| 150 | spin_lock(&io_lock); | 150 | spin_lock(&io_lock); |
| 151 | 151 | ||
| 152 | if (w83697ug_select_wd_register() < 0) | 152 | if (w83697ug_select_wd_register() < 0) { |
| 153 | spin_unlock(&io_lock); | ||
| 153 | return; | 154 | return; |
| 155 | } | ||
| 154 | 156 | ||
| 155 | outb_p(0xF4, WDT_EFER); /* Select CRF4 */ | 157 | outb_p(0xF4, WDT_EFER); /* Select CRF4 */ |
| 156 | outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ | 158 | outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ |
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index a4fe7a38d9b0..3bde56bce63a 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c | |||
| @@ -218,16 +218,14 @@ static void wdrtas_timer_keepalive(void) | |||
| 218 | */ | 218 | */ |
| 219 | static int wdrtas_get_temperature(void) | 219 | static int wdrtas_get_temperature(void) |
| 220 | { | 220 | { |
| 221 | long result; | 221 | int result; |
| 222 | int temperature = 0; | 222 | int temperature = 0; |
| 223 | 223 | ||
| 224 | result = rtas_call(wdrtas_token_get_sensor_state, 2, 2, | 224 | result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature); |
| 225 | (void *)__pa(&temperature), | ||
| 226 | WDRTAS_THERMAL_SENSOR, 0); | ||
| 227 | 225 | ||
| 228 | if (result < 0) | 226 | if (result < 0) |
| 229 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " | 227 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " |
| 230 | "faild: %li\n", result); | 228 | "failed: %i\n", result); |
| 231 | else | 229 | else |
| 232 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ | 230 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ |
| 233 | 231 | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 891d2e90753a..abad71b1632b 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -927,9 +927,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { | |||
| 927 | void __init xen_init_IRQ(void) | 927 | void __init xen_init_IRQ(void) |
| 928 | { | 928 | { |
| 929 | int i; | 929 | int i; |
| 930 | size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s); | ||
| 931 | 930 | ||
| 932 | cpu_evtchn_mask_p = alloc_bootmem(size); | 931 | cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s), |
| 932 | GFP_KERNEL); | ||
| 933 | BUG_ON(cpu_evtchn_mask_p == NULL); | 933 | BUG_ON(cpu_evtchn_mask_p == NULL); |
| 934 | 934 | ||
| 935 | init_evtchn_cpu_bindings(); | 935 | init_evtchn_cpu_bindings(); |
