diff options
Diffstat (limited to 'drivers/pci/hotplug')
| -rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 5 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 127 | ||||
| -rw-r--r-- | drivers/pci/hotplug/fakephp.c | 18 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pci_hotplug.h | 4 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 157 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 12 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pcihp_skeleton.c | 9 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp.h | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 6 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_sysfs.c | 4 |
10 files changed, 274 insertions, 70 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index be104eced34c..7fff07e877c7 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -150,6 +150,11 @@ struct acpiphp_attention_info | |||
| 150 | struct module *owner; | 150 | struct module *owner; |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | struct acpiphp_ioapic { | ||
| 154 | struct pci_dev *dev; | ||
| 155 | u32 gsi_base; | ||
| 156 | struct list_head list; | ||
| 157 | }; | ||
| 153 | 158 | ||
| 154 | /* PCI bus bridge HID */ | 159 | /* PCI bus bridge HID */ |
| 155 | #define ACPI_PCI_HOST_HID "PNP0A03" | 160 | #define ACPI_PCI_HOST_HID "PNP0A03" |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ae67a8f55ba1..83e8e4412de5 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -53,6 +53,8 @@ | |||
| 53 | #include "acpiphp.h" | 53 | #include "acpiphp.h" |
| 54 | 54 | ||
| 55 | static LIST_HEAD(bridge_list); | 55 | static LIST_HEAD(bridge_list); |
| 56 | static LIST_HEAD(ioapic_list); | ||
| 57 | static DEFINE_SPINLOCK(ioapic_list_lock); | ||
| 56 | 58 | ||
| 57 | #define MY_NAME "acpiphp_glue" | 59 | #define MY_NAME "acpiphp_glue" |
| 58 | 60 | ||
| @@ -797,6 +799,7 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 797 | struct pci_dev *pdev; | 799 | struct pci_dev *pdev; |
| 798 | u32 gsi_base; | 800 | u32 gsi_base; |
| 799 | u64 phys_addr; | 801 | u64 phys_addr; |
| 802 | struct acpiphp_ioapic *ioapic; | ||
| 800 | 803 | ||
| 801 | /* Evaluate _STA if present */ | 804 | /* Evaluate _STA if present */ |
| 802 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 805 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
| @@ -811,41 +814,107 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 811 | if (get_gsi_base(handle, &gsi_base)) | 814 | if (get_gsi_base(handle, &gsi_base)) |
| 812 | return AE_OK; | 815 | return AE_OK; |
| 813 | 816 | ||
| 817 | ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); | ||
| 818 | if (!ioapic) | ||
| 819 | return AE_NO_MEMORY; | ||
| 820 | |||
| 814 | pdev = get_apic_pci_info(handle); | 821 | pdev = get_apic_pci_info(handle); |
| 815 | if (!pdev) | 822 | if (!pdev) |
| 816 | return AE_OK; | 823 | goto exit_kfree; |
| 817 | 824 | ||
| 818 | if (pci_enable_device(pdev)) { | 825 | if (pci_enable_device(pdev)) |
| 819 | pci_dev_put(pdev); | 826 | goto exit_pci_dev_put; |
| 820 | return AE_OK; | ||
| 821 | } | ||
| 822 | 827 | ||
| 823 | pci_set_master(pdev); | 828 | pci_set_master(pdev); |
| 824 | 829 | ||
| 825 | if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) { | 830 | if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) |
| 826 | pci_disable_device(pdev); | 831 | goto exit_pci_disable_device; |
| 827 | pci_dev_put(pdev); | ||
| 828 | return AE_OK; | ||
| 829 | } | ||
| 830 | 832 | ||
| 831 | phys_addr = pci_resource_start(pdev, 0); | 833 | phys_addr = pci_resource_start(pdev, 0); |
| 832 | if (acpi_register_ioapic(handle, phys_addr, gsi_base)) { | 834 | if (acpi_register_ioapic(handle, phys_addr, gsi_base)) |
| 833 | pci_release_region(pdev, 0); | 835 | goto exit_pci_release_region; |
| 834 | pci_disable_device(pdev); | 836 | |
| 835 | pci_dev_put(pdev); | 837 | ioapic->gsi_base = gsi_base; |
| 838 | ioapic->dev = pdev; | ||
| 839 | spin_lock(&ioapic_list_lock); | ||
| 840 | list_add_tail(&ioapic->list, &ioapic_list); | ||
| 841 | spin_unlock(&ioapic_list_lock); | ||
| 842 | |||
| 843 | return AE_OK; | ||
| 844 | |||
| 845 | exit_pci_release_region: | ||
| 846 | pci_release_region(pdev, 0); | ||
| 847 | exit_pci_disable_device: | ||
| 848 | pci_disable_device(pdev); | ||
| 849 | exit_pci_dev_put: | ||
| 850 | pci_dev_put(pdev); | ||
| 851 | exit_kfree: | ||
| 852 | kfree(ioapic); | ||
| 853 | |||
| 854 | return AE_OK; | ||
| 855 | } | ||
| 856 | |||
| 857 | static acpi_status | ||
| 858 | ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
| 859 | { | ||
| 860 | acpi_status status; | ||
| 861 | unsigned long sta; | ||
| 862 | acpi_handle tmp; | ||
| 863 | u32 gsi_base; | ||
| 864 | struct acpiphp_ioapic *pos, *n, *ioapic = NULL; | ||
| 865 | |||
| 866 | /* Evaluate _STA if present */ | ||
| 867 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | ||
| 868 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) | ||
| 869 | return AE_CTRL_DEPTH; | ||
| 870 | |||
| 871 | /* Scan only PCI bus scope */ | ||
| 872 | status = acpi_get_handle(handle, "_HID", &tmp); | ||
| 873 | if (ACPI_SUCCESS(status)) | ||
| 874 | return AE_CTRL_DEPTH; | ||
| 875 | |||
| 876 | if (get_gsi_base(handle, &gsi_base)) | ||
| 836 | return AE_OK; | 877 | return AE_OK; |
| 878 | |||
| 879 | acpi_unregister_ioapic(handle, gsi_base); | ||
| 880 | |||
| 881 | spin_lock(&ioapic_list_lock); | ||
| 882 | list_for_each_entry_safe(pos, n, &ioapic_list, list) { | ||
| 883 | if (pos->gsi_base != gsi_base) | ||
| 884 | continue; | ||
| 885 | ioapic = pos; | ||
| 886 | list_del(&ioapic->list); | ||
| 887 | break; | ||
| 837 | } | 888 | } |
| 889 | spin_unlock(&ioapic_list_lock); | ||
| 890 | |||
| 891 | if (!ioapic) | ||
| 892 | return AE_OK; | ||
| 893 | |||
| 894 | pci_release_region(ioapic->dev, 0); | ||
| 895 | pci_disable_device(ioapic->dev); | ||
| 896 | pci_dev_put(ioapic->dev); | ||
| 897 | kfree(ioapic); | ||
| 838 | 898 | ||
| 839 | return AE_OK; | 899 | return AE_OK; |
| 840 | } | 900 | } |
| 841 | 901 | ||
| 842 | static int acpiphp_configure_ioapics(acpi_handle handle) | 902 | static int acpiphp_configure_ioapics(acpi_handle handle) |
| 843 | { | 903 | { |
| 904 | ioapic_add(handle, 0, NULL, NULL); | ||
| 844 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 905 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
| 845 | ACPI_UINT32_MAX, ioapic_add, NULL, NULL); | 906 | ACPI_UINT32_MAX, ioapic_add, NULL, NULL); |
| 846 | return 0; | 907 | return 0; |
| 847 | } | 908 | } |
| 848 | 909 | ||
| 910 | static int acpiphp_unconfigure_ioapics(acpi_handle handle) | ||
| 911 | { | ||
| 912 | ioapic_remove(handle, 0, NULL, NULL); | ||
| 913 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
| 914 | ACPI_UINT32_MAX, ioapic_remove, NULL, NULL); | ||
| 915 | return 0; | ||
| 916 | } | ||
| 917 | |||
| 849 | static int power_on_slot(struct acpiphp_slot *slot) | 918 | static int power_on_slot(struct acpiphp_slot *slot) |
| 850 | { | 919 | { |
| 851 | acpi_status status; | 920 | acpi_status status; |
| @@ -997,7 +1066,7 @@ acpiphp_bus_add_out: | |||
| 997 | * @handle: handle to acpi namespace | 1066 | * @handle: handle to acpi namespace |
| 998 | * | 1067 | * |
| 999 | */ | 1068 | */ |
| 1000 | int acpiphp_bus_trim(acpi_handle handle) | 1069 | static int acpiphp_bus_trim(acpi_handle handle) |
| 1001 | { | 1070 | { |
| 1002 | struct acpi_device *device; | 1071 | struct acpi_device *device; |
| 1003 | int retval; | 1072 | int retval; |
| @@ -1074,10 +1143,11 @@ static int enable_device(struct acpiphp_slot *slot) | |||
| 1074 | 1143 | ||
| 1075 | pci_bus_assign_resources(bus); | 1144 | pci_bus_assign_resources(bus); |
| 1076 | acpiphp_sanitize_bus(bus); | 1145 | acpiphp_sanitize_bus(bus); |
| 1146 | acpiphp_set_hpp_values(slot->bridge->handle, bus); | ||
| 1147 | list_for_each_entry(func, &slot->funcs, sibling) | ||
| 1148 | acpiphp_configure_ioapics(func->handle); | ||
| 1077 | pci_enable_bridges(bus); | 1149 | pci_enable_bridges(bus); |
| 1078 | pci_bus_add_devices(bus); | 1150 | pci_bus_add_devices(bus); |
| 1079 | acpiphp_set_hpp_values(slot->bridge->handle, bus); | ||
| 1080 | acpiphp_configure_ioapics(slot->bridge->handle); | ||
| 1081 | 1151 | ||
| 1082 | /* associate pci_dev to our representation */ | 1152 | /* associate pci_dev to our representation */ |
| 1083 | list_for_each (l, &slot->funcs) { | 1153 | list_for_each (l, &slot->funcs) { |
| @@ -1103,6 +1173,16 @@ static int enable_device(struct acpiphp_slot *slot) | |||
| 1103 | return retval; | 1173 | return retval; |
| 1104 | } | 1174 | } |
| 1105 | 1175 | ||
| 1176 | static void disable_bridges(struct pci_bus *bus) | ||
| 1177 | { | ||
| 1178 | struct pci_dev *dev; | ||
| 1179 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 1180 | if (dev->subordinate) { | ||
| 1181 | disable_bridges(dev->subordinate); | ||
| 1182 | pci_disable_device(dev); | ||
| 1183 | } | ||
| 1184 | } | ||
| 1185 | } | ||
| 1106 | 1186 | ||
| 1107 | /** | 1187 | /** |
| 1108 | * disable_device - disable a slot | 1188 | * disable_device - disable a slot |
| @@ -1127,6 +1207,19 @@ static int disable_device(struct acpiphp_slot *slot) | |||
| 1127 | func->bridge = NULL; | 1207 | func->bridge = NULL; |
| 1128 | } | 1208 | } |
| 1129 | 1209 | ||
| 1210 | if (func->pci_dev) { | ||
| 1211 | pci_stop_bus_device(func->pci_dev); | ||
| 1212 | if (func->pci_dev->subordinate) { | ||
| 1213 | disable_bridges(func->pci_dev->subordinate); | ||
| 1214 | pci_disable_device(func->pci_dev); | ||
| 1215 | } | ||
| 1216 | } | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | list_for_each (l, &slot->funcs) { | ||
| 1220 | func = list_entry(l, struct acpiphp_func, sibling); | ||
| 1221 | |||
| 1222 | acpiphp_unconfigure_ioapics(func->handle); | ||
| 1130 | acpiphp_bus_trim(func->handle); | 1223 | acpiphp_bus_trim(func->handle); |
| 1131 | /* try to remove anyway. | 1224 | /* try to remove anyway. |
| 1132 | * acpiphp_bus_add might have been failed */ | 1225 | * acpiphp_bus_add might have been failed */ |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index dd2b762777c4..05a4f0f90186 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
| @@ -176,7 +176,9 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
| 176 | struct pci_bus *bus = temp->bus; | 176 | struct pci_bus *bus = temp->bus; |
| 177 | struct pci_dev *dev; | 177 | struct pci_dev *dev; |
| 178 | int func; | 178 | int func; |
| 179 | int retval; | ||
| 179 | u8 hdr_type; | 180 | u8 hdr_type; |
| 181 | |||
| 180 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | 182 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { |
| 181 | temp->hdr_type = hdr_type & 0x7f; | 183 | temp->hdr_type = hdr_type & 0x7f; |
| 182 | if (!pci_find_slot(bus->number, temp->devfn)) { | 184 | if (!pci_find_slot(bus->number, temp->devfn)) { |
| @@ -185,8 +187,12 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
| 185 | dbg("New device on %s function %x:%x\n", | 187 | dbg("New device on %s function %x:%x\n", |
| 186 | bus->name, temp->devfn >> 3, | 188 | bus->name, temp->devfn >> 3, |
| 187 | temp->devfn & 7); | 189 | temp->devfn & 7); |
| 188 | pci_bus_add_device(dev); | 190 | retval = pci_bus_add_device(dev); |
| 189 | add_slot(dev); | 191 | if (retval) |
| 192 | dev_err(&dev->dev, "error adding " | ||
| 193 | "device, continuing.\n"); | ||
| 194 | else | ||
| 195 | add_slot(dev); | ||
| 190 | } | 196 | } |
| 191 | } | 197 | } |
| 192 | /* multifunction device? */ | 198 | /* multifunction device? */ |
| @@ -205,8 +211,12 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
| 205 | dbg("New device on %s function %x:%x\n", | 211 | dbg("New device on %s function %x:%x\n", |
| 206 | bus->name, temp->devfn >> 3, | 212 | bus->name, temp->devfn >> 3, |
| 207 | temp->devfn & 7); | 213 | temp->devfn & 7); |
| 208 | pci_bus_add_device(dev); | 214 | retval = pci_bus_add_device(dev); |
| 209 | add_slot(dev); | 215 | if (retval) |
| 216 | dev_err(&dev->dev, "error adding " | ||
| 217 | "device, continuing.\n"); | ||
| 218 | else | ||
| 219 | add_slot(dev); | ||
| 210 | } | 220 | } |
| 211 | } | 221 | } |
| 212 | } | 222 | } |
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index e929b7c11429..772523dc3860 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h | |||
| @@ -172,8 +172,8 @@ struct hotplug_slot { | |||
| 172 | 172 | ||
| 173 | extern int pci_hp_register (struct hotplug_slot *slot); | 173 | extern int pci_hp_register (struct hotplug_slot *slot); |
| 174 | extern int pci_hp_deregister (struct hotplug_slot *slot); | 174 | extern int pci_hp_deregister (struct hotplug_slot *slot); |
| 175 | extern int pci_hp_change_slot_info (struct hotplug_slot *slot, | 175 | extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, |
| 176 | struct hotplug_slot_info *info); | 176 | struct hotplug_slot_info *info); |
| 177 | extern struct subsystem pci_hotplug_slots_subsys; | 177 | extern struct subsystem pci_hotplug_slots_subsys; |
| 178 | 178 | ||
| 179 | /* PCI Setting Record (Type 0) */ | 179 | /* PCI Setting Record (Type 0) */ |
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index b7b378df89e3..e2823ea9c4ed 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -482,31 +482,95 @@ static int has_test_file (struct hotplug_slot *slot) | |||
| 482 | 482 | ||
| 483 | static int fs_add_slot (struct hotplug_slot *slot) | 483 | static int fs_add_slot (struct hotplug_slot *slot) |
| 484 | { | 484 | { |
| 485 | if (has_power_file(slot) == 0) | 485 | int retval = 0; |
| 486 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr); | ||
| 487 | 486 | ||
| 488 | if (has_attention_file(slot) == 0) | 487 | if (has_power_file(slot) == 0) { |
| 489 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr); | 488 | retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr); |
| 489 | if (retval) | ||
| 490 | goto exit_power; | ||
| 491 | } | ||
| 490 | 492 | ||
| 491 | if (has_latch_file(slot) == 0) | 493 | if (has_attention_file(slot) == 0) { |
| 492 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr); | 494 | retval = sysfs_create_file(&slot->kobj, |
| 495 | &hotplug_slot_attr_attention.attr); | ||
| 496 | if (retval) | ||
| 497 | goto exit_attention; | ||
| 498 | } | ||
| 493 | 499 | ||
| 494 | if (has_adapter_file(slot) == 0) | 500 | if (has_latch_file(slot) == 0) { |
| 495 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr); | 501 | retval = sysfs_create_file(&slot->kobj, |
| 502 | &hotplug_slot_attr_latch.attr); | ||
| 503 | if (retval) | ||
| 504 | goto exit_latch; | ||
| 505 | } | ||
| 496 | 506 | ||
| 497 | if (has_address_file(slot) == 0) | 507 | if (has_adapter_file(slot) == 0) { |
| 498 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr); | 508 | retval = sysfs_create_file(&slot->kobj, |
| 509 | &hotplug_slot_attr_presence.attr); | ||
| 510 | if (retval) | ||
| 511 | goto exit_adapter; | ||
| 512 | } | ||
| 499 | 513 | ||
| 500 | if (has_max_bus_speed_file(slot) == 0) | 514 | if (has_address_file(slot) == 0) { |
| 501 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); | 515 | retval = sysfs_create_file(&slot->kobj, |
| 516 | &hotplug_slot_attr_address.attr); | ||
| 517 | if (retval) | ||
| 518 | goto exit_address; | ||
| 519 | } | ||
| 502 | 520 | ||
| 521 | if (has_max_bus_speed_file(slot) == 0) { | ||
| 522 | retval = sysfs_create_file(&slot->kobj, | ||
| 523 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 524 | if (retval) | ||
| 525 | goto exit_max_speed; | ||
| 526 | } | ||
| 527 | |||
| 528 | if (has_cur_bus_speed_file(slot) == 0) { | ||
| 529 | retval = sysfs_create_file(&slot->kobj, | ||
| 530 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 531 | if (retval) | ||
| 532 | goto exit_cur_speed; | ||
| 533 | } | ||
| 534 | |||
| 535 | if (has_test_file(slot) == 0) { | ||
| 536 | retval = sysfs_create_file(&slot->kobj, | ||
| 537 | &hotplug_slot_attr_test.attr); | ||
| 538 | if (retval) | ||
| 539 | goto exit_test; | ||
| 540 | } | ||
| 541 | |||
| 542 | goto exit; | ||
| 543 | |||
| 544 | exit_test: | ||
| 503 | if (has_cur_bus_speed_file(slot) == 0) | 545 | if (has_cur_bus_speed_file(slot) == 0) |
| 504 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); | 546 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); |
| 505 | 547 | ||
| 506 | if (has_test_file(slot) == 0) | 548 | exit_cur_speed: |
| 507 | sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr); | 549 | if (has_max_bus_speed_file(slot) == 0) |
| 550 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); | ||
| 508 | 551 | ||
| 509 | return 0; | 552 | exit_max_speed: |
| 553 | if (has_address_file(slot) == 0) | ||
| 554 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr); | ||
| 555 | |||
| 556 | exit_address: | ||
| 557 | if (has_adapter_file(slot) == 0) | ||
| 558 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); | ||
| 559 | |||
| 560 | exit_adapter: | ||
| 561 | if (has_latch_file(slot) == 0) | ||
| 562 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr); | ||
| 563 | |||
| 564 | exit_latch: | ||
| 565 | if (has_attention_file(slot) == 0) | ||
| 566 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr); | ||
| 567 | |||
| 568 | exit_attention: | ||
| 569 | if (has_power_file(slot) == 0) | ||
| 570 | sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); | ||
| 571 | exit_power: | ||
| 572 | exit: | ||
| 573 | return retval; | ||
| 510 | } | 574 | } |
| 511 | 575 | ||
| 512 | static void fs_remove_slot (struct hotplug_slot *slot) | 576 | static void fs_remove_slot (struct hotplug_slot *slot) |
| @@ -626,8 +690,11 @@ int pci_hp_deregister (struct hotplug_slot *slot) | |||
| 626 | * | 690 | * |
| 627 | * Returns 0 if successful, anything else for an error. | 691 | * Returns 0 if successful, anything else for an error. |
| 628 | */ | 692 | */ |
| 629 | int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info) | 693 | int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, |
| 694 | struct hotplug_slot_info *info) | ||
| 630 | { | 695 | { |
| 696 | int retval; | ||
| 697 | |||
| 631 | if ((slot == NULL) || (info == NULL)) | 698 | if ((slot == NULL) || (info == NULL)) |
| 632 | return -ENODEV; | 699 | return -ENODEV; |
| 633 | 700 | ||
| @@ -636,32 +703,60 @@ int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info | |||
| 636 | * for the files referring to the fields that have now changed. | 703 | * for the files referring to the fields that have now changed. |
| 637 | */ | 704 | */ |
| 638 | if ((has_power_file(slot) == 0) && | 705 | if ((has_power_file(slot) == 0) && |
| 639 | (slot->info->power_status != info->power_status)) | 706 | (slot->info->power_status != info->power_status)) { |
| 640 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr); | 707 | retval = sysfs_update_file(&slot->kobj, |
| 708 | &hotplug_slot_attr_power.attr); | ||
| 709 | if (retval) | ||
| 710 | return retval; | ||
| 711 | } | ||
| 641 | 712 | ||
| 642 | if ((has_attention_file(slot) == 0) && | 713 | if ((has_attention_file(slot) == 0) && |
| 643 | (slot->info->attention_status != info->attention_status)) | 714 | (slot->info->attention_status != info->attention_status)) { |
| 644 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr); | 715 | retval = sysfs_update_file(&slot->kobj, |
| 716 | &hotplug_slot_attr_attention.attr); | ||
| 717 | if (retval) | ||
| 718 | return retval; | ||
| 719 | } | ||
| 645 | 720 | ||
| 646 | if ((has_latch_file(slot) == 0) && | 721 | if ((has_latch_file(slot) == 0) && |
| 647 | (slot->info->latch_status != info->latch_status)) | 722 | (slot->info->latch_status != info->latch_status)) { |
| 648 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr); | 723 | retval = sysfs_update_file(&slot->kobj, |
| 724 | &hotplug_slot_attr_latch.attr); | ||
| 725 | if (retval) | ||
| 726 | return retval; | ||
| 727 | } | ||
| 649 | 728 | ||
| 650 | if ((has_adapter_file(slot) == 0) && | 729 | if ((has_adapter_file(slot) == 0) && |
| 651 | (slot->info->adapter_status != info->adapter_status)) | 730 | (slot->info->adapter_status != info->adapter_status)) { |
| 652 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr); | 731 | retval = sysfs_update_file(&slot->kobj, |
| 732 | &hotplug_slot_attr_presence.attr); | ||
| 733 | if (retval) | ||
| 734 | return retval; | ||
| 735 | } | ||
| 653 | 736 | ||
| 654 | if ((has_address_file(slot) == 0) && | 737 | if ((has_address_file(slot) == 0) && |
| 655 | (slot->info->address != info->address)) | 738 | (slot->info->address != info->address)) { |
| 656 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr); | 739 | retval = sysfs_update_file(&slot->kobj, |
| 740 | &hotplug_slot_attr_address.attr); | ||
| 741 | if (retval) | ||
| 742 | return retval; | ||
| 743 | } | ||
| 657 | 744 | ||
| 658 | if ((has_max_bus_speed_file(slot) == 0) && | 745 | if ((has_max_bus_speed_file(slot) == 0) && |
| 659 | (slot->info->max_bus_speed != info->max_bus_speed)) | 746 | (slot->info->max_bus_speed != info->max_bus_speed)) { |
| 660 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); | 747 | retval = sysfs_update_file(&slot->kobj, |
| 748 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 749 | if (retval) | ||
| 750 | return retval; | ||
| 751 | } | ||
| 661 | 752 | ||
| 662 | if ((has_cur_bus_speed_file(slot) == 0) && | 753 | if ((has_cur_bus_speed_file(slot) == 0) && |
| 663 | (slot->info->cur_bus_speed != info->cur_bus_speed)) | 754 | (slot->info->cur_bus_speed != info->cur_bus_speed)) { |
| 664 | sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr); | 755 | retval = sysfs_update_file(&slot->kobj, |
| 756 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 757 | if (retval) | ||
| 758 | return retval; | ||
| 759 | } | ||
| 665 | 760 | ||
| 666 | memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); | 761 | memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); |
| 667 | 762 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 33d198768356..41290a106bd8 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -762,14 +762,14 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 762 | if (rc || !getstatus) { | 762 | if (rc || !getstatus) { |
| 763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 763 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 764 | mutex_unlock(&p_slot->ctrl->crit_sect); | 764 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 765 | return 1; | 765 | return -ENODEV; |
| 766 | } | 766 | } |
| 767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { | 767 | if (MRL_SENS(p_slot->ctrl->ctrlcap)) { |
| 768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 768 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
| 769 | if (rc || getstatus) { | 769 | if (rc || getstatus) { |
| 770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 770 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 771 | mutex_unlock(&p_slot->ctrl->crit_sect); | 771 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 772 | return 1; | 772 | return -ENODEV; |
| 773 | } | 773 | } |
| 774 | } | 774 | } |
| 775 | 775 | ||
| @@ -778,7 +778,7 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 778 | if (rc || getstatus) { | 778 | if (rc || getstatus) { |
| 779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); | 779 | info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 780 | mutex_unlock(&p_slot->ctrl->crit_sect); | 780 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 781 | return 1; | 781 | return -EINVAL; |
| 782 | } | 782 | } |
| 783 | } | 783 | } |
| 784 | mutex_unlock(&p_slot->ctrl->crit_sect); | 784 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| @@ -813,7 +813,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 813 | if (ret || !getstatus) { | 813 | if (ret || !getstatus) { |
| 814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); | 814 | info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 815 | mutex_unlock(&p_slot->ctrl->crit_sect); | 815 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 816 | return 1; | 816 | return -ENODEV; |
| 817 | } | 817 | } |
| 818 | } | 818 | } |
| 819 | 819 | ||
| @@ -822,7 +822,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 822 | if (ret || getstatus) { | 822 | if (ret || getstatus) { |
| 823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); | 823 | info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); |
| 824 | mutex_unlock(&p_slot->ctrl->crit_sect); | 824 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 825 | return 1; | 825 | return -ENODEV; |
| 826 | } | 826 | } |
| 827 | } | 827 | } |
| 828 | 828 | ||
| @@ -831,7 +831,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 831 | if (ret || !getstatus) { | 831 | if (ret || !getstatus) { |
| 832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); | 832 | info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); |
| 833 | mutex_unlock(&p_slot->ctrl->crit_sect); | 833 | mutex_unlock(&p_slot->ctrl->crit_sect); |
| 834 | return 1; | 834 | return -EINVAL; |
| 835 | } | 835 | } |
| 836 | } | 836 | } |
| 837 | 837 | ||
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 8ad446605f75..2b9e10e38613 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PCI Hot Plug Controller Skeleton Driver - 0.2 | 2 | * PCI Hot Plug Controller Skeleton Driver - 0.3 |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) |
| 5 | * Copyright (C) 2001,2003 IBM Corp. | 5 | * Copyright (C) 2001,2003 IBM Corp. |
| @@ -21,7 +21,7 @@ | |||
| 21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
| 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 23 | * | 23 | * |
| 24 | * This driver is to be used as a skeleton driver to be show how to interface | 24 | * This driver is to be used as a skeleton driver to show how to interface |
| 25 | * with the pci hotplug core easily. | 25 | * with the pci hotplug core easily. |
| 26 | * | 26 | * |
| 27 | * Send feedback to <greg@kroah.com> | 27 | * Send feedback to <greg@kroah.com> |
| @@ -58,8 +58,6 @@ static LIST_HEAD(slot_list); | |||
| 58 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) | 58 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) |
| 59 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) | 59 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) |
| 60 | 60 | ||
| 61 | |||
| 62 | |||
| 63 | /* local variables */ | 61 | /* local variables */ |
| 64 | static int debug; | 62 | static int debug; |
| 65 | static int num_slots; | 63 | static int num_slots; |
| @@ -109,7 +107,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 109 | return retval; | 107 | return retval; |
| 110 | } | 108 | } |
| 111 | 109 | ||
| 112 | |||
| 113 | static int disable_slot(struct hotplug_slot *hotplug_slot) | 110 | static int disable_slot(struct hotplug_slot *hotplug_slot) |
| 114 | { | 111 | { |
| 115 | struct slot *slot = hotplug_slot->private; | 112 | struct slot *slot = hotplug_slot->private; |
| @@ -342,7 +339,7 @@ static int __init pcihp_skel_init(void) | |||
| 342 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 339 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
| 343 | /* | 340 | /* |
| 344 | * Do specific initialization stuff for your driver here | 341 | * Do specific initialization stuff for your driver here |
| 345 | * Like initializing your controller hardware (if any) and | 342 | * like initializing your controller hardware (if any) and |
| 346 | * determining the number of slots you have in the system | 343 | * determining the number of slots you have in the system |
| 347 | * right now. | 344 | * right now. |
| 348 | */ | 345 | */ |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7208b95c6ee7..c7103ac5cd06 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -173,7 +173,7 @@ struct controller { | |||
| 173 | #define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" | 173 | #define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" |
| 174 | 174 | ||
| 175 | /* sysfs functions for the hotplug controller info */ | 175 | /* sysfs functions for the hotplug controller info */ |
| 176 | extern void shpchp_create_ctrl_files (struct controller *ctrl); | 176 | extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl); |
| 177 | 177 | ||
| 178 | extern int shpchp_sysfs_enable_slot(struct slot *slot); | 178 | extern int shpchp_sysfs_enable_slot(struct slot *slot); |
| 179 | extern int shpchp_sysfs_disable_slot(struct slot *slot); | 179 | extern int shpchp_sysfs_disable_slot(struct slot *slot); |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a14e7de19846..235c18a22393 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
| @@ -449,10 +449,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 449 | ctrl->speed = PCI_SPEED_33MHz; | 449 | ctrl->speed = PCI_SPEED_33MHz; |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | shpchp_create_ctrl_files(ctrl); | 452 | rc = shpchp_create_ctrl_files(ctrl); |
| 453 | if (rc) | ||
| 454 | goto err_cleanup_slots; | ||
| 453 | 455 | ||
| 454 | return 0; | 456 | return 0; |
| 455 | 457 | ||
| 458 | err_cleanup_slots: | ||
| 459 | cleanup_slots(ctrl); | ||
| 456 | err_out_release_ctlr: | 460 | err_out_release_ctlr: |
| 457 | ctrl->hpc_ops->release_ctlr(ctrl); | 461 | ctrl->hpc_ops->release_ctlr(ctrl); |
| 458 | err_out_free_ctrl: | 462 | err_out_free_ctrl: |
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 620e1139e607..29fa9d26adae 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c | |||
| @@ -91,9 +91,9 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
| 91 | } | 91 | } |
| 92 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); | 92 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); |
| 93 | 93 | ||
| 94 | void shpchp_create_ctrl_files (struct controller *ctrl) | 94 | int __must_check shpchp_create_ctrl_files (struct controller *ctrl) |
| 95 | { | 95 | { |
| 96 | device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); | 96 | return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void shpchp_remove_ctrl_files(struct controller *ctrl) | 99 | void shpchp_remove_ctrl_files(struct controller *ctrl) |
