aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Chiang <achiang@hp.com>2009-06-10 15:55:30 -0400
committerLen Brown <len.brown@intel.com>2009-06-17 23:22:16 -0400
commit499650de6906722184b639989b47227a362b62f8 (patch)
treef0920b27dc659fb976f3ac2ca77bca6a386cd6c0
parentc22d7f5a389dad15de448b142f44e4000b3426f0 (diff)
ACPI: eviscerate pci_bind.c
Now that we can dynamically convert an ACPI CA handle to a struct pci_dev at runtime, there's no need to statically bind them during boot. acpi_pci_bind/unbind are vastly simplified, and are only used to evaluate _PRT methods on P2P bridges and non-bridge children. This patch also changes the time-space tradeoff ever so slightly. Looking up the ACPI-PCI binding is never in the performance path, and by eliminating this caching, we save 24 bytes for each _ADR device in the ACPI namespace. This patch lays further groundwork to eventually eliminate the acpi_driver_ops.bind callback. Signed-off-by: Alex Chiang <achiang@hp.com> Acked-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/pci_bind.c245
-rw-r--r--drivers/acpi/pci_root.c2
-rw-r--r--include/acpi/acpi_drivers.h3
3 files changed, 39 insertions, 211 deletions
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index c283c29662a7..703d2a3e8012 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -24,12 +24,7 @@
24 */ 24 */
25 25
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h> 27#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/spinlock.h>
32#include <linux/pm.h>
33#include <linux/pci.h> 28#include <linux/pci.h>
34#include <linux/acpi.h> 29#include <linux/acpi.h>
35#include <acpi/acpi_bus.h> 30#include <acpi/acpi_bus.h>
@@ -111,238 +106,72 @@ EXPORT_SYMBOL(acpi_get_pci_id);
111 106
112static int acpi_pci_unbind(struct acpi_device *device) 107static int acpi_pci_unbind(struct acpi_device *device)
113{ 108{
114 int result = 0; 109 struct pci_dev *dev;
115 acpi_status status;
116 struct acpi_pci_data *data;
117 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
118
119
120 if (!device || !device->parent)
121 return -EINVAL;
122
123 status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
124 if (ACPI_FAILURE(status))
125 return -ENODEV;
126
127 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
128 (char *) buffer.pointer));
129 kfree(buffer.pointer);
130 110
131 status = 111 dev = acpi_get_pci_dev(device->handle);
132 acpi_get_data(device->handle, acpi_pci_data_handler, 112 if (!dev)
133 (void **)&data); 113 return 0;
134 if (ACPI_FAILURE(status)) {
135 result = -ENODEV;
136 goto end;
137 }
138 114
139 status = acpi_detach_data(device->handle, acpi_pci_data_handler); 115 if (dev->subordinate)
140 if (ACPI_FAILURE(status)) { 116 acpi_pci_irq_del_prt(pci_domain_nr(dev->bus),
141 ACPI_EXCEPTION((AE_INFO, status, 117 dev->subordinate->number);
142 "Unable to detach data from device %s",
143 acpi_device_bid(device)));
144 result = -ENODEV;
145 goto end;
146 }
147 if (data->dev->subordinate) {
148 acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
149 }
150 pci_dev_put(data->dev);
151 kfree(data);
152 118
153 end: 119 pci_dev_put(dev);
154 return result; 120 return 0;
155} 121}
156 122
157static int acpi_pci_bind(struct acpi_device *device) 123static int acpi_pci_bind(struct acpi_device *device)
158{ 124{
159 int result = 0;
160 acpi_status status; 125 acpi_status status;
161 struct acpi_pci_data *data;
162 struct acpi_pci_data *pdata;
163 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
164 acpi_handle handle; 126 acpi_handle handle;
127 unsigned char bus;
128 struct pci_dev *dev;
165 129
166 if (!device || !device->parent) 130 dev = acpi_get_pci_dev(device->handle);
167 return -EINVAL; 131 if (!dev)
168 132 return 0;
169 data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
170 if (!data)
171 return -ENOMEM;
172
173 status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
174 if (ACPI_FAILURE(status)) {
175 kfree(data);
176 return -ENODEV;
177 }
178
179 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
180 (char *)buffer.pointer));
181
182 /*
183 * Segment & Bus
184 * -------------
185 * These are obtained via the parent device's ACPI-PCI context.
186 */
187 status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
188 (void **)&pdata);
189 if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
190 ACPI_EXCEPTION((AE_INFO, status,
191 "Invalid ACPI-PCI context for parent device %s",
192 acpi_device_bid(device->parent)));
193 result = -ENODEV;
194 goto end;
195 }
196 data->id.segment = pdata->id.segment;
197 data->id.bus = pdata->bus->number;
198
199 /*
200 * Device & Function
201 * -----------------
202 * These are simply obtained from the device's _ADR method. Note
203 * that a value of zero is valid.
204 */
205 data->id.device = device->pnp.bus_address >> 16;
206 data->id.function = device->pnp.bus_address & 0xFFFF;
207
208 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n",
209 data->id.segment, data->id.bus, data->id.device,
210 data->id.function));
211
212 /*
213 * TBD: Support slot devices (e.g. function=0xFFFF).
214 */
215
216 /*
217 * Locate PCI Device
218 * -----------------
219 * Locate matching device in PCI namespace. If it doesn't exist
220 * this typically means that the device isn't currently inserted
221 * (e.g. docking station, port replicator, etc.).
222 */
223 data->dev = pci_get_slot(pdata->bus,
224 PCI_DEVFN(data->id.device, data->id.function));
225 if (!data->dev) {
226 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
227 "Device %04x:%02x:%02x.%d not present in PCI namespace\n",
228 data->id.segment, data->id.bus,
229 data->id.device, data->id.function));
230 result = -ENODEV;
231 goto end;
232 }
233 if (!data->dev->bus) {
234 printk(KERN_ERR PREFIX
235 "Device %04x:%02x:%02x.%d has invalid 'bus' field\n",
236 data->id.segment, data->id.bus,
237 data->id.device, data->id.function);
238 result = -ENODEV;
239 goto end;
240 }
241 133
242 /* 134 /*
243 * PCI Bridge? 135 * Install the 'bind' function to facilitate callbacks for
244 * ----------- 136 * children of the P2P bridge.
245 * If so, set the 'bus' field and install the 'bind' function to
246 * facilitate callbacks for all of its children.
247 */ 137 */
248 if (data->dev->subordinate) { 138 if (dev->subordinate) {
249 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 139 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
250 "Device %04x:%02x:%02x.%d is a PCI bridge\n", 140 "Device %04x:%02x:%02x.%d is a PCI bridge\n",
251 data->id.segment, data->id.bus, 141 pci_domain_nr(dev->bus), dev->bus->number,
252 data->id.device, data->id.function)); 142 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
253 data->bus = data->dev->subordinate;
254 device->ops.bind = acpi_pci_bind; 143 device->ops.bind = acpi_pci_bind;
255 device->ops.unbind = acpi_pci_unbind; 144 device->ops.unbind = acpi_pci_unbind;
256 } 145 }
257 146
258 /* 147 /*
259 * Attach ACPI-PCI Context 148 * Evaluate and parse _PRT, if exists. This code allows parsing of
260 * ----------------------- 149 * _PRT objects within the scope of non-bridge devices. Note that
261 * Thus binding the ACPI and PCI devices. 150 * _PRTs within the scope of a PCI bridge assume the bridge's
262 */ 151 * subordinate bus number.
263 status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
264 if (ACPI_FAILURE(status)) {
265 ACPI_EXCEPTION((AE_INFO, status,
266 "Unable to attach ACPI-PCI context to device %s",
267 acpi_device_bid(device)));
268 result = -ENODEV;
269 goto end;
270 }
271
272 /*
273 * PCI Routing Table
274 * -----------------
275 * Evaluate and parse _PRT, if exists. This code is independent of
276 * PCI bridges (above) to allow parsing of _PRT objects within the
277 * scope of non-bridge devices. Note that _PRTs within the scope of
278 * a PCI bridge assume the bridge's subordinate bus number.
279 * 152 *
280 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? 153 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
281 */ 154 */
282 status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); 155 status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
283 if (ACPI_SUCCESS(status)) { 156 if (ACPI_FAILURE(status))
284 if (data->bus) /* PCI-PCI bridge */ 157 goto out;
285 acpi_pci_irq_add_prt(device->handle, data->id.segment,
286 data->bus->number);
287 else /* non-bridge PCI device */
288 acpi_pci_irq_add_prt(device->handle, data->id.segment,
289 data->id.bus);
290 }
291
292 end:
293 kfree(buffer.pointer);
294 if (result) {
295 pci_dev_put(data->dev);
296 kfree(data);
297 }
298 return result;
299}
300 158
301int 159 if (dev->subordinate)
302acpi_pci_bind_root(struct acpi_device *device, 160 bus = dev->subordinate->number;
303 struct acpi_pci_id *id, struct pci_bus *bus) 161 else
304{ 162 bus = dev->bus->number;
305 int result = 0;
306 acpi_status status;
307 struct acpi_pci_data *data = NULL;
308 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
309 163
310 if (!device || !id || !bus) { 164 acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
311 return -EINVAL;
312 }
313 165
314 data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); 166out:
315 if (!data) 167 pci_dev_put(dev);
316 return -ENOMEM; 168 return 0;
169}
317 170
318 data->id = *id; 171int acpi_pci_bind_root(struct acpi_device *device)
319 data->bus = bus; 172{
320 device->ops.bind = acpi_pci_bind; 173 device->ops.bind = acpi_pci_bind;
321 device->ops.unbind = acpi_pci_unbind; 174 device->ops.unbind = acpi_pci_unbind;
322 175
323 status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); 176 return 0;
324 if (ACPI_FAILURE(status)) {
325 kfree (data);
326 return -ENODEV;
327 }
328
329 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
330 "%04x:%02x\n", (char *)buffer.pointer,
331 id->segment, id->bus));
332
333 status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
334 if (ACPI_FAILURE(status)) {
335 ACPI_EXCEPTION((AE_INFO, status,
336 "Unable to attach ACPI-PCI context to device %s",
337 (char *)buffer.pointer));
338 result = -ENODEV;
339 goto end;
340 }
341
342 end:
343 kfree(buffer.pointer);
344 if (result != 0)
345 kfree(data);
346
347 return result;
348} 177}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index e5099919e574..f23fcc5c9674 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -603,7 +603,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
603 * ----------------------- 603 * -----------------------
604 * Thus binding the ACPI and PCI devices. 604 * Thus binding the ACPI and PCI devices.
605 */ 605 */
606 result = acpi_pci_bind_root(device, &root->id, root->bus); 606 result = acpi_pci_bind_root(device);
607 if (result) 607 if (result)
608 goto end; 608 goto end;
609 609
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index dbe3989952ee..2740a2894837 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -100,8 +100,7 @@ struct pci_bus;
100 100
101struct pci_dev *acpi_get_pci_dev(acpi_handle); 101struct pci_dev *acpi_get_pci_dev(acpi_handle);
102acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id); 102acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id);
103int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id, 103int acpi_pci_bind_root(struct acpi_device *device);
104 struct pci_bus *bus);
105 104
106/* Arch-defined function to add a bus to the system */ 105/* Arch-defined function to add a bus to the system */
107 106