diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 54 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 18 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 999 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_ibm.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 18 |
5 files changed, 436 insertions, 655 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6c781edabcc6..f4e028924667 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -49,6 +49,7 @@ | |||
49 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 49 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
50 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 50 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) |
51 | 51 | ||
52 | struct acpiphp_context; | ||
52 | struct acpiphp_bridge; | 53 | struct acpiphp_bridge; |
53 | struct acpiphp_slot; | 54 | struct acpiphp_slot; |
54 | 55 | ||
@@ -59,6 +60,7 @@ struct slot { | |||
59 | struct hotplug_slot *hotplug_slot; | 60 | struct hotplug_slot *hotplug_slot; |
60 | struct acpiphp_slot *acpi_slot; | 61 | struct acpiphp_slot *acpi_slot; |
61 | struct hotplug_slot_info info; | 62 | struct hotplug_slot_info info; |
63 | unsigned int sun; /* ACPI _SUN (Slot User Number) value */ | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | static inline const char *slot_name(struct slot *slot) | 66 | static inline const char *slot_name(struct slot *slot) |
@@ -75,15 +77,11 @@ struct acpiphp_bridge { | |||
75 | struct list_head list; | 77 | struct list_head list; |
76 | struct list_head slots; | 78 | struct list_head slots; |
77 | struct kref ref; | 79 | struct kref ref; |
78 | acpi_handle handle; | ||
79 | 80 | ||
80 | /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ | 81 | struct acpiphp_context *context; |
81 | struct acpiphp_func *func; | ||
82 | 82 | ||
83 | int nr_slots; | 83 | int nr_slots; |
84 | 84 | ||
85 | u32 flags; | ||
86 | |||
87 | /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */ | 85 | /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */ |
88 | struct pci_bus *pci_bus; | 86 | struct pci_bus *pci_bus; |
89 | 87 | ||
@@ -99,15 +97,13 @@ struct acpiphp_bridge { | |||
99 | */ | 97 | */ |
100 | struct acpiphp_slot { | 98 | struct acpiphp_slot { |
101 | struct list_head node; | 99 | struct list_head node; |
102 | struct acpiphp_bridge *bridge; /* parent */ | 100 | struct pci_bus *bus; |
103 | struct list_head funcs; /* one slot may have different | 101 | struct list_head funcs; /* one slot may have different |
104 | objects (i.e. for each function) */ | 102 | objects (i.e. for each function) */ |
105 | struct slot *slot; | 103 | struct slot *slot; |
106 | struct mutex crit_sect; | 104 | struct mutex crit_sect; |
107 | 105 | ||
108 | u8 device; /* pci device# */ | 106 | u8 device; /* pci device# */ |
109 | |||
110 | unsigned long long sun; /* ACPI _SUN (slot unique number) */ | ||
111 | u32 flags; /* see below */ | 107 | u32 flags; /* see below */ |
112 | }; | 108 | }; |
113 | 109 | ||
@@ -119,15 +115,32 @@ struct acpiphp_slot { | |||
119 | * typically 8 objects per slot (i.e. for each PCI function) | 115 | * typically 8 objects per slot (i.e. for each PCI function) |
120 | */ | 116 | */ |
121 | struct acpiphp_func { | 117 | struct acpiphp_func { |
122 | struct acpiphp_slot *slot; /* parent */ | 118 | struct acpiphp_bridge *parent; |
119 | struct acpiphp_slot *slot; | ||
123 | 120 | ||
124 | struct list_head sibling; | 121 | struct list_head sibling; |
125 | acpi_handle handle; | ||
126 | 122 | ||
127 | u8 function; /* pci function# */ | 123 | u8 function; /* pci function# */ |
128 | u32 flags; /* see below */ | 124 | u32 flags; /* see below */ |
129 | }; | 125 | }; |
130 | 126 | ||
127 | struct acpiphp_context { | ||
128 | acpi_handle handle; | ||
129 | struct acpiphp_func func; | ||
130 | struct acpiphp_bridge *bridge; | ||
131 | unsigned int refcount; | ||
132 | }; | ||
133 | |||
134 | static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func) | ||
135 | { | ||
136 | return container_of(func, struct acpiphp_context, func); | ||
137 | } | ||
138 | |||
139 | static inline acpi_handle func_to_handle(struct acpiphp_func *func) | ||
140 | { | ||
141 | return func_to_context(func)->handle; | ||
142 | } | ||
143 | |||
131 | /* | 144 | /* |
132 | * struct acpiphp_attention_info - device specific attention registration | 145 | * struct acpiphp_attention_info - device specific attention registration |
133 | * | 146 | * |
@@ -141,45 +154,32 @@ struct acpiphp_attention_info | |||
141 | struct module *owner; | 154 | struct module *owner; |
142 | }; | 155 | }; |
143 | 156 | ||
144 | /* PCI bus bridge HID */ | ||
145 | #define ACPI_PCI_HOST_HID "PNP0A03" | ||
146 | |||
147 | /* ACPI _STA method value (ignore bit 4; battery present) */ | 157 | /* ACPI _STA method value (ignore bit 4; battery present) */ |
148 | #define ACPI_STA_ALL (0x0000000f) | 158 | #define ACPI_STA_ALL (0x0000000f) |
149 | 159 | ||
150 | /* bridge flags */ | ||
151 | #define BRIDGE_HAS_EJ0 (0x00000001) | ||
152 | |||
153 | /* slot flags */ | 160 | /* slot flags */ |
154 | 161 | ||
155 | #define SLOT_POWEREDON (0x00000001) | 162 | #define SLOT_ENABLED (0x00000001) |
156 | #define SLOT_ENABLED (0x00000002) | ||
157 | #define SLOT_MULTIFUNCTION (0x00000004) | ||
158 | 163 | ||
159 | /* function flags */ | 164 | /* function flags */ |
160 | 165 | ||
161 | #define FUNC_HAS_STA (0x00000001) | 166 | #define FUNC_HAS_STA (0x00000001) |
162 | #define FUNC_HAS_EJ0 (0x00000002) | 167 | #define FUNC_HAS_EJ0 (0x00000002) |
163 | #define FUNC_HAS_PS0 (0x00000010) | 168 | #define FUNC_HAS_DCK (0x00000004) |
164 | #define FUNC_HAS_PS1 (0x00000020) | ||
165 | #define FUNC_HAS_PS2 (0x00000040) | ||
166 | #define FUNC_HAS_PS3 (0x00000080) | ||
167 | #define FUNC_HAS_DCK (0x00000100) | ||
168 | 169 | ||
169 | /* function prototypes */ | 170 | /* function prototypes */ |
170 | 171 | ||
171 | /* acpiphp_core.c */ | 172 | /* acpiphp_core.c */ |
172 | int acpiphp_register_attention(struct acpiphp_attention_info*info); | 173 | int acpiphp_register_attention(struct acpiphp_attention_info*info); |
173 | int acpiphp_unregister_attention(struct acpiphp_attention_info *info); | 174 | int acpiphp_unregister_attention(struct acpiphp_attention_info *info); |
174 | int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); | 175 | int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun); |
175 | void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | 176 | void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); |
176 | 177 | ||
177 | /* acpiphp_glue.c */ | 178 | /* acpiphp_glue.c */ |
178 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 179 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
179 | 180 | ||
180 | int acpiphp_enable_slot(struct acpiphp_slot *slot); | 181 | int acpiphp_enable_slot(struct acpiphp_slot *slot); |
181 | int acpiphp_disable_slot(struct acpiphp_slot *slot); | 182 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); |
182 | int acpiphp_eject_slot(struct acpiphp_slot *slot); | ||
183 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); | 183 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); |
184 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); | 184 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); |
185 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); | 185 | u8 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 ca8127950fcd..bf2203ef1308 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -155,15 +155,11 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
155 | static int disable_slot(struct hotplug_slot *hotplug_slot) | 155 | static int disable_slot(struct hotplug_slot *hotplug_slot) |
156 | { | 156 | { |
157 | struct slot *slot = hotplug_slot->private; | 157 | struct slot *slot = hotplug_slot->private; |
158 | int retval; | ||
159 | 158 | ||
160 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 159 | dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
161 | 160 | ||
162 | /* disable the specified slot */ | 161 | /* disable the specified slot */ |
163 | retval = acpiphp_disable_slot(slot->acpi_slot); | 162 | return acpiphp_disable_and_eject_slot(slot->acpi_slot); |
164 | if (!retval) | ||
165 | retval = acpiphp_eject_slot(slot->acpi_slot); | ||
166 | return retval; | ||
167 | } | 163 | } |
168 | 164 | ||
169 | 165 | ||
@@ -290,7 +286,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
290 | } | 286 | } |
291 | 287 | ||
292 | /* callback routine to initialize 'struct slot' for each slot */ | 288 | /* callback routine to initialize 'struct slot' for each slot */ |
293 | int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | 289 | int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, |
290 | unsigned int sun) | ||
294 | { | 291 | { |
295 | struct slot *slot; | 292 | struct slot *slot; |
296 | int retval = -ENOMEM; | 293 | int retval = -ENOMEM; |
@@ -317,12 +314,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
317 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); | 314 | slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); |
318 | 315 | ||
319 | acpiphp_slot->slot = slot; | 316 | acpiphp_slot->slot = slot; |
320 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); | 317 | slot->sun = sun; |
318 | snprintf(name, SLOT_NAME_SIZE, "%u", sun); | ||
321 | 319 | ||
322 | retval = pci_hp_register(slot->hotplug_slot, | 320 | retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus, |
323 | acpiphp_slot->bridge->pci_bus, | 321 | acpiphp_slot->device, name); |
324 | acpiphp_slot->device, | ||
325 | name); | ||
326 | if (retval == -EBUSY) | 322 | if (retval == -EBUSY) |
327 | goto error_hpslot; | 323 | goto error_hpslot; |
328 | if (retval) { | 324 | if (retval) { |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 8bfad0dc29ab..8054ddcdaed0 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/pci.h> | 46 | #include <linux/pci.h> |
47 | #include <linux/pci_hotplug.h> | 47 | #include <linux/pci_hotplug.h> |
48 | #include <linux/pci-acpi.h> | 48 | #include <linux/pci-acpi.h> |
49 | #include <linux/pm_runtime.h> | ||
49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
50 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
51 | #include <linux/acpi.h> | 52 | #include <linux/acpi.h> |
@@ -55,28 +56,82 @@ | |||
55 | 56 | ||
56 | static LIST_HEAD(bridge_list); | 57 | static LIST_HEAD(bridge_list); |
57 | static DEFINE_MUTEX(bridge_mutex); | 58 | static DEFINE_MUTEX(bridge_mutex); |
59 | static DEFINE_MUTEX(acpiphp_context_lock); | ||
58 | 60 | ||
59 | #define MY_NAME "acpiphp_glue" | 61 | #define MY_NAME "acpiphp_glue" |
60 | 62 | ||
61 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); | 63 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); |
62 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 64 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
63 | static void acpiphp_set_hpp_values(struct pci_bus *bus); | 65 | static void acpiphp_set_hpp_values(struct pci_bus *bus); |
64 | static void hotplug_event_func(acpi_handle handle, u32 type, void *context); | 66 | static void hotplug_event(acpi_handle handle, u32 type, void *data); |
65 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | ||
66 | static void free_bridge(struct kref *kref); | 67 | static void free_bridge(struct kref *kref); |
67 | 68 | ||
68 | /* callback routine to check for the existence of a pci dock device */ | 69 | static void acpiphp_context_handler(acpi_handle handle, void *context) |
69 | static acpi_status | ||
70 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
71 | { | 70 | { |
72 | int *count = (int *)context; | 71 | /* Intentionally empty. */ |
72 | } | ||
73 | 73 | ||
74 | if (is_dock_device(handle)) { | 74 | /** |
75 | (*count)++; | 75 | * acpiphp_init_context - Create hotplug context and grab a reference to it. |
76 | return AE_CTRL_TERMINATE; | 76 | * @handle: ACPI object handle to create the context for. |
77 | } else { | 77 | * |
78 | return AE_OK; | 78 | * Call under acpiphp_context_lock. |
79 | */ | ||
80 | static struct acpiphp_context *acpiphp_init_context(acpi_handle handle) | ||
81 | { | ||
82 | struct acpiphp_context *context; | ||
83 | acpi_status status; | ||
84 | |||
85 | context = kzalloc(sizeof(*context), GFP_KERNEL); | ||
86 | if (!context) | ||
87 | return NULL; | ||
88 | |||
89 | context->handle = handle; | ||
90 | context->refcount = 1; | ||
91 | status = acpi_attach_data(handle, acpiphp_context_handler, context); | ||
92 | if (ACPI_FAILURE(status)) { | ||
93 | kfree(context); | ||
94 | return NULL; | ||
79 | } | 95 | } |
96 | return context; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * acpiphp_get_context - Get hotplug context and grab a reference to it. | ||
101 | * @handle: ACPI object handle to get the context for. | ||
102 | * | ||
103 | * Call under acpiphp_context_lock. | ||
104 | */ | ||
105 | static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) | ||
106 | { | ||
107 | struct acpiphp_context *context = NULL; | ||
108 | acpi_status status; | ||
109 | void *data; | ||
110 | |||
111 | status = acpi_get_data(handle, acpiphp_context_handler, &data); | ||
112 | if (ACPI_SUCCESS(status)) { | ||
113 | context = data; | ||
114 | context->refcount++; | ||
115 | } | ||
116 | return context; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * acpiphp_put_context - Drop a reference to ACPI hotplug context. | ||
121 | * @handle: ACPI object handle to put the context for. | ||
122 | * | ||
123 | * The context object is removed if there are no more references to it. | ||
124 | * | ||
125 | * Call under acpiphp_context_lock. | ||
126 | */ | ||
127 | static void acpiphp_put_context(struct acpiphp_context *context) | ||
128 | { | ||
129 | if (--context->refcount) | ||
130 | return; | ||
131 | |||
132 | WARN_ON(context->bridge); | ||
133 | acpi_detach_data(context->handle, acpiphp_context_handler); | ||
134 | kfree(context); | ||
80 | } | 135 | } |
81 | 136 | ||
82 | static inline void get_bridge(struct acpiphp_bridge *bridge) | 137 | static inline void get_bridge(struct acpiphp_bridge *bridge) |
@@ -91,25 +146,36 @@ static inline void put_bridge(struct acpiphp_bridge *bridge) | |||
91 | 146 | ||
92 | static void free_bridge(struct kref *kref) | 147 | static void free_bridge(struct kref *kref) |
93 | { | 148 | { |
149 | struct acpiphp_context *context; | ||
94 | struct acpiphp_bridge *bridge; | 150 | struct acpiphp_bridge *bridge; |
95 | struct acpiphp_slot *slot, *next; | 151 | struct acpiphp_slot *slot, *next; |
96 | struct acpiphp_func *func, *tmp; | 152 | struct acpiphp_func *func, *tmp; |
97 | 153 | ||
154 | mutex_lock(&acpiphp_context_lock); | ||
155 | |||
98 | bridge = container_of(kref, struct acpiphp_bridge, ref); | 156 | bridge = container_of(kref, struct acpiphp_bridge, ref); |
99 | 157 | ||
100 | list_for_each_entry_safe(slot, next, &bridge->slots, node) { | 158 | list_for_each_entry_safe(slot, next, &bridge->slots, node) { |
101 | list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { | 159 | list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) |
102 | kfree(func); | 160 | acpiphp_put_context(func_to_context(func)); |
103 | } | 161 | |
104 | kfree(slot); | 162 | kfree(slot); |
105 | } | 163 | } |
106 | 164 | ||
107 | /* Release reference acquired by acpiphp_bridge_handle_to_function() */ | 165 | context = bridge->context; |
108 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) | 166 | /* Root bridges will not have hotplug context. */ |
109 | put_bridge(bridge->func->slot->bridge); | 167 | if (context) { |
168 | /* Release the reference taken by acpiphp_enumerate_slots(). */ | ||
169 | put_bridge(context->func.parent); | ||
170 | context->bridge = NULL; | ||
171 | acpiphp_put_context(context); | ||
172 | } | ||
173 | |||
110 | put_device(&bridge->pci_bus->dev); | 174 | put_device(&bridge->pci_bus->dev); |
111 | pci_dev_put(bridge->pci_dev); | 175 | pci_dev_put(bridge->pci_dev); |
112 | kfree(bridge); | 176 | kfree(bridge); |
177 | |||
178 | mutex_unlock(&acpiphp_context_lock); | ||
113 | } | 179 | } |
114 | 180 | ||
115 | /* | 181 | /* |
@@ -121,8 +187,8 @@ static void free_bridge(struct kref *kref) | |||
121 | */ | 187 | */ |
122 | static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | 188 | static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) |
123 | { | 189 | { |
124 | struct acpiphp_func *func = data; | 190 | struct acpiphp_context *context = data; |
125 | struct pci_bus *bus = func->slot->bridge->pci_bus; | 191 | struct pci_bus *bus = context->func.slot->bus; |
126 | u32 buses; | 192 | u32 buses; |
127 | 193 | ||
128 | if (!bus->self) | 194 | if (!bus->self) |
@@ -147,7 +213,7 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | |||
147 | 213 | ||
148 | static const struct acpi_dock_ops acpiphp_dock_ops = { | 214 | static const struct acpi_dock_ops acpiphp_dock_ops = { |
149 | .fixup = post_dock_fixups, | 215 | .fixup = post_dock_fixups, |
150 | .handler = hotplug_event_func, | 216 | .handler = hotplug_event, |
151 | }; | 217 | }; |
152 | 218 | ||
153 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ | 219 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ |
@@ -181,54 +247,56 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) | |||
181 | 247 | ||
182 | static void acpiphp_dock_init(void *data) | 248 | static void acpiphp_dock_init(void *data) |
183 | { | 249 | { |
184 | struct acpiphp_func *func = data; | 250 | struct acpiphp_context *context = data; |
185 | 251 | ||
186 | get_bridge(func->slot->bridge); | 252 | get_bridge(context->func.parent); |
187 | } | 253 | } |
188 | 254 | ||
189 | static void acpiphp_dock_release(void *data) | 255 | static void acpiphp_dock_release(void *data) |
190 | { | 256 | { |
191 | struct acpiphp_func *func = data; | 257 | struct acpiphp_context *context = data; |
192 | 258 | ||
193 | put_bridge(func->slot->bridge); | 259 | put_bridge(context->func.parent); |
194 | } | 260 | } |
195 | 261 | ||
196 | /* callback routine to register each ACPI PCI slot object */ | 262 | /* callback routine to register each ACPI PCI slot object */ |
197 | static acpi_status | 263 | static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, |
198 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | 264 | void **rv) |
199 | { | 265 | { |
200 | struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; | 266 | struct acpiphp_bridge *bridge = data; |
267 | struct acpiphp_context *context; | ||
201 | struct acpiphp_slot *slot; | 268 | struct acpiphp_slot *slot; |
202 | struct acpiphp_func *newfunc; | 269 | struct acpiphp_func *newfunc; |
203 | acpi_status status = AE_OK; | 270 | acpi_status status = AE_OK; |
204 | unsigned long long adr, sun; | 271 | unsigned long long adr; |
205 | int device, function, retval, found = 0; | 272 | int device, function; |
206 | struct pci_bus *pbus = bridge->pci_bus; | 273 | struct pci_bus *pbus = bridge->pci_bus; |
207 | struct pci_dev *pdev; | 274 | struct pci_dev *pdev = bridge->pci_dev; |
208 | u32 val; | 275 | u32 val; |
209 | 276 | ||
210 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) | 277 | if (pdev && device_is_managed_by_native_pciehp(pdev)) |
211 | return AE_OK; | 278 | return AE_OK; |
212 | 279 | ||
213 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 280 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
214 | if (ACPI_FAILURE(status)) { | 281 | if (ACPI_FAILURE(status)) { |
215 | warn("can't evaluate _ADR (%#x)\n", status); | 282 | acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status); |
216 | return AE_OK; | 283 | return AE_OK; |
217 | } | 284 | } |
218 | 285 | ||
219 | device = (adr >> 16) & 0xffff; | 286 | device = (adr >> 16) & 0xffff; |
220 | function = adr & 0xffff; | 287 | function = adr & 0xffff; |
221 | 288 | ||
222 | pdev = bridge->pci_dev; | 289 | mutex_lock(&acpiphp_context_lock); |
223 | if (pdev && device_is_managed_by_native_pciehp(pdev)) | 290 | context = acpiphp_init_context(handle); |
224 | return AE_OK; | 291 | if (!context) { |
225 | 292 | mutex_unlock(&acpiphp_context_lock); | |
226 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); | 293 | acpi_handle_err(handle, "No hotplug context\n"); |
227 | if (!newfunc) | 294 | return AE_NOT_EXIST; |
228 | return AE_NO_MEMORY; | 295 | } |
229 | 296 | newfunc = &context->func; | |
230 | newfunc->handle = handle; | ||
231 | newfunc->function = function; | 297 | newfunc->function = function; |
298 | newfunc->parent = bridge; | ||
299 | mutex_unlock(&acpiphp_context_lock); | ||
232 | 300 | ||
233 | if (acpi_has_method(handle, "_EJ0")) | 301 | if (acpi_has_method(handle, "_EJ0")) |
234 | newfunc->flags = FUNC_HAS_EJ0; | 302 | newfunc->flags = FUNC_HAS_EJ0; |
@@ -236,73 +304,61 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
236 | if (acpi_has_method(handle, "_STA")) | 304 | if (acpi_has_method(handle, "_STA")) |
237 | newfunc->flags |= FUNC_HAS_STA; | 305 | newfunc->flags |= FUNC_HAS_STA; |
238 | 306 | ||
239 | if (acpi_has_method(handle, "_PS0")) | ||
240 | newfunc->flags |= FUNC_HAS_PS0; | ||
241 | |||
242 | if (acpi_has_method(handle, "_PS3")) | ||
243 | newfunc->flags |= FUNC_HAS_PS3; | ||
244 | |||
245 | if (acpi_has_method(handle, "_DCK")) | 307 | if (acpi_has_method(handle, "_DCK")) |
246 | newfunc->flags |= FUNC_HAS_DCK; | 308 | newfunc->flags |= FUNC_HAS_DCK; |
247 | 309 | ||
248 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); | ||
249 | if (ACPI_FAILURE(status)) { | ||
250 | /* | ||
251 | * use the count of the number of slots we've found | ||
252 | * for the number of the slot | ||
253 | */ | ||
254 | sun = bridge->nr_slots+1; | ||
255 | } | ||
256 | |||
257 | /* search for objects that share the same slot */ | 310 | /* search for objects that share the same slot */ |
258 | list_for_each_entry(slot, &bridge->slots, node) | 311 | list_for_each_entry(slot, &bridge->slots, node) |
259 | if (slot->device == device) { | 312 | if (slot->device == device) |
260 | if (slot->sun != sun) | 313 | goto slot_found; |
261 | warn("sibling found, but _SUN doesn't match!\n"); | ||
262 | found = 1; | ||
263 | break; | ||
264 | } | ||
265 | 314 | ||
266 | if (!found) { | 315 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); |
267 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); | 316 | if (!slot) { |
268 | if (!slot) { | 317 | status = AE_NO_MEMORY; |
269 | kfree(newfunc); | 318 | goto err; |
270 | return AE_NO_MEMORY; | 319 | } |
271 | } | 320 | |
321 | slot->bus = bridge->pci_bus; | ||
322 | slot->device = device; | ||
323 | INIT_LIST_HEAD(&slot->funcs); | ||
324 | mutex_init(&slot->crit_sect); | ||
325 | |||
326 | list_add_tail(&slot->node, &bridge->slots); | ||
272 | 327 | ||
273 | slot->bridge = bridge; | 328 | /* Register slots for ejectable funtions only. */ |
274 | slot->device = device; | 329 | if (acpi_pci_check_ejectable(pbus, handle) || is_dock_device(handle)) { |
275 | slot->sun = sun; | 330 | unsigned long long sun; |
276 | INIT_LIST_HEAD(&slot->funcs); | 331 | int retval; |
277 | mutex_init(&slot->crit_sect); | ||
278 | 332 | ||
279 | mutex_lock(&bridge_mutex); | ||
280 | list_add_tail(&slot->node, &bridge->slots); | ||
281 | mutex_unlock(&bridge_mutex); | ||
282 | bridge->nr_slots++; | 333 | bridge->nr_slots++; |
334 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); | ||
335 | if (ACPI_FAILURE(status)) | ||
336 | sun = bridge->nr_slots; | ||
283 | 337 | ||
284 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", | 338 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
285 | slot->sun, pci_domain_nr(pbus), pbus->number, device); | 339 | sun, pci_domain_nr(pbus), pbus->number, device); |
286 | retval = acpiphp_register_hotplug_slot(slot); | 340 | |
341 | retval = acpiphp_register_hotplug_slot(slot, sun); | ||
287 | if (retval) { | 342 | if (retval) { |
343 | slot->slot = NULL; | ||
344 | bridge->nr_slots--; | ||
288 | if (retval == -EBUSY) | 345 | if (retval == -EBUSY) |
289 | warn("Slot %llu already registered by another " | 346 | warn("Slot %llu already registered by another " |
290 | "hotplug driver\n", slot->sun); | 347 | "hotplug driver\n", sun); |
291 | else | 348 | else |
292 | warn("acpiphp_register_hotplug_slot failed " | 349 | warn("acpiphp_register_hotplug_slot failed " |
293 | "(err code = 0x%x)\n", retval); | 350 | "(err code = 0x%x)\n", retval); |
294 | goto err_exit; | ||
295 | } | 351 | } |
352 | /* Even if the slot registration fails, we can still use it. */ | ||
296 | } | 353 | } |
297 | 354 | ||
355 | slot_found: | ||
298 | newfunc->slot = slot; | 356 | newfunc->slot = slot; |
299 | mutex_lock(&bridge_mutex); | ||
300 | list_add_tail(&newfunc->sibling, &slot->funcs); | 357 | list_add_tail(&newfunc->sibling, &slot->funcs); |
301 | mutex_unlock(&bridge_mutex); | ||
302 | 358 | ||
303 | if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), | 359 | if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), |
304 | &val, 60*1000)) | 360 | &val, 60*1000)) |
305 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 361 | slot->flags |= SLOT_ENABLED; |
306 | 362 | ||
307 | if (is_dock_device(handle)) { | 363 | if (is_dock_device(handle)) { |
308 | /* we don't want to call this device's _EJ0 | 364 | /* we don't want to call this device's _EJ0 |
@@ -311,128 +367,46 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
311 | */ | 367 | */ |
312 | newfunc->flags &= ~FUNC_HAS_EJ0; | 368 | newfunc->flags &= ~FUNC_HAS_EJ0; |
313 | if (register_hotplug_dock_device(handle, | 369 | if (register_hotplug_dock_device(handle, |
314 | &acpiphp_dock_ops, newfunc, | 370 | &acpiphp_dock_ops, context, |
315 | acpiphp_dock_init, acpiphp_dock_release)) | 371 | acpiphp_dock_init, acpiphp_dock_release)) |
316 | dbg("failed to register dock device\n"); | 372 | dbg("failed to register dock device\n"); |
317 | } | 373 | } |
318 | 374 | ||
319 | /* install notify handler */ | 375 | /* install notify handler */ |
320 | if (!(newfunc->flags & FUNC_HAS_DCK)) { | 376 | if (!(newfunc->flags & FUNC_HAS_DCK)) { |
321 | status = acpi_install_notify_handler(handle, | 377 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
322 | ACPI_SYSTEM_NOTIFY, | 378 | handle_hotplug_event, |
323 | handle_hotplug_event_func, | 379 | context); |
324 | newfunc); | ||
325 | |||
326 | if (ACPI_FAILURE(status)) | 380 | if (ACPI_FAILURE(status)) |
327 | err("failed to register interrupt notify handler\n"); | 381 | acpi_handle_err(handle, |
328 | } else | 382 | "failed to install notify handler\n"); |
329 | status = AE_OK; | ||
330 | |||
331 | return status; | ||
332 | |||
333 | err_exit: | ||
334 | bridge->nr_slots--; | ||
335 | mutex_lock(&bridge_mutex); | ||
336 | list_del(&slot->node); | ||
337 | mutex_unlock(&bridge_mutex); | ||
338 | kfree(slot); | ||
339 | kfree(newfunc); | ||
340 | |||
341 | return AE_OK; | ||
342 | } | ||
343 | |||
344 | |||
345 | /* see if it's worth looking at this bridge */ | ||
346 | static int detect_ejectable_slots(acpi_handle handle) | ||
347 | { | ||
348 | int found = acpi_pci_detect_ejectable(handle); | ||
349 | if (!found) { | ||
350 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
351 | is_pci_dock_device, NULL, (void *)&found, NULL); | ||
352 | } | ||
353 | return found; | ||
354 | } | ||
355 | |||
356 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ | ||
357 | static void init_bridge_misc(struct acpiphp_bridge *bridge) | ||
358 | { | ||
359 | acpi_status status; | ||
360 | |||
361 | /* must be added to the list prior to calling register_slot */ | ||
362 | mutex_lock(&bridge_mutex); | ||
363 | list_add(&bridge->list, &bridge_list); | ||
364 | mutex_unlock(&bridge_mutex); | ||
365 | |||
366 | /* register all slot objects under this bridge */ | ||
367 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | ||
368 | register_slot, NULL, bridge, NULL); | ||
369 | if (ACPI_FAILURE(status)) { | ||
370 | mutex_lock(&bridge_mutex); | ||
371 | list_del(&bridge->list); | ||
372 | mutex_unlock(&bridge_mutex); | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | /* install notify handler for P2P bridges */ | ||
377 | if (!pci_is_root_bus(bridge->pci_bus)) { | ||
378 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { | ||
379 | status = acpi_remove_notify_handler(bridge->func->handle, | ||
380 | ACPI_SYSTEM_NOTIFY, | ||
381 | handle_hotplug_event_func); | ||
382 | if (ACPI_FAILURE(status)) | ||
383 | err("failed to remove notify handler\n"); | ||
384 | } | ||
385 | status = acpi_install_notify_handler(bridge->handle, | ||
386 | ACPI_SYSTEM_NOTIFY, | ||
387 | handle_hotplug_event_bridge, | ||
388 | bridge); | ||
389 | |||
390 | if (ACPI_FAILURE(status)) { | ||
391 | err("failed to register interrupt notify handler\n"); | ||
392 | } | ||
393 | } | 383 | } |
394 | } | ||
395 | |||
396 | |||
397 | /* find acpiphp_func from acpiphp_bridge */ | ||
398 | static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) | ||
399 | { | ||
400 | struct acpiphp_bridge *bridge; | ||
401 | struct acpiphp_slot *slot; | ||
402 | struct acpiphp_func *func = NULL; | ||
403 | 384 | ||
404 | mutex_lock(&bridge_mutex); | 385 | return AE_OK; |
405 | list_for_each_entry(bridge, &bridge_list, list) { | ||
406 | list_for_each_entry(slot, &bridge->slots, node) { | ||
407 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
408 | if (func->handle == handle) { | ||
409 | get_bridge(func->slot->bridge); | ||
410 | mutex_unlock(&bridge_mutex); | ||
411 | return func; | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | } | ||
416 | mutex_unlock(&bridge_mutex); | ||
417 | 386 | ||
418 | return NULL; | 387 | err: |
388 | mutex_lock(&acpiphp_context_lock); | ||
389 | acpiphp_put_context(context); | ||
390 | mutex_unlock(&acpiphp_context_lock); | ||
391 | return status; | ||
419 | } | 392 | } |
420 | 393 | ||
421 | |||
422 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | 394 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) |
423 | { | 395 | { |
424 | struct acpiphp_bridge *bridge; | 396 | struct acpiphp_context *context; |
425 | 397 | struct acpiphp_bridge *bridge = NULL; | |
426 | mutex_lock(&bridge_mutex); | 398 | |
427 | list_for_each_entry(bridge, &bridge_list, list) | 399 | mutex_lock(&acpiphp_context_lock); |
428 | if (bridge->handle == handle) { | 400 | context = acpiphp_get_context(handle); |
401 | if (context) { | ||
402 | bridge = context->bridge; | ||
403 | if (bridge) | ||
429 | get_bridge(bridge); | 404 | get_bridge(bridge); |
430 | mutex_unlock(&bridge_mutex); | ||
431 | return bridge; | ||
432 | } | ||
433 | mutex_unlock(&bridge_mutex); | ||
434 | 405 | ||
435 | return NULL; | 406 | acpiphp_put_context(context); |
407 | } | ||
408 | mutex_unlock(&acpiphp_context_lock); | ||
409 | return bridge; | ||
436 | } | 410 | } |
437 | 411 | ||
438 | static void cleanup_bridge(struct acpiphp_bridge *bridge) | 412 | static void cleanup_bridge(struct acpiphp_bridge *bridge) |
@@ -440,39 +414,24 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
440 | struct acpiphp_slot *slot; | 414 | struct acpiphp_slot *slot; |
441 | struct acpiphp_func *func; | 415 | struct acpiphp_func *func; |
442 | acpi_status status; | 416 | acpi_status status; |
443 | acpi_handle handle = bridge->handle; | ||
444 | |||
445 | if (!pci_is_root_bus(bridge->pci_bus)) { | ||
446 | status = acpi_remove_notify_handler(handle, | ||
447 | ACPI_SYSTEM_NOTIFY, | ||
448 | handle_hotplug_event_bridge); | ||
449 | if (ACPI_FAILURE(status)) | ||
450 | err("failed to remove notify handler\n"); | ||
451 | } | ||
452 | |||
453 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { | ||
454 | status = acpi_install_notify_handler(bridge->func->handle, | ||
455 | ACPI_SYSTEM_NOTIFY, | ||
456 | handle_hotplug_event_func, | ||
457 | bridge->func); | ||
458 | if (ACPI_FAILURE(status)) | ||
459 | err("failed to install interrupt notify handler\n"); | ||
460 | } | ||
461 | 417 | ||
462 | list_for_each_entry(slot, &bridge->slots, node) { | 418 | list_for_each_entry(slot, &bridge->slots, node) { |
463 | list_for_each_entry(func, &slot->funcs, sibling) { | 419 | list_for_each_entry(func, &slot->funcs, sibling) { |
464 | if (is_dock_device(func->handle)) { | 420 | acpi_handle handle = func_to_handle(func); |
465 | unregister_hotplug_dock_device(func->handle); | 421 | |
466 | } | 422 | if (is_dock_device(handle)) |
423 | unregister_hotplug_dock_device(handle); | ||
424 | |||
467 | if (!(func->flags & FUNC_HAS_DCK)) { | 425 | if (!(func->flags & FUNC_HAS_DCK)) { |
468 | status = acpi_remove_notify_handler(func->handle, | 426 | status = acpi_remove_notify_handler(handle, |
469 | ACPI_SYSTEM_NOTIFY, | 427 | ACPI_SYSTEM_NOTIFY, |
470 | handle_hotplug_event_func); | 428 | handle_hotplug_event); |
471 | if (ACPI_FAILURE(status)) | 429 | if (ACPI_FAILURE(status)) |
472 | err("failed to remove notify handler\n"); | 430 | err("failed to remove notify handler\n"); |
473 | } | 431 | } |
474 | } | 432 | } |
475 | acpiphp_unregister_hotplug_slot(slot); | 433 | if (slot->slot) |
434 | acpiphp_unregister_hotplug_slot(slot); | ||
476 | } | 435 | } |
477 | 436 | ||
478 | mutex_lock(&bridge_mutex); | 437 | mutex_lock(&bridge_mutex); |
@@ -480,71 +439,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
480 | mutex_unlock(&bridge_mutex); | 439 | mutex_unlock(&bridge_mutex); |
481 | } | 440 | } |
482 | 441 | ||
483 | static int power_on_slot(struct acpiphp_slot *slot) | ||
484 | { | ||
485 | acpi_status status; | ||
486 | struct acpiphp_func *func; | ||
487 | int retval = 0; | ||
488 | |||
489 | /* if already enabled, just skip */ | ||
490 | if (slot->flags & SLOT_POWEREDON) | ||
491 | goto err_exit; | ||
492 | |||
493 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
494 | if (func->flags & FUNC_HAS_PS0) { | ||
495 | dbg("%s: executing _PS0\n", __func__); | ||
496 | status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); | ||
497 | if (ACPI_FAILURE(status)) { | ||
498 | warn("%s: _PS0 failed\n", __func__); | ||
499 | retval = -1; | ||
500 | goto err_exit; | ||
501 | } else | ||
502 | break; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /* TBD: evaluate _STA to check if the slot is enabled */ | ||
507 | |||
508 | slot->flags |= SLOT_POWEREDON; | ||
509 | |||
510 | err_exit: | ||
511 | return retval; | ||
512 | } | ||
513 | |||
514 | |||
515 | static int power_off_slot(struct acpiphp_slot *slot) | ||
516 | { | ||
517 | acpi_status status; | ||
518 | struct acpiphp_func *func; | ||
519 | |||
520 | int retval = 0; | ||
521 | |||
522 | /* if already disabled, just skip */ | ||
523 | if ((slot->flags & SLOT_POWEREDON) == 0) | ||
524 | goto err_exit; | ||
525 | |||
526 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
527 | if (func->flags & FUNC_HAS_PS3) { | ||
528 | status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); | ||
529 | if (ACPI_FAILURE(status)) { | ||
530 | warn("%s: _PS3 failed\n", __func__); | ||
531 | retval = -1; | ||
532 | goto err_exit; | ||
533 | } else | ||
534 | break; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | /* TBD: evaluate _STA to check if the slot is disabled */ | ||
539 | |||
540 | slot->flags &= (~SLOT_POWEREDON); | ||
541 | |||
542 | err_exit: | ||
543 | return retval; | ||
544 | } | ||
545 | |||
546 | |||
547 | |||
548 | /** | 442 | /** |
549 | * acpiphp_max_busnr - return the highest reserved bus number under the given bus. | 443 | * acpiphp_max_busnr - return the highest reserved bus number under the given bus. |
550 | * @bus: bus to start search with | 444 | * @bus: bus to start search with |
@@ -572,52 +466,32 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | |||
572 | return max; | 466 | return max; |
573 | } | 467 | } |
574 | 468 | ||
575 | |||
576 | /** | 469 | /** |
577 | * acpiphp_bus_add - add a new bus to acpi subsystem | 470 | * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree. |
578 | * @func: acpiphp_func of the bridge | 471 | * @handle: ACPI device object handle to start from. |
579 | */ | 472 | */ |
580 | static int acpiphp_bus_add(struct acpiphp_func *func) | 473 | static void acpiphp_bus_trim(acpi_handle handle) |
581 | { | 474 | { |
582 | struct acpi_device *device; | 475 | struct acpi_device *adev = NULL; |
583 | int ret_val; | ||
584 | 476 | ||
585 | if (!acpi_bus_get_device(func->handle, &device)) { | 477 | acpi_bus_get_device(handle, &adev); |
586 | dbg("bus exists... trim\n"); | 478 | if (adev) |
587 | /* this shouldn't be in here, so remove | 479 | acpi_bus_trim(adev); |
588 | * the bus then re-add it... | ||
589 | */ | ||
590 | acpi_bus_trim(device); | ||
591 | } | ||
592 | |||
593 | ret_val = acpi_bus_scan(func->handle); | ||
594 | if (!ret_val) | ||
595 | ret_val = acpi_bus_get_device(func->handle, &device); | ||
596 | |||
597 | if (ret_val) | ||
598 | dbg("error adding bus, %x\n", -ret_val); | ||
599 | |||
600 | return ret_val; | ||
601 | } | 480 | } |
602 | 481 | ||
603 | |||
604 | /** | 482 | /** |
605 | * acpiphp_bus_trim - trim a bus from acpi subsystem | 483 | * acpiphp_bus_add - Scan ACPI namespace subtree. |
606 | * @handle: handle to acpi namespace | 484 | * @handle: ACPI object handle to start the scan from. |
607 | */ | 485 | */ |
608 | static int acpiphp_bus_trim(acpi_handle handle) | 486 | static void acpiphp_bus_add(acpi_handle handle) |
609 | { | 487 | { |
610 | struct acpi_device *device; | 488 | struct acpi_device *adev = NULL; |
611 | int retval; | ||
612 | |||
613 | retval = acpi_bus_get_device(handle, &device); | ||
614 | if (retval) { | ||
615 | dbg("acpi_device not found\n"); | ||
616 | return retval; | ||
617 | } | ||
618 | 489 | ||
619 | acpi_bus_trim(device); | 490 | acpiphp_bus_trim(handle); |
620 | return 0; | 491 | acpi_bus_scan(handle); |
492 | acpi_bus_get_device(handle, &adev); | ||
493 | if (adev) | ||
494 | acpi_device_set_power(adev, ACPI_STATE_D0); | ||
621 | } | 495 | } |
622 | 496 | ||
623 | static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) | 497 | static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) |
@@ -634,7 +508,8 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) | |||
634 | params[1].type = ACPI_TYPE_INTEGER; | 508 | params[1].type = ACPI_TYPE_INTEGER; |
635 | params[1].integer.value = 1; | 509 | params[1].integer.value = 1; |
636 | /* _REG is optional, we don't care about if there is failure */ | 510 | /* _REG is optional, we don't care about if there is failure */ |
637 | acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL); | 511 | acpi_evaluate_object(func_to_handle(func), "_REG", &arg_list, |
512 | NULL); | ||
638 | } | 513 | } |
639 | } | 514 | } |
640 | 515 | ||
@@ -642,59 +517,44 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) | |||
642 | { | 517 | { |
643 | struct acpiphp_func *func; | 518 | struct acpiphp_func *func; |
644 | 519 | ||
645 | if (!dev->subordinate) | ||
646 | return; | ||
647 | |||
648 | /* quirk, or pcie could set it already */ | 520 | /* quirk, or pcie could set it already */ |
649 | if (dev->is_hotplug_bridge) | 521 | if (dev->is_hotplug_bridge) |
650 | return; | 522 | return; |
651 | 523 | ||
652 | if (PCI_SLOT(dev->devfn) != slot->device) | ||
653 | return; | ||
654 | |||
655 | list_for_each_entry(func, &slot->funcs, sibling) { | 524 | list_for_each_entry(func, &slot->funcs, sibling) { |
656 | if (PCI_FUNC(dev->devfn) == func->function) { | 525 | if (PCI_FUNC(dev->devfn) == func->function) { |
657 | /* check if this bridge has ejectable slots */ | 526 | dev->is_hotplug_bridge = 1; |
658 | if ((detect_ejectable_slots(func->handle) > 0)) | ||
659 | dev->is_hotplug_bridge = 1; | ||
660 | break; | 527 | break; |
661 | } | 528 | } |
662 | } | 529 | } |
663 | } | 530 | } |
664 | 531 | ||
665 | /** | 532 | /** |
666 | * enable_device - enable, configure a slot | 533 | * enable_slot - enable, configure a slot |
667 | * @slot: slot to be enabled | 534 | * @slot: slot to be enabled |
668 | * | 535 | * |
669 | * This function should be called per *physical slot*, | 536 | * This function should be called per *physical slot*, |
670 | * not per each slot object in ACPI namespace. | 537 | * not per each slot object in ACPI namespace. |
671 | */ | 538 | */ |
672 | static int __ref enable_device(struct acpiphp_slot *slot) | 539 | static void __ref enable_slot(struct acpiphp_slot *slot) |
673 | { | 540 | { |
674 | struct pci_dev *dev; | 541 | struct pci_dev *dev; |
675 | struct pci_bus *bus = slot->bridge->pci_bus; | 542 | struct pci_bus *bus = slot->bus; |
676 | struct acpiphp_func *func; | 543 | struct acpiphp_func *func; |
677 | int num, max, pass; | 544 | int max, pass; |
678 | LIST_HEAD(add_list); | 545 | LIST_HEAD(add_list); |
679 | 546 | ||
680 | if (slot->flags & SLOT_ENABLED) | ||
681 | goto err_exit; | ||
682 | |||
683 | list_for_each_entry(func, &slot->funcs, sibling) | 547 | list_for_each_entry(func, &slot->funcs, sibling) |
684 | acpiphp_bus_add(func); | 548 | acpiphp_bus_add(func_to_handle(func)); |
685 | 549 | ||
686 | num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); | 550 | pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); |
687 | if (num == 0) { | ||
688 | /* Maybe only part of funcs are added. */ | ||
689 | dbg("No new device found\n"); | ||
690 | goto err_exit; | ||
691 | } | ||
692 | 551 | ||
693 | max = acpiphp_max_busnr(bus); | 552 | max = acpiphp_max_busnr(bus); |
694 | for (pass = 0; pass < 2; pass++) { | 553 | for (pass = 0; pass < 2; pass++) { |
695 | list_for_each_entry(dev, &bus->devices, bus_list) { | 554 | list_for_each_entry(dev, &bus->devices, bus_list) { |
696 | if (PCI_SLOT(dev->devfn) != slot->device) | 555 | if (PCI_SLOT(dev->devfn) != slot->device) |
697 | continue; | 556 | continue; |
557 | |||
698 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 558 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
699 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | 559 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
700 | max = pci_scan_bridge(bus, dev, max, pass); | 560 | max = pci_scan_bridge(bus, dev, max, pass); |
@@ -733,16 +593,12 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
733 | continue; | 593 | continue; |
734 | } | 594 | } |
735 | } | 595 | } |
736 | |||
737 | |||
738 | err_exit: | ||
739 | return 0; | ||
740 | } | 596 | } |
741 | 597 | ||
742 | /* return first device in slot, acquiring a reference on it */ | 598 | /* return first device in slot, acquiring a reference on it */ |
743 | static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) | 599 | static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) |
744 | { | 600 | { |
745 | struct pci_bus *bus = slot->bridge->pci_bus; | 601 | struct pci_bus *bus = slot->bus; |
746 | struct pci_dev *dev; | 602 | struct pci_dev *dev; |
747 | struct pci_dev *ret = NULL; | 603 | struct pci_dev *ret = NULL; |
748 | 604 | ||
@@ -758,16 +614,16 @@ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) | |||
758 | } | 614 | } |
759 | 615 | ||
760 | /** | 616 | /** |
761 | * disable_device - disable a slot | 617 | * disable_slot - disable a slot |
762 | * @slot: ACPI PHP slot | 618 | * @slot: ACPI PHP slot |
763 | */ | 619 | */ |
764 | static int disable_device(struct acpiphp_slot *slot) | 620 | static void disable_slot(struct acpiphp_slot *slot) |
765 | { | 621 | { |
766 | struct acpiphp_func *func; | 622 | struct acpiphp_func *func; |
767 | struct pci_dev *pdev; | 623 | struct pci_dev *pdev; |
768 | 624 | ||
769 | /* | 625 | /* |
770 | * enable_device() enumerates all functions in this device via | 626 | * enable_slot() enumerates all functions in this device via |
771 | * pci_scan_slot(), whether they have associated ACPI hotplug | 627 | * pci_scan_slot(), whether they have associated ACPI hotplug |
772 | * methods (_EJ0, etc.) or not. Therefore, we remove all functions | 628 | * methods (_EJ0, etc.) or not. Therefore, we remove all functions |
773 | * here. | 629 | * here. |
@@ -777,13 +633,10 @@ static int disable_device(struct acpiphp_slot *slot) | |||
777 | pci_dev_put(pdev); | 633 | pci_dev_put(pdev); |
778 | } | 634 | } |
779 | 635 | ||
780 | list_for_each_entry(func, &slot->funcs, sibling) { | 636 | list_for_each_entry(func, &slot->funcs, sibling) |
781 | acpiphp_bus_trim(func->handle); | 637 | acpiphp_bus_trim(func_to_handle(func)); |
782 | } | ||
783 | 638 | ||
784 | slot->flags &= (~SLOT_ENABLED); | 639 | slot->flags &= (~SLOT_ENABLED); |
785 | |||
786 | return 0; | ||
787 | } | 640 | } |
788 | 641 | ||
789 | 642 | ||
@@ -801,18 +654,21 @@ static int disable_device(struct acpiphp_slot *slot) | |||
801 | */ | 654 | */ |
802 | static unsigned int get_slot_status(struct acpiphp_slot *slot) | 655 | static unsigned int get_slot_status(struct acpiphp_slot *slot) |
803 | { | 656 | { |
804 | acpi_status status; | ||
805 | unsigned long long sta = 0; | 657 | unsigned long long sta = 0; |
806 | u32 dvid; | ||
807 | struct acpiphp_func *func; | 658 | struct acpiphp_func *func; |
808 | 659 | ||
809 | list_for_each_entry(func, &slot->funcs, sibling) { | 660 | list_for_each_entry(func, &slot->funcs, sibling) { |
810 | if (func->flags & FUNC_HAS_STA) { | 661 | if (func->flags & FUNC_HAS_STA) { |
811 | status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); | 662 | acpi_status status; |
663 | |||
664 | status = acpi_evaluate_integer(func_to_handle(func), | ||
665 | "_STA", NULL, &sta); | ||
812 | if (ACPI_SUCCESS(status) && sta) | 666 | if (ACPI_SUCCESS(status) && sta) |
813 | break; | 667 | break; |
814 | } else { | 668 | } else { |
815 | pci_bus_read_config_dword(slot->bridge->pci_bus, | 669 | u32 dvid; |
670 | |||
671 | pci_bus_read_config_dword(slot->bus, | ||
816 | PCI_DEVFN(slot->device, | 672 | PCI_DEVFN(slot->device, |
817 | func->function), | 673 | func->function), |
818 | PCI_VENDOR_ID, &dvid); | 674 | PCI_VENDOR_ID, &dvid); |
@@ -827,23 +683,42 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) | |||
827 | } | 683 | } |
828 | 684 | ||
829 | /** | 685 | /** |
830 | * acpiphp_eject_slot - physically eject the slot | 686 | * trim_stale_devices - remove PCI devices that are not responding. |
831 | * @slot: ACPI PHP slot | 687 | * @dev: PCI device to start walking the hierarchy from. |
832 | */ | 688 | */ |
833 | int acpiphp_eject_slot(struct acpiphp_slot *slot) | 689 | static void trim_stale_devices(struct pci_dev *dev) |
834 | { | 690 | { |
835 | struct acpiphp_func *func; | 691 | acpi_handle handle = ACPI_HANDLE(&dev->dev); |
692 | struct pci_bus *bus = dev->subordinate; | ||
693 | bool alive = false; | ||
836 | 694 | ||
837 | list_for_each_entry(func, &slot->funcs, sibling) { | 695 | if (handle) { |
838 | /* We don't want to call _EJ0 on non-existing functions. */ | 696 | acpi_status status; |
839 | if ((func->flags & FUNC_HAS_EJ0)) { | 697 | unsigned long long sta; |
840 | if (ACPI_FAILURE(acpi_evaluate_ej0(func->handle))) | 698 | |
841 | return -1; | 699 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
842 | else | 700 | alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; |
843 | break; | 701 | } |
844 | } | 702 | if (!alive) { |
703 | u32 v; | ||
704 | |||
705 | /* Check if the device responds. */ | ||
706 | alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0); | ||
707 | } | ||
708 | if (!alive) { | ||
709 | pci_stop_and_remove_bus_device(dev); | ||
710 | if (handle) | ||
711 | acpiphp_bus_trim(handle); | ||
712 | } else if (bus) { | ||
713 | struct pci_dev *child, *tmp; | ||
714 | |||
715 | /* The device is a bridge. so check the bus below it. */ | ||
716 | pm_runtime_get_sync(&dev->dev); | ||
717 | list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) | ||
718 | trim_stale_devices(child); | ||
719 | |||
720 | pm_runtime_put(&dev->dev); | ||
845 | } | 721 | } |
846 | return 0; | ||
847 | } | 722 | } |
848 | 723 | ||
849 | /** | 724 | /** |
@@ -853,43 +728,30 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) | |||
853 | * Iterate over all slots under this bridge and make sure that if a | 728 | * Iterate over all slots under this bridge and make sure that if a |
854 | * card is present they are enabled, and if not they are disabled. | 729 | * card is present they are enabled, and if not they are disabled. |
855 | */ | 730 | */ |
856 | static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) | 731 | static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) |
857 | { | 732 | { |
858 | struct acpiphp_slot *slot; | 733 | struct acpiphp_slot *slot; |
859 | int retval = 0; | ||
860 | int enabled, disabled; | ||
861 | |||
862 | enabled = disabled = 0; | ||
863 | 734 | ||
864 | list_for_each_entry(slot, &bridge->slots, node) { | 735 | list_for_each_entry(slot, &bridge->slots, node) { |
865 | unsigned int status = get_slot_status(slot); | 736 | struct pci_bus *bus = slot->bus; |
866 | if (slot->flags & SLOT_ENABLED) { | 737 | struct pci_dev *dev, *tmp; |
867 | if (status == ACPI_STA_ALL) | 738 | |
868 | continue; | 739 | mutex_lock(&slot->crit_sect); |
869 | retval = acpiphp_disable_slot(slot); | 740 | /* wake up all functions */ |
870 | if (retval) { | 741 | if (get_slot_status(slot) == ACPI_STA_ALL) { |
871 | err("Error occurred in disabling\n"); | 742 | /* remove stale devices if any */ |
872 | goto err_exit; | 743 | list_for_each_entry_safe(dev, tmp, &bus->devices, |
873 | } else { | 744 | bus_list) |
874 | acpiphp_eject_slot(slot); | 745 | if (PCI_SLOT(dev->devfn) == slot->device) |
875 | } | 746 | trim_stale_devices(dev); |
876 | disabled++; | 747 | |
748 | /* configure all functions */ | ||
749 | enable_slot(slot); | ||
877 | } else { | 750 | } else { |
878 | if (status != ACPI_STA_ALL) | 751 | disable_slot(slot); |
879 | continue; | ||
880 | retval = acpiphp_enable_slot(slot); | ||
881 | if (retval) { | ||
882 | err("Error occurred in enabling\n"); | ||
883 | goto err_exit; | ||
884 | } | ||
885 | enabled++; | ||
886 | } | 752 | } |
753 | mutex_unlock(&slot->crit_sect); | ||
887 | } | 754 | } |
888 | |||
889 | dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled); | ||
890 | |||
891 | err_exit: | ||
892 | return retval; | ||
893 | } | 755 | } |
894 | 756 | ||
895 | static void acpiphp_set_hpp_values(struct pci_bus *bus) | 757 | static void acpiphp_set_hpp_values(struct pci_bus *bus) |
@@ -928,25 +790,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
928 | * ACPI event handlers | 790 | * ACPI event handlers |
929 | */ | 791 | */ |
930 | 792 | ||
931 | static acpi_status | ||
932 | check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
933 | { | ||
934 | struct acpiphp_bridge *bridge; | ||
935 | char objname[64]; | ||
936 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
937 | .pointer = objname }; | ||
938 | |||
939 | bridge = acpiphp_handle_to_bridge(handle); | ||
940 | if (bridge) { | ||
941 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
942 | dbg("%s: re-enumerating slots under %s\n", | ||
943 | __func__, objname); | ||
944 | acpiphp_check_bridge(bridge); | ||
945 | put_bridge(bridge); | ||
946 | } | ||
947 | return AE_OK ; | ||
948 | } | ||
949 | |||
950 | void acpiphp_check_host_bridge(acpi_handle handle) | 793 | void acpiphp_check_host_bridge(acpi_handle handle) |
951 | { | 794 | { |
952 | struct acpiphp_bridge *bridge; | 795 | struct acpiphp_bridge *bridge; |
@@ -956,27 +799,23 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
956 | acpiphp_check_bridge(bridge); | 799 | acpiphp_check_bridge(bridge); |
957 | put_bridge(bridge); | 800 | put_bridge(bridge); |
958 | } | 801 | } |
959 | |||
960 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
961 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); | ||
962 | } | 802 | } |
963 | 803 | ||
964 | static void _handle_hotplug_event_bridge(struct work_struct *work) | 804 | static void hotplug_event(acpi_handle handle, u32 type, void *data) |
965 | { | 805 | { |
806 | struct acpiphp_context *context = data; | ||
807 | struct acpiphp_func *func = &context->func; | ||
966 | struct acpiphp_bridge *bridge; | 808 | struct acpiphp_bridge *bridge; |
967 | char objname[64]; | 809 | char objname[64]; |
968 | struct acpi_buffer buffer = { .length = sizeof(objname), | 810 | struct acpi_buffer buffer = { .length = sizeof(objname), |
969 | .pointer = objname }; | 811 | .pointer = objname }; |
970 | struct acpi_hp_work *hp_work; | ||
971 | acpi_handle handle; | ||
972 | u32 type; | ||
973 | 812 | ||
974 | hp_work = container_of(work, struct acpi_hp_work, work); | 813 | mutex_lock(&acpiphp_context_lock); |
975 | handle = hp_work->handle; | 814 | bridge = context->bridge; |
976 | type = hp_work->type; | 815 | if (bridge) |
977 | bridge = (struct acpiphp_bridge *)hp_work->context; | 816 | get_bridge(bridge); |
978 | 817 | ||
979 | acpi_scan_lock_acquire(); | 818 | mutex_unlock(&acpiphp_context_lock); |
980 | 819 | ||
981 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 820 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
982 | 821 | ||
@@ -985,187 +824,129 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
985 | /* bus re-enumerate */ | 824 | /* bus re-enumerate */ |
986 | dbg("%s: Bus check notify on %s\n", __func__, objname); | 825 | dbg("%s: Bus check notify on %s\n", __func__, objname); |
987 | dbg("%s: re-enumerating slots under %s\n", __func__, objname); | 826 | dbg("%s: re-enumerating slots under %s\n", __func__, objname); |
988 | acpiphp_check_bridge(bridge); | 827 | if (bridge) { |
989 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 828 | acpiphp_check_bridge(bridge); |
990 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); | 829 | } else { |
830 | struct acpiphp_slot *slot = func->slot; | ||
831 | |||
832 | mutex_lock(&slot->crit_sect); | ||
833 | enable_slot(slot); | ||
834 | mutex_unlock(&slot->crit_sect); | ||
835 | } | ||
991 | break; | 836 | break; |
992 | 837 | ||
993 | case ACPI_NOTIFY_DEVICE_CHECK: | 838 | case ACPI_NOTIFY_DEVICE_CHECK: |
994 | /* device check */ | 839 | /* device check */ |
995 | dbg("%s: Device check notify on %s\n", __func__, objname); | 840 | dbg("%s: Device check notify on %s\n", __func__, objname); |
996 | acpiphp_check_bridge(bridge); | 841 | if (bridge) |
997 | break; | 842 | acpiphp_check_bridge(bridge); |
843 | else | ||
844 | acpiphp_check_bridge(func->parent); | ||
998 | 845 | ||
999 | case ACPI_NOTIFY_DEVICE_WAKE: | ||
1000 | /* wake event */ | ||
1001 | dbg("%s: Device wake notify on %s\n", __func__, objname); | ||
1002 | break; | 846 | break; |
1003 | 847 | ||
1004 | case ACPI_NOTIFY_EJECT_REQUEST: | 848 | case ACPI_NOTIFY_EJECT_REQUEST: |
1005 | /* request device eject */ | 849 | /* request device eject */ |
1006 | dbg("%s: Device eject notify on %s\n", __func__, objname); | 850 | dbg("%s: Device eject notify on %s\n", __func__, objname); |
1007 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { | 851 | acpiphp_disable_and_eject_slot(func->slot); |
1008 | struct acpiphp_slot *slot; | ||
1009 | slot = bridge->func->slot; | ||
1010 | if (!acpiphp_disable_slot(slot)) | ||
1011 | acpiphp_eject_slot(slot); | ||
1012 | } | ||
1013 | break; | 852 | break; |
853 | } | ||
1014 | 854 | ||
1015 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 855 | if (bridge) |
1016 | printk(KERN_ERR "Device %s cannot be configured due" | 856 | put_bridge(bridge); |
1017 | " to a frequency mismatch\n", objname); | 857 | } |
1018 | break; | ||
1019 | 858 | ||
1020 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 859 | static void hotplug_event_work(struct work_struct *work) |
1021 | printk(KERN_ERR "Device %s cannot be configured due" | 860 | { |
1022 | " to a bus mode mismatch\n", objname); | 861 | struct acpiphp_context *context; |
1023 | break; | 862 | struct acpi_hp_work *hp_work; |
1024 | 863 | ||
1025 | case ACPI_NOTIFY_POWER_FAULT: | 864 | hp_work = container_of(work, struct acpi_hp_work, work); |
1026 | printk(KERN_ERR "Device %s has suffered a power fault\n", | 865 | context = hp_work->context; |
1027 | objname); | 866 | acpi_scan_lock_acquire(); |
1028 | break; | ||
1029 | 867 | ||
1030 | default: | 868 | hotplug_event(hp_work->handle, hp_work->type, context); |
1031 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); | ||
1032 | break; | ||
1033 | } | ||
1034 | 869 | ||
1035 | acpi_scan_lock_release(); | 870 | acpi_scan_lock_release(); |
1036 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 871 | kfree(hp_work); /* allocated in handle_hotplug_event() */ |
1037 | put_bridge(bridge); | 872 | put_bridge(context->func.parent); |
1038 | } | 873 | } |
1039 | 874 | ||
1040 | /** | 875 | /** |
1041 | * handle_hotplug_event_bridge - handle ACPI event on bridges | 876 | * handle_hotplug_event - handle ACPI hotplug event |
1042 | * @handle: Notify()'ed acpi_handle | 877 | * @handle: Notify()'ed acpi_handle |
1043 | * @type: Notify code | 878 | * @type: Notify code |
1044 | * @context: pointer to acpiphp_bridge structure | 879 | * @data: pointer to acpiphp_context structure |
1045 | * | 880 | * |
1046 | * Handles ACPI event notification on {host,p2p} bridges. | 881 | * Handles ACPI event notification on slots. |
1047 | */ | 882 | */ |
1048 | static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, | 883 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) |
1049 | void *context) | ||
1050 | { | ||
1051 | struct acpiphp_bridge *bridge = context; | ||
1052 | |||
1053 | /* | ||
1054 | * Currently the code adds all hotplug events to the kacpid_wq | ||
1055 | * queue when it should add hotplug events to the kacpi_hotplug_wq. | ||
1056 | * The proper way to fix this is to reorganize the code so that | ||
1057 | * drivers (dock, etc.) do not call acpi_os_execute(), etc. | ||
1058 | * For now just re-add this work to the kacpi_hotplug_wq so we | ||
1059 | * don't deadlock on hotplug actions. | ||
1060 | */ | ||
1061 | get_bridge(bridge); | ||
1062 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); | ||
1063 | } | ||
1064 | |||
1065 | static void hotplug_event_func(acpi_handle handle, u32 type, void *context) | ||
1066 | { | 884 | { |
1067 | struct acpiphp_func *func = context; | 885 | struct acpiphp_context *context; |
1068 | char objname[64]; | ||
1069 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
1070 | .pointer = objname }; | ||
1071 | |||
1072 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
1073 | 886 | ||
1074 | switch (type) { | 887 | switch (type) { |
1075 | case ACPI_NOTIFY_BUS_CHECK: | 888 | case ACPI_NOTIFY_BUS_CHECK: |
1076 | /* bus re-enumerate */ | ||
1077 | dbg("%s: Bus check notify on %s\n", __func__, objname); | ||
1078 | acpiphp_enable_slot(func->slot); | ||
1079 | break; | ||
1080 | |||
1081 | case ACPI_NOTIFY_DEVICE_CHECK: | 889 | case ACPI_NOTIFY_DEVICE_CHECK: |
1082 | /* device check : re-enumerate from parent bus */ | ||
1083 | dbg("%s: Device check notify on %s\n", __func__, objname); | ||
1084 | acpiphp_check_bridge(func->slot->bridge); | ||
1085 | break; | ||
1086 | |||
1087 | case ACPI_NOTIFY_DEVICE_WAKE: | ||
1088 | /* wake event */ | ||
1089 | dbg("%s: Device wake notify on %s\n", __func__, objname); | ||
1090 | break; | ||
1091 | |||
1092 | case ACPI_NOTIFY_EJECT_REQUEST: | 890 | case ACPI_NOTIFY_EJECT_REQUEST: |
1093 | /* request device eject */ | ||
1094 | dbg("%s: Device eject notify on %s\n", __func__, objname); | ||
1095 | if (!(acpiphp_disable_slot(func->slot))) | ||
1096 | acpiphp_eject_slot(func->slot); | ||
1097 | break; | 891 | break; |
1098 | 892 | ||
1099 | default: | 893 | case ACPI_NOTIFY_DEVICE_WAKE: |
1100 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); | 894 | return; |
1101 | break; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | static void _handle_hotplug_event_func(struct work_struct *work) | ||
1106 | { | ||
1107 | struct acpi_hp_work *hp_work; | ||
1108 | struct acpiphp_func *func; | ||
1109 | 895 | ||
1110 | hp_work = container_of(work, struct acpi_hp_work, work); | 896 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
1111 | func = hp_work->context; | 897 | acpi_handle_err(handle, "Device cannot be configured due " |
1112 | acpi_scan_lock_acquire(); | 898 | "to a frequency mismatch\n"); |
899 | return; | ||
1113 | 900 | ||
1114 | hotplug_event_func(hp_work->handle, hp_work->type, func); | 901 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
902 | acpi_handle_err(handle, "Device cannot be configured due " | ||
903 | "to a bus mode mismatch\n"); | ||
904 | return; | ||
1115 | 905 | ||
1116 | acpi_scan_lock_release(); | 906 | case ACPI_NOTIFY_POWER_FAULT: |
1117 | kfree(hp_work); /* allocated in handle_hotplug_event_func */ | 907 | acpi_handle_err(handle, "Device has suffered a power fault\n"); |
1118 | put_bridge(func->slot->bridge); | 908 | return; |
1119 | } | ||
1120 | 909 | ||
1121 | /** | 910 | default: |
1122 | * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) | 911 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); |
1123 | * @handle: Notify()'ed acpi_handle | 912 | return; |
1124 | * @type: Notify code | 913 | } |
1125 | * @context: pointer to acpiphp_func structure | ||
1126 | * | ||
1127 | * Handles ACPI event notification on slots. | ||
1128 | */ | ||
1129 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, | ||
1130 | void *context) | ||
1131 | { | ||
1132 | struct acpiphp_func *func = context; | ||
1133 | 914 | ||
1134 | /* | 915 | mutex_lock(&acpiphp_context_lock); |
1135 | * Currently the code adds all hotplug events to the kacpid_wq | 916 | context = acpiphp_get_context(handle); |
1136 | * queue when it should add hotplug events to the kacpi_hotplug_wq. | 917 | if (context) { |
1137 | * The proper way to fix this is to reorganize the code so that | 918 | get_bridge(context->func.parent); |
1138 | * drivers (dock, etc.) do not call acpi_os_execute(), etc. | 919 | acpiphp_put_context(context); |
1139 | * For now just re-add this work to the kacpi_hotplug_wq so we | 920 | alloc_acpi_hp_work(handle, type, context, hotplug_event_work); |
1140 | * don't deadlock on hotplug actions. | 921 | } |
1141 | */ | 922 | mutex_unlock(&acpiphp_context_lock); |
1142 | get_bridge(func->slot->bridge); | ||
1143 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); | ||
1144 | } | 923 | } |
1145 | 924 | ||
1146 | /* | 925 | /* |
1147 | * Create hotplug slots for the PCI bus. | 926 | * Create hotplug slots for the PCI bus. |
1148 | * It should always return 0 to avoid skipping following notifiers. | 927 | * It should always return 0 to avoid skipping following notifiers. |
1149 | */ | 928 | */ |
1150 | void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) | 929 | void acpiphp_enumerate_slots(struct pci_bus *bus) |
1151 | { | 930 | { |
1152 | struct acpiphp_bridge *bridge; | 931 | struct acpiphp_bridge *bridge; |
932 | acpi_handle handle; | ||
933 | acpi_status status; | ||
1153 | 934 | ||
1154 | if (acpiphp_disabled) | 935 | if (acpiphp_disabled) |
1155 | return; | 936 | return; |
1156 | 937 | ||
1157 | if (detect_ejectable_slots(handle) <= 0) | 938 | handle = ACPI_HANDLE(bus->bridge); |
939 | if (!handle) | ||
1158 | return; | 940 | return; |
1159 | 941 | ||
1160 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 942 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
1161 | if (bridge == NULL) { | 943 | if (!bridge) { |
1162 | err("out of memory\n"); | 944 | acpi_handle_err(handle, "No memory for bridge object\n"); |
1163 | return; | 945 | return; |
1164 | } | 946 | } |
1165 | 947 | ||
1166 | INIT_LIST_HEAD(&bridge->slots); | 948 | INIT_LIST_HEAD(&bridge->slots); |
1167 | kref_init(&bridge->ref); | 949 | kref_init(&bridge->ref); |
1168 | bridge->handle = handle; | ||
1169 | bridge->pci_dev = pci_dev_get(bus->self); | 950 | bridge->pci_dev = pci_dev_get(bus->self); |
1170 | bridge->pci_bus = bus; | 951 | bridge->pci_bus = bus; |
1171 | 952 | ||
@@ -1176,30 +957,62 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) | |||
1176 | */ | 957 | */ |
1177 | get_device(&bus->dev); | 958 | get_device(&bus->dev); |
1178 | 959 | ||
1179 | if (!pci_is_root_bus(bridge->pci_bus) && | 960 | if (!pci_is_root_bus(bridge->pci_bus)) { |
1180 | acpi_has_method(bridge->handle, "_EJ0")) { | 961 | struct acpiphp_context *context; |
1181 | dbg("found ejectable p2p bridge\n"); | 962 | |
1182 | bridge->flags |= BRIDGE_HAS_EJ0; | 963 | /* |
1183 | bridge->func = acpiphp_bridge_handle_to_function(handle); | 964 | * This bridge should have been registered as a hotplug function |
965 | * under its parent, so the context has to be there. If not, we | ||
966 | * are in deep goo. | ||
967 | */ | ||
968 | mutex_lock(&acpiphp_context_lock); | ||
969 | context = acpiphp_get_context(handle); | ||
970 | if (WARN_ON(!context)) { | ||
971 | mutex_unlock(&acpiphp_context_lock); | ||
972 | put_device(&bus->dev); | ||
973 | kfree(bridge); | ||
974 | return; | ||
975 | } | ||
976 | bridge->context = context; | ||
977 | context->bridge = bridge; | ||
978 | /* Get a reference to the parent bridge. */ | ||
979 | get_bridge(context->func.parent); | ||
980 | mutex_unlock(&acpiphp_context_lock); | ||
1184 | } | 981 | } |
1185 | 982 | ||
1186 | init_bridge_misc(bridge); | 983 | /* must be added to the list prior to calling register_slot */ |
984 | mutex_lock(&bridge_mutex); | ||
985 | list_add(&bridge->list, &bridge_list); | ||
986 | mutex_unlock(&bridge_mutex); | ||
987 | |||
988 | /* register all slot objects under this bridge */ | ||
989 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
990 | register_slot, NULL, bridge, NULL); | ||
991 | if (ACPI_FAILURE(status)) { | ||
992 | acpi_handle_err(handle, "failed to register slots\n"); | ||
993 | cleanup_bridge(bridge); | ||
994 | put_bridge(bridge); | ||
995 | } | ||
1187 | } | 996 | } |
1188 | 997 | ||
1189 | /* Destroy hotplug slots associated with the PCI bus */ | 998 | /* Destroy hotplug slots associated with the PCI bus */ |
1190 | void acpiphp_remove_slots(struct pci_bus *bus) | 999 | void acpiphp_remove_slots(struct pci_bus *bus) |
1191 | { | 1000 | { |
1192 | struct acpiphp_bridge *bridge, *tmp; | 1001 | struct acpiphp_bridge *bridge; |
1193 | 1002 | ||
1194 | if (acpiphp_disabled) | 1003 | if (acpiphp_disabled) |
1195 | return; | 1004 | return; |
1196 | 1005 | ||
1197 | list_for_each_entry_safe(bridge, tmp, &bridge_list, list) | 1006 | mutex_lock(&bridge_mutex); |
1007 | list_for_each_entry(bridge, &bridge_list, list) | ||
1198 | if (bridge->pci_bus == bus) { | 1008 | if (bridge->pci_bus == bus) { |
1009 | mutex_unlock(&bridge_mutex); | ||
1199 | cleanup_bridge(bridge); | 1010 | cleanup_bridge(bridge); |
1200 | put_bridge(bridge); | 1011 | put_bridge(bridge); |
1201 | break; | 1012 | return; |
1202 | } | 1013 | } |
1014 | |||
1015 | mutex_unlock(&bridge_mutex); | ||
1203 | } | 1016 | } |
1204 | 1017 | ||
1205 | /** | 1018 | /** |
@@ -1208,51 +1021,39 @@ void acpiphp_remove_slots(struct pci_bus *bus) | |||
1208 | */ | 1021 | */ |
1209 | int acpiphp_enable_slot(struct acpiphp_slot *slot) | 1022 | int acpiphp_enable_slot(struct acpiphp_slot *slot) |
1210 | { | 1023 | { |
1211 | int retval; | ||
1212 | |||
1213 | mutex_lock(&slot->crit_sect); | 1024 | mutex_lock(&slot->crit_sect); |
1025 | /* configure all functions */ | ||
1026 | if (!(slot->flags & SLOT_ENABLED)) | ||
1027 | enable_slot(slot); | ||
1214 | 1028 | ||
1215 | /* wake up all functions */ | ||
1216 | retval = power_on_slot(slot); | ||
1217 | if (retval) | ||
1218 | goto err_exit; | ||
1219 | |||
1220 | if (get_slot_status(slot) == ACPI_STA_ALL) { | ||
1221 | /* configure all functions */ | ||
1222 | retval = enable_device(slot); | ||
1223 | if (retval) | ||
1224 | power_off_slot(slot); | ||
1225 | } else { | ||
1226 | dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__); | ||
1227 | power_off_slot(slot); | ||
1228 | } | ||
1229 | |||
1230 | err_exit: | ||
1231 | mutex_unlock(&slot->crit_sect); | 1029 | mutex_unlock(&slot->crit_sect); |
1232 | return retval; | 1030 | return 0; |
1233 | } | 1031 | } |
1234 | 1032 | ||
1235 | /** | 1033 | /** |
1236 | * acpiphp_disable_slot - power off slot | 1034 | * acpiphp_disable_and_eject_slot - power off and eject slot |
1237 | * @slot: ACPI PHP slot | 1035 | * @slot: ACPI PHP slot |
1238 | */ | 1036 | */ |
1239 | int acpiphp_disable_slot(struct acpiphp_slot *slot) | 1037 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) |
1240 | { | 1038 | { |
1039 | struct acpiphp_func *func; | ||
1241 | int retval = 0; | 1040 | int retval = 0; |
1242 | 1041 | ||
1243 | mutex_lock(&slot->crit_sect); | 1042 | mutex_lock(&slot->crit_sect); |
1244 | 1043 | ||
1245 | /* unconfigure all functions */ | 1044 | /* unconfigure all functions */ |
1246 | retval = disable_device(slot); | 1045 | disable_slot(slot); |
1247 | if (retval) | 1046 | |
1248 | goto err_exit; | 1047 | list_for_each_entry(func, &slot->funcs, sibling) |
1048 | if (func->flags & FUNC_HAS_EJ0) { | ||
1049 | acpi_handle handle = func_to_handle(func); | ||
1249 | 1050 | ||
1250 | /* power off all functions */ | 1051 | if (ACPI_FAILURE(acpi_evaluate_ej0(handle))) |
1251 | retval = power_off_slot(slot); | 1052 | acpi_handle_err(handle, "_EJ0 failed\n"); |
1252 | if (retval) | 1053 | |
1253 | goto err_exit; | 1054 | break; |
1055 | } | ||
1254 | 1056 | ||
1255 | err_exit: | ||
1256 | mutex_unlock(&slot->crit_sect); | 1057 | mutex_unlock(&slot->crit_sect); |
1257 | return retval; | 1058 | return retval; |
1258 | } | 1059 | } |
@@ -1264,7 +1065,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) | |||
1264 | */ | 1065 | */ |
1265 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | 1066 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) |
1266 | { | 1067 | { |
1267 | return (slot->flags & SLOT_POWEREDON); | 1068 | return (slot->flags & SLOT_ENABLED); |
1268 | } | 1069 | } |
1269 | 1070 | ||
1270 | 1071 | ||
@@ -1274,11 +1075,7 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | |||
1274 | */ | 1075 | */ |
1275 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | 1076 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) |
1276 | { | 1077 | { |
1277 | unsigned int sta; | 1078 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); |
1278 | |||
1279 | sta = get_slot_status(slot); | ||
1280 | |||
1281 | return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1; | ||
1282 | } | 1079 | } |
1283 | 1080 | ||
1284 | 1081 | ||
@@ -1288,9 +1085,5 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
1288 | */ | 1085 | */ |
1289 | u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) | 1086 | u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) |
1290 | { | 1087 | { |
1291 | unsigned int sta; | 1088 | return !!get_slot_status(slot); |
1292 | |||
1293 | sta = get_slot_status(slot); | ||
1294 | |||
1295 | return (sta == 0) ? 0 : 1; | ||
1296 | } | 1089 | } |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index c35e8ad6db01..8d45f6d69540 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
@@ -66,7 +66,7 @@ do { \ | |||
66 | #define IBM_HARDWARE_ID1 "IBM37D0" | 66 | #define IBM_HARDWARE_ID1 "IBM37D0" |
67 | #define IBM_HARDWARE_ID2 "IBM37D4" | 67 | #define IBM_HARDWARE_ID2 "IBM37D4" |
68 | 68 | ||
69 | #define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun) | 69 | #define hpslot_to_sun(A) (((struct slot *)((A)->private))->sun) |
70 | 70 | ||
71 | /* union apci_descriptor - allows access to the | 71 | /* union apci_descriptor - allows access to the |
72 | * various device descriptors that are embedded in the | 72 | * various device descriptors that are embedded in the |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 01e264fb50e0..7c29ee4ed0ae 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -210,7 +210,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
210 | } | 210 | } |
211 | 211 | ||
212 | if (!error) | 212 | if (!error) |
213 | dev_info(&dev->dev, "power state changed by ACPI to %s\n", | 213 | dev_dbg(&dev->dev, "power state changed by ACPI to %s\n", |
214 | acpi_power_state_string(state_conv[state])); | 214 | acpi_power_state_string(state_conv[state])); |
215 | 215 | ||
216 | return error; | 216 | return error; |
@@ -290,24 +290,16 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { | |||
290 | 290 | ||
291 | void acpi_pci_add_bus(struct pci_bus *bus) | 291 | void acpi_pci_add_bus(struct pci_bus *bus) |
292 | { | 292 | { |
293 | acpi_handle handle = NULL; | 293 | if (acpi_pci_disabled || !bus->bridge) |
294 | |||
295 | if (bus->bridge) | ||
296 | handle = ACPI_HANDLE(bus->bridge); | ||
297 | if (acpi_pci_disabled || handle == NULL) | ||
298 | return; | 294 | return; |
299 | 295 | ||
300 | acpi_pci_slot_enumerate(bus, handle); | 296 | acpi_pci_slot_enumerate(bus); |
301 | acpiphp_enumerate_slots(bus, handle); | 297 | acpiphp_enumerate_slots(bus); |
302 | } | 298 | } |
303 | 299 | ||
304 | void acpi_pci_remove_bus(struct pci_bus *bus) | 300 | void acpi_pci_remove_bus(struct pci_bus *bus) |
305 | { | 301 | { |
306 | /* | 302 | if (acpi_pci_disabled || !bus->bridge) |
307 | * bus->bridge->acpi_node.handle has already been reset to NULL | ||
308 | * when acpi_pci_remove_bus() is called, so don't check ACPI handle. | ||
309 | */ | ||
310 | if (acpi_pci_disabled) | ||
311 | return; | 303 | return; |
312 | 304 | ||
313 | acpiphp_remove_slots(bus); | 305 | acpiphp_remove_slots(bus); |