1 /*
2  * ACPI PCI HotPlug PCI configuration space management
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001,2002 IBM Corp.
7  * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
8  * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
9  * Copyright (C) 2002 NEC Corporation
10  *
11  * All rights reserved.
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or (at
16  * your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
21  * NON INFRINGEMENT.  See the GNU General Public License for more
22  * details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * Send feedback to <t-kochi@bq.jp.nec.com>
29  *
30  */
31 
32 #include <linux/init.h>
33 #include <linux/module.h>
34 
35 #include <linux/kernel.h>
36 #include <linux/pci.h>
37 #include "pci_hotplug.h"
38 #include "acpiphp.h"
39 
40 #define MY_NAME "acpiphp_pci"
41 
42 static void acpiphp_configure_irq (struct pci_dev *dev);
43 
44 
45 /* allocate mem/pmem/io resource to a new function */
init_config_space(struct acpiphp_func * func)46 static int init_config_space (struct acpiphp_func *func)
47 {
48 	u32 bar, len;
49 	u32 address[] = {
50 		PCI_BASE_ADDRESS_0,
51 		PCI_BASE_ADDRESS_1,
52 		PCI_BASE_ADDRESS_2,
53 		PCI_BASE_ADDRESS_3,
54 		PCI_BASE_ADDRESS_4,
55 		PCI_BASE_ADDRESS_5,
56 		0
57 	};
58 	int count;
59 	struct acpiphp_bridge *bridge;
60 	struct pci_resource *res;
61 	struct pci_bus *bus;
62 	int devfn;
63 
64 	bridge = func->slot->bridge;
65 	bus = bridge->pci_bus;
66 	devfn = PCI_DEVFN(func->slot->device, func->function);
67 
68 	for (count = 0; address[count]; count++) {	/* for 6 BARs */
69 		pci_bus_write_config_dword(bus, devfn, address[count], 0xFFFFFFFF);
70 		pci_bus_read_config_dword(bus, devfn, address[count], &bar);
71 
72 		if (!bar)	/* This BAR is not implemented */
73 			continue;
74 
75 		dbg("Device %02x.%d BAR %d wants %x\n", PCI_SLOT(devfn),
76 				PCI_FUNC(devfn), count, bar);
77 
78 		if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
79 			/* This is IO */
80 
81 			len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
82 			len = len & ~(len - 1);
83 
84 			dbg("len in IO %x, BAR %d\n", len, count);
85 
86 			spin_lock(&bridge->res_lock);
87 			res = acpiphp_get_io_resource(&bridge->io_head, len);
88 			spin_unlock(&bridge->res_lock);
89 
90 			if (!res) {
91 				err("cannot allocate requested io for %02x:%02x.%d len %x\n",
92 				    bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
93 				return -1;
94 			}
95 			pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
96 			res->next = func->io_head;
97 			func->io_head = res;
98 
99 		} else {
100 			/* This is Memory */
101 			if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
102 				/* pfmem */
103 
104 				len = bar & 0xFFFFFFF0;
105 				len = ~len + 1;
106 
107 				dbg("len in PFMEM %x, BAR %d\n", len, count);
108 
109 				spin_lock(&bridge->res_lock);
110 				res = acpiphp_get_resource(&bridge->p_mem_head, len);
111 				spin_unlock(&bridge->res_lock);
112 
113 				if (!res) {
114 					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
115 					    bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
116 					return -1;
117 				}
118 
119 				pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
120 
121 				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
122 					dbg("inside the pfmem 64 case, count %d\n", count);
123 					count += 1;
124 					pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32));
125 				}
126 
127 				res->next = func->p_mem_head;
128 				func->p_mem_head = res;
129 
130 			} else {
131 				/* regular memory */
132 
133 				len = bar & 0xFFFFFFF0;
134 				len = ~len + 1;
135 
136 				dbg("len in MEM %x, BAR %d\n", len, count);
137 
138 				spin_lock(&bridge->res_lock);
139 				res = acpiphp_get_resource(&bridge->mem_head, len);
140 				spin_unlock(&bridge->res_lock);
141 
142 				if (!res) {
143 					err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
144 					    bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
145 					return -1;
146 				}
147 
148 				pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
149 
150 				if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
151 					/* takes up another dword */
152 					dbg("inside mem 64 case, reg. mem, count %d\n", count);
153 					count += 1;
154 					pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32));
155 				}
156 
157 				res->next = func->mem_head;
158 				func->mem_head = res;
159 
160 			}
161 		}
162 	}
163 
164 	/* disable expansion rom */
165 	pci_bus_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, 0x00000000);
166 
167 	return 0;
168 }
169 
170 
171 /* enable pci_dev */
configure_pci_dev(struct pci_dev_wrapped * wrapped_dev,struct pci_bus_wrapped * wrapped_bus)172 static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
173 {
174 	u16 tmp;
175 	struct acpiphp_func *func;
176 	struct acpiphp_bridge *bridge;
177 	struct pci_dev *dev;
178 
179 	func = (struct acpiphp_func *)wrapped_dev->data;
180 	bridge = (struct acpiphp_bridge *)wrapped_bus->data;
181 	dev = wrapped_dev->dev;
182 
183 	/* TBD: support PCI-to-PCI bridge case */
184 	if (!func || !bridge)
185 		return 0;
186 
187 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, bridge->hpp.cache_line_size);
188 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer);
189 
190 	pci_read_config_word(dev, PCI_COMMAND, &tmp);
191 	if (bridge->hpp.enable_SERR)
192 		tmp |= PCI_COMMAND_SERR;
193 	if (bridge->hpp.enable_PERR)
194 		tmp |= PCI_COMMAND_PARITY;
195 	//tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
196 	pci_write_config_word(dev, PCI_COMMAND, tmp);
197 
198 	acpiphp_configure_irq(dev);
199 #ifdef CONFIG_PROC_FS
200 	pci_proc_attach_device(dev);
201 #endif
202 	pci_announce_device_to_drivers(dev);
203 	info("Device %s configured\n", dev->slot_name);
204 
205 	return 0;
206 }
207 
208 
is_pci_dev_in_use(struct pci_dev * dev)209 static int is_pci_dev_in_use (struct pci_dev* dev)
210 {
211 	/*
212 	 * dev->driver will be set if the device is in use by a new-style
213 	 * driver -- otherwise, check the device's regions to see if any
214 	 * driver has claimed them
215 	 */
216 
217 	int i, inuse=0;
218 
219 	if (dev->driver) return 1; //assume driver feels responsible
220 
221 	for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
222 		if (!pci_resource_start(dev, i))
223 			continue;
224 
225 		if (pci_resource_flags(dev, i) & IORESOURCE_IO)
226 			inuse = check_region(pci_resource_start(dev, i),
227 					     pci_resource_len(dev, i));
228 		else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
229 			inuse = check_mem_region(pci_resource_start(dev, i),
230 						 pci_resource_len(dev, i));
231 	}
232 
233 	return inuse;
234 }
235 
236 
pci_hp_remove_device(struct pci_dev * dev)237 static int pci_hp_remove_device (struct pci_dev *dev)
238 {
239 	if (is_pci_dev_in_use(dev)) {
240 		err("***Cannot safely power down device -- "
241 		       "it appears to be in use***\n");
242 		return -EBUSY;
243 	}
244 	pci_remove_device(dev);
245 	return 0;
246 }
247 
248 
249 /* remove device driver */
unconfigure_pci_dev_driver(struct pci_dev_wrapped * wrapped_dev,struct pci_bus_wrapped * wrapped_bus)250 static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
251 {
252 	struct pci_dev *dev = wrapped_dev->dev;
253 
254 	dbg("attempting removal of driver for device %s\n", dev->slot_name);
255 
256 	/* Now, remove the Linux Driver Representation */
257 	if (dev->driver) {
258 		if (dev->driver->remove) {
259 			dev->driver->remove(dev);
260 			dbg("driver was properly removed\n");
261 		}
262 		dev->driver = NULL;
263 	}
264 
265 	return is_pci_dev_in_use(dev);
266 }
267 
268 
269 /* remove pci_dev itself from system */
unconfigure_pci_dev(struct pci_dev_wrapped * wrapped_dev,struct pci_bus_wrapped * wrapped_bus)270 static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
271 {
272 	struct pci_dev *dev = wrapped_dev->dev;
273 
274 	/* Now, remove the Linux Representation */
275 	if (dev) {
276 		if (pci_hp_remove_device(dev) == 0) {
277 			info("Device %s removed\n", dev->slot_name);
278 			kfree(dev); /* Now, remove */
279 		} else {
280 			return -1; /* problems while freeing, abort visitation */
281 		}
282 	}
283 
284 	return 0;
285 }
286 
287 
288 /* remove pci_bus itself from system */
unconfigure_pci_bus(struct pci_bus_wrapped * wrapped_bus,struct pci_dev_wrapped * wrapped_dev)289 static int unconfigure_pci_bus (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev)
290 {
291 	struct pci_bus *bus = wrapped_bus->bus;
292 
293 #ifdef CONFIG_PROC_FS
294 	/* Now, remove the Linux Representation */
295 	if (bus->procdir) {
296 		pci_proc_detach_bus(bus);
297 	}
298 #endif
299 	/* the cleanup code should live in the kernel ... */
300 	bus->self->subordinate = NULL;
301 	/* unlink from parent bus */
302 	list_del(&bus->node);
303 
304 	/* Now, remove */
305 	if (bus)
306 		kfree(bus);
307 
308 	return 0;
309 }
310 
311 
312 /* detect_used_resource - subtract resource under dev from bridge */
detect_used_resource(struct acpiphp_bridge * bridge,struct pci_dev * dev)313 static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
314 {
315 	u32 bar, len;
316 	u64 base;
317 	u32 address[] = {
318 		PCI_BASE_ADDRESS_0,
319 		PCI_BASE_ADDRESS_1,
320 		PCI_BASE_ADDRESS_2,
321 		PCI_BASE_ADDRESS_3,
322 		PCI_BASE_ADDRESS_4,
323 		PCI_BASE_ADDRESS_5,
324 		0
325 	};
326 	int count;
327 	struct pci_resource *res;
328 
329 	dbg("Device %s\n", dev->slot_name);
330 
331 	for (count = 0; address[count]; count++) {	/* for 6 BARs */
332 		pci_read_config_dword(dev, address[count], &bar);
333 
334 		if (!bar)	/* This BAR is not implemented */
335 			continue;
336 
337 		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
338 		pci_read_config_dword(dev, address[count], &len);
339 
340 		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
341 			/* This is IO */
342 			base = bar & 0xFFFFFFFC;
343 			len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
344 			len = len & ~(len - 1);
345 
346 			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
347 
348 			spin_lock(&bridge->res_lock);
349 			res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
350 			spin_unlock(&bridge->res_lock);
351 			if (res)
352 				kfree(res);
353 		} else {
354 			/* This is Memory */
355 			base = bar & 0xFFFFFFF0;
356 			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
357 				/* pfmem */
358 
359 				len &= 0xFFFFFFF0;
360 				len = ~len + 1;
361 
362 				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
363 					dbg("prefetch mem 64\n");
364 					count += 1;
365 				}
366 				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
367 				spin_lock(&bridge->res_lock);
368 				res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
369 				spin_unlock(&bridge->res_lock);
370 				if (res)
371 					kfree(res);
372 			} else {
373 				/* regular memory */
374 
375 				len &= 0xFFFFFFF0;
376 				len = ~len + 1;
377 
378 				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
379 					/* takes up another dword */
380 					dbg("mem 64\n");
381 					count += 1;
382 				}
383 				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
384 				spin_lock(&bridge->res_lock);
385 				res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
386 				spin_unlock(&bridge->res_lock);
387 				if (res)
388 					kfree(res);
389 			}
390 		}
391 
392 		pci_write_config_dword(dev, address[count], bar);
393 	}
394 
395 	return 0;
396 }
397 
398 
399 /* detect_pci_resource_bus - subtract resource under pci_bus */
detect_used_resource_bus(struct acpiphp_bridge * bridge,struct pci_bus * bus)400 static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus)
401 {
402 	struct list_head *l;
403 	struct pci_dev *dev;
404 
405 	list_for_each (l, &bus->devices) {
406 		dev = pci_dev_b(l);
407 		detect_used_resource(bridge, dev);
408 		/* XXX recursive call */
409 		if (dev->subordinate)
410 			detect_used_resource_bus(bridge, dev->subordinate);
411 	}
412 }
413 
414 
415 /**
416  * acpiphp_detect_pci_resource - detect resources under bridge
417  * @bridge: detect all resources already used under this bridge
418  *
419  * collect all resources already allocated for all devices under a bridge.
420  */
acpiphp_detect_pci_resource(struct acpiphp_bridge * bridge)421 int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
422 {
423 	detect_used_resource_bus(bridge, bridge->pci_bus);
424 
425 	return 0;
426 }
427 
428 
429 /**
430  * acpiphp_init_slot_resource - gather resource usage information of a slot
431  * @slot: ACPI slot object to be checked, should have valid pci_dev member
432  *
433  * TBD: PCI-to-PCI bridge case
434  *      use pci_dev->resource[]
435  */
acpiphp_init_func_resource(struct acpiphp_func * func)436 int acpiphp_init_func_resource (struct acpiphp_func *func)
437 {
438 	u64 base;
439 	u32 bar, len;
440 	u32 address[] = {
441 		PCI_BASE_ADDRESS_0,
442 		PCI_BASE_ADDRESS_1,
443 		PCI_BASE_ADDRESS_2,
444 		PCI_BASE_ADDRESS_3,
445 		PCI_BASE_ADDRESS_4,
446 		PCI_BASE_ADDRESS_5,
447 		0
448 	};
449 	int count;
450 	struct pci_resource *res;
451 	struct pci_dev *dev;
452 
453 	dev = func->pci_dev;
454 	dbg("Hot-pluggable device %s\n", dev->slot_name);
455 
456 	for (count = 0; address[count]; count++) {	/* for 6 BARs */
457 		pci_read_config_dword(dev, address[count], &bar);
458 
459 		if (!bar)	/* This BAR is not implemented */
460 			continue;
461 
462 		pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
463 		pci_read_config_dword(dev, address[count], &len);
464 
465 		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
466 			/* This is IO */
467 			base = bar & 0xFFFFFFFC;
468 			len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
469 			len = len & ~(len - 1);
470 
471 			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
472 
473 			res = acpiphp_make_resource(base, len);
474 			if (!res)
475 				goto no_memory;
476 
477 			res->next = func->io_head;
478 			func->io_head = res;
479 
480 		} else {
481 			/* This is Memory */
482 			base = bar & 0xFFFFFFF0;
483 			if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
484 				/* pfmem */
485 
486 				len &= 0xFFFFFFF0;
487 				len = ~len + 1;
488 
489 				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {	/* takes up another dword */
490 					dbg("prefetch mem 64\n");
491 					count += 1;
492 				}
493 				dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
494 				res = acpiphp_make_resource(base, len);
495 				if (!res)
496 					goto no_memory;
497 
498 				res->next = func->p_mem_head;
499 				func->p_mem_head = res;
500 
501 			} else {
502 				/* regular memory */
503 
504 				len &= 0xFFFFFFF0;
505 				len = ~len + 1;
506 
507 				if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
508 					/* takes up another dword */
509 					dbg("mem 64\n");
510 					count += 1;
511 				}
512 				dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
513 				res = acpiphp_make_resource(base, len);
514 				if (!res)
515 					goto no_memory;
516 
517 				res->next = func->mem_head;
518 				func->mem_head = res;
519 
520 			}
521 		}
522 
523 		pci_write_config_dword(dev, address[count], bar);
524 	}
525 #if 1
526 	acpiphp_dump_func_resource(func);
527 #endif
528 
529 	return 0;
530 
531  no_memory:
532 	err("out of memory\n");
533 	acpiphp_free_resource(&func->io_head);
534 	acpiphp_free_resource(&func->mem_head);
535 	acpiphp_free_resource(&func->p_mem_head);
536 
537 	return -1;
538 }
539 
540 
541 /**
542  * acpiphp_configure_slot - allocate PCI resources
543  * @slot: slot to be configured
544  *
545  * initializes a PCI functions on a device inserted
546  * into the slot
547  *
548  */
acpiphp_configure_slot(struct acpiphp_slot * slot)549 int acpiphp_configure_slot (struct acpiphp_slot *slot)
550 {
551 	struct acpiphp_func *func;
552 	struct list_head *l;
553 	u8 hdr;
554 	u32 dvid;
555 	int retval = 0;
556 	int is_multi = 0;
557 
558 	pci_bus_read_config_byte(slot->bridge->pci_bus,
559 					PCI_DEVFN(slot->device, 0),
560 					PCI_HEADER_TYPE, &hdr);
561 
562 	if (hdr & 0x80)
563 		is_multi = 1;
564 
565 	list_for_each (l, &slot->funcs) {
566 		func = list_entry(l, struct acpiphp_func, sibling);
567 		if (is_multi || func->function == 0) {
568 			pci_bus_read_config_dword(slot->bridge->pci_bus,
569 						    PCI_DEVFN(slot->device,
570 								func->function),
571 						    PCI_VENDOR_ID, &dvid);
572 			if (dvid != 0xffffffff) {
573 				retval = init_config_space(func);
574 				if (retval)
575 					break;
576 			}
577 		}
578 	}
579 
580 	return retval;
581 }
582 
583 
584 /* for pci_visit_dev() */
585 static struct pci_visit configure_functions = {
586 	.post_visit_pci_dev =	configure_pci_dev
587 };
588 
589 static struct pci_visit unconfigure_functions_phase1 = {
590 	.post_visit_pci_dev =	unconfigure_pci_dev_driver
591 };
592 
593 static struct pci_visit unconfigure_functions_phase2 = {
594 	.post_visit_pci_bus =	unconfigure_pci_bus,
595 	.post_visit_pci_dev =	unconfigure_pci_dev
596 };
597 
598 
599 /**
600  * acpiphp_configure_function - configure PCI function
601  * @func: function to be configured
602  *
603  * initializes a PCI functions on a device inserted
604  * into the slot
605  *
606  */
acpiphp_configure_function(struct acpiphp_func * func)607 int acpiphp_configure_function (struct acpiphp_func *func)
608 {
609 	int retval = 0;
610 	struct pci_dev_wrapped wrapped_dev;
611 	struct pci_bus_wrapped wrapped_bus;
612 	struct acpiphp_bridge *bridge;
613 
614 	/* if pci_dev is NULL, ignore it */
615 	if (!func->pci_dev)
616 		goto err_exit;
617 
618 	bridge = func->slot->bridge;
619 
620 	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
621 	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
622 	wrapped_dev.dev = func->pci_dev;
623 	wrapped_dev.data = func;
624 	wrapped_bus.bus = bridge->pci_bus;
625 	wrapped_bus.data = bridge;
626 
627 	retval = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
628 	if (retval)
629 		goto err_exit;
630 
631  err_exit:
632 	return retval;
633 }
634 
635 
636 /**
637  * acpiphp_unconfigure_function - unconfigure PCI function
638  * @func: function to be unconfigured
639  *
640  */
acpiphp_unconfigure_function(struct acpiphp_func * func)641 int acpiphp_unconfigure_function (struct acpiphp_func *func)
642 {
643 	struct acpiphp_bridge *bridge;
644 	struct pci_dev_wrapped wrapped_dev;
645 	struct pci_bus_wrapped wrapped_bus;
646 	int retval = 0;
647 
648 	/* if pci_dev is NULL, ignore it */
649 	if (!func->pci_dev)
650 		goto err_exit;
651 
652 	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
653 	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
654 	wrapped_dev.dev = func->pci_dev;
655 	//wrapped_dev.data = func;
656 	wrapped_bus.bus = func->slot->bridge->pci_bus;
657 	//wrapped_bus.data = func->slot->bridge;
658 
659 	retval = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
660 	if (retval)
661 		goto err_exit;
662 
663 	retval = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
664 	if (retval)
665 		goto err_exit;
666 
667 	/* free all resources */
668 	bridge = func->slot->bridge;
669 
670 	spin_lock(&bridge->res_lock);
671 	acpiphp_move_resource(&func->io_head, &bridge->io_head);
672 	acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
673 	acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
674 	acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
675 	spin_unlock(&bridge->res_lock);
676 
677  err_exit:
678 	return retval;
679 }
680 
681 
682 /*
683  * acpiphp_configure_irq - configure PCI_INTERRUPT_PIN
684  *
685  * for x86 platforms, pcibios_enable_device calls pcibios_enable_irq,
686  * which allocates irq for pci_dev
687  *
688  * for IA64 platforms, we have to program dev->irq from pci IRQ routing
689  * information derived from ACPI table
690  *
691  * TBD:
692  * separate architecture dependent part
693  * (preferably, pci_enable_device() cares for allocating irq...)
694  */
acpiphp_configure_irq(struct pci_dev * dev)695 static void acpiphp_configure_irq (struct pci_dev *dev)
696 {
697 #if CONFIG_IA64		    /* XXX IA64 specific */
698 	extern void iosapic_fixup_pci_interrupt (struct pci_dev *dev);
699 
700 	iosapic_fixup_pci_interrupt(dev);
701 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
702 #endif
703 }
704