aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/acpiphp.h5
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c43
3 files changed, 43 insertions, 7 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 1592dbe4f904..b6162be4df40 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -77,6 +77,8 @@ struct acpiphp_bridge {
77 77
78 /* PCI-to-PCI bridge device */ 78 /* PCI-to-PCI bridge device */
79 struct pci_dev *pci_dev; 79 struct pci_dev *pci_dev;
80
81 bool is_going_away;
80}; 82};
81 83
82 84
@@ -150,6 +152,7 @@ struct acpiphp_attention_info
150/* slot flags */ 152/* slot flags */
151 153
152#define SLOT_ENABLED (0x00000001) 154#define SLOT_ENABLED (0x00000001)
155#define SLOT_IS_GOING_AWAY (0x00000002)
153 156
154/* function flags */ 157/* function flags */
155 158
@@ -169,7 +172,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
169typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); 172typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
170 173
171int acpiphp_enable_slot(struct acpiphp_slot *slot); 174int acpiphp_enable_slot(struct acpiphp_slot *slot);
172int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); 175int acpiphp_disable_slot(struct acpiphp_slot *slot);
173u8 acpiphp_get_power_status(struct acpiphp_slot *slot); 176u8 acpiphp_get_power_status(struct acpiphp_slot *slot);
174u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); 177u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);
175u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); 178u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index dca66bc44578..728c31f4c2c5 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
156 pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); 156 pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
157 157
158 /* disable the specified slot */ 158 /* disable the specified slot */
159 return acpiphp_disable_and_eject_slot(slot->acpi_slot); 159 return acpiphp_disable_slot(slot->acpi_slot);
160} 160}
161 161
162 162
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 1cf605f67673..641ba6761bd7 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -430,6 +430,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
430 pr_err("failed to remove notify handler\n"); 430 pr_err("failed to remove notify handler\n");
431 } 431 }
432 } 432 }
433 slot->flags |= SLOT_IS_GOING_AWAY;
433 if (slot->slot) 434 if (slot->slot)
434 acpiphp_unregister_hotplug_slot(slot); 435 acpiphp_unregister_hotplug_slot(slot);
435 } 436 }
@@ -437,6 +438,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
437 mutex_lock(&bridge_mutex); 438 mutex_lock(&bridge_mutex);
438 list_del(&bridge->list); 439 list_del(&bridge->list);
439 mutex_unlock(&bridge_mutex); 440 mutex_unlock(&bridge_mutex);
441
442 bridge->is_going_away = true;
440} 443}
441 444
442/** 445/**
@@ -736,6 +739,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
736{ 739{
737 struct acpiphp_slot *slot; 740 struct acpiphp_slot *slot;
738 741
742 /* Bail out if the bridge is going away. */
743 if (bridge->is_going_away)
744 return;
745
739 list_for_each_entry(slot, &bridge->slots, node) { 746 list_for_each_entry(slot, &bridge->slots, node) {
740 struct pci_bus *bus = slot->bus; 747 struct pci_bus *bus = slot->bus;
741 struct pci_dev *dev, *tmp; 748 struct pci_dev *dev, *tmp;
@@ -805,6 +812,8 @@ void acpiphp_check_host_bridge(acpi_handle handle)
805 } 812 }
806} 813}
807 814
815static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
816
808static void hotplug_event(acpi_handle handle, u32 type, void *data) 817static void hotplug_event(acpi_handle handle, u32 type, void *data)
809{ 818{
810 struct acpiphp_context *context = data; 819 struct acpiphp_context *context = data;
@@ -834,6 +843,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
834 } else { 843 } else {
835 struct acpiphp_slot *slot = func->slot; 844 struct acpiphp_slot *slot = func->slot;
836 845
846 if (slot->flags & SLOT_IS_GOING_AWAY)
847 break;
848
837 mutex_lock(&slot->crit_sect); 849 mutex_lock(&slot->crit_sect);
838 enable_slot(slot); 850 enable_slot(slot);
839 mutex_unlock(&slot->crit_sect); 851 mutex_unlock(&slot->crit_sect);
@@ -849,6 +861,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
849 struct acpiphp_slot *slot = func->slot; 861 struct acpiphp_slot *slot = func->slot;
850 int ret; 862 int ret;
851 863
864 if (slot->flags & SLOT_IS_GOING_AWAY)
865 break;
866
852 /* 867 /*
853 * Check if anything has changed in the slot and rescan 868 * Check if anything has changed in the slot and rescan
854 * from the parent if that's the case. 869 * from the parent if that's the case.
@@ -878,9 +893,11 @@ static void hotplug_event_work(void *data, u32 type)
878 acpi_handle handle = context->handle; 893 acpi_handle handle = context->handle;
879 894
880 acpi_scan_lock_acquire(); 895 acpi_scan_lock_acquire();
896 pci_lock_rescan_remove();
881 897
882 hotplug_event(handle, type, context); 898 hotplug_event(handle, type, context);
883 899
900 pci_unlock_rescan_remove();
884 acpi_scan_lock_release(); 901 acpi_scan_lock_release();
885 acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); 902 acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
886 put_bridge(context->func.parent); 903 put_bridge(context->func.parent);
@@ -1048,12 +1065,19 @@ void acpiphp_remove_slots(struct pci_bus *bus)
1048 */ 1065 */
1049int acpiphp_enable_slot(struct acpiphp_slot *slot) 1066int acpiphp_enable_slot(struct acpiphp_slot *slot)
1050{ 1067{
1068 pci_lock_rescan_remove();
1069
1070 if (slot->flags & SLOT_IS_GOING_AWAY)
1071 return -ENODEV;
1072
1051 mutex_lock(&slot->crit_sect); 1073 mutex_lock(&slot->crit_sect);
1052 /* configure all functions */ 1074 /* configure all functions */
1053 if (!(slot->flags & SLOT_ENABLED)) 1075 if (!(slot->flags & SLOT_ENABLED))
1054 enable_slot(slot); 1076 enable_slot(slot);
1055 1077
1056 mutex_unlock(&slot->crit_sect); 1078 mutex_unlock(&slot->crit_sect);
1079
1080 pci_unlock_rescan_remove();
1057 return 0; 1081 return 0;
1058} 1082}
1059 1083
@@ -1061,10 +1085,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
1061 * acpiphp_disable_and_eject_slot - power off and eject slot 1085 * acpiphp_disable_and_eject_slot - power off and eject slot
1062 * @slot: ACPI PHP slot 1086 * @slot: ACPI PHP slot
1063 */ 1087 */
1064int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) 1088static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
1065{ 1089{
1066 struct acpiphp_func *func; 1090 struct acpiphp_func *func;
1067 int retval = 0; 1091
1092 if (slot->flags & SLOT_IS_GOING_AWAY)
1093 return -ENODEV;
1068 1094
1069 mutex_lock(&slot->crit_sect); 1095 mutex_lock(&slot->crit_sect);
1070 1096
@@ -1082,9 +1108,18 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
1082 } 1108 }
1083 1109
1084 mutex_unlock(&slot->crit_sect); 1110 mutex_unlock(&slot->crit_sect);
1085 return retval; 1111 return 0;
1086} 1112}
1087 1113
1114int acpiphp_disable_slot(struct acpiphp_slot *slot)
1115{
1116 int ret;
1117
1118 pci_lock_rescan_remove();
1119 ret = acpiphp_disable_and_eject_slot(slot);
1120 pci_unlock_rescan_remove();
1121 return ret;
1122}
1088 1123
1089/* 1124/*
1090 * slot enabled: 1 1125 * slot enabled: 1
@@ -1095,7 +1130,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
1095 return (slot->flags & SLOT_ENABLED); 1130 return (slot->flags & SLOT_ENABLED);
1096} 1131}
1097 1132
1098
1099/* 1133/*
1100 * latch open: 1 1134 * latch open: 1
1101 * latch closed: 0 1135 * latch closed: 0
@@ -1105,7 +1139,6 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
1105 return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); 1139 return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI);
1106} 1140}
1107 1141
1108
1109/* 1142/*
1110 * adapter presence : 1 1143 * adapter presence : 1
1111 * absence : 0 1144 * absence : 0