2 * PCI Express Hot Plug Controller Driver
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001 IBM Corp.
7 * Copyright (C) 2003-2004 Intel Corporation
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19 * NON INFRINGEMENT. See the GNU General Public License for more
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/types.h>
34 #include <linux/slab.h>
35 #include <linux/workqueue.h>
36 #include <linux/proc_fs.h>
37 #include <linux/pci.h>
41 #include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
45 int pciehp_configure_device (struct controller
* ctrl
, struct pci_func
* func
)
48 struct pci_bus
*child
;
51 if (func
->pci_dev
== NULL
)
52 func
->pci_dev
= pci_find_slot(func
->bus
, PCI_DEVFN(func
->device
, func
->function
));
54 /* Still NULL ? Well then scan for it ! */
55 if (func
->pci_dev
== NULL
) {
56 dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__
);
58 num
= pci_scan_slot(ctrl
->pci_dev
->subordinate
, PCI_DEVFN(func
->device
, func
->function
));
61 pci_bus_add_devices(ctrl
->pci_dev
->subordinate
);
63 func
->pci_dev
= pci_find_slot(func
->bus
, PCI_DEVFN(func
->device
, func
->function
));
64 if (func
->pci_dev
== NULL
) {
65 dbg("ERROR: pci_dev still null\n");
70 if (func
->pci_dev
->hdr_type
== PCI_HEADER_TYPE_BRIDGE
) {
71 pci_read_config_byte(func
->pci_dev
, PCI_SECONDARY_BUS
, &bus
);
72 child
= pci_add_new_bus(func
->pci_dev
->bus
, (func
->pci_dev
), bus
);
73 pci_do_scan_bus(child
);
81 int pciehp_unconfigure_device(struct pci_func
* func
)
86 dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__
, func
->bus
,
87 func
->device
, func
->function
);
89 for (j
=0; j
<8 ; j
++) {
90 struct pci_dev
* temp
= pci_find_slot(func
->bus
,
91 (func
->device
<< 3) | j
);
93 pci_remove_bus_device(temp
);
102 * @bus_num: bus number of PCI device
103 * @dev_num: device number of PCI device
104 * @slot: pointer to u8 where slot number will be returned
106 int pciehp_set_irq (u8 bus_num
, u8 dev_num
, u8 int_pin
, u8 irq_num
)
108 #if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
111 struct pci_dev fakedev
;
112 struct pci_bus fakebus
;
114 fakedev
.devfn
= dev_num
<< 3;
115 fakedev
.bus
= &fakebus
;
116 fakebus
.number
= bus_num
;
117 dbg("%s: dev %d, bus %d, pin %d, num %d\n",
118 __FUNCTION__
, dev_num
, bus_num
, int_pin
, irq_num
);
119 rc
= pcibios_set_irq_routing(&fakedev
, int_pin
- 0x0a, irq_num
);
120 dbg("%s: rc %d\n", __FUNCTION__
, rc
);
124 /* set the Edge Level Control Register (ELCR) */
125 temp_word
= inb(0x4d0);
126 temp_word
|= inb(0x4d1) << 8;
128 temp_word
|= 0x01 << irq_num
;
130 /* This should only be for x86 as it sets the Edge Level Control Register */
131 outb((u8
) (temp_word
& 0xFF), 0x4d0);
132 outb((u8
) ((temp_word
& 0xFF00) >> 8), 0x4d1);
137 /* More PCI configuration routines; this time centered around hotplug controller */
143 * Reads configuration for all slots in a PCI bus and saves info.
145 * Note: For non-hot plug busses, the slot # saved is the device #
147 * returns 0 if success
149 int pciehp_save_config(struct controller
*ctrl
, int busnumber
, int num_ctlr_slots
, int first_device_num
)
156 struct pci_func
*new_slot
;
165 int is_hot_plug
= num_ctlr_slots
|| first_device_num
;
166 struct pci_bus lpci_bus
, *pci_bus
;
167 int FirstSupported
, LastSupported
;
169 dbg("%s: Enter\n", __FUNCTION__
);
171 memcpy(&lpci_bus
, ctrl
->pci_dev
->subordinate
, sizeof(lpci_bus
));
174 dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__
,
175 num_ctlr_slots
, first_device_num
);
177 /* Decide which slots are supported */
179 /*********************************
180 * is_hot_plug is the slot mask
181 *********************************/
182 FirstSupported
= first_device_num
;
183 LastSupported
= FirstSupported
+ num_ctlr_slots
- 1;
186 LastSupported
= 0x1F;
189 dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported
,
192 /* Save PCI configuration space for all devices in supported slots */
193 dbg("%s: pci_bus->number = %x\n", __FUNCTION__
, pci_bus
->number
);
194 pci_bus
->number
= busnumber
;
195 dbg("%s: bus = %x, dev = %x\n", __FUNCTION__
, busnumber
, device
);
196 for (device
= FirstSupported
; device
<= LastSupported
; device
++) {
198 rc
= pci_bus_read_config_dword(pci_bus
, PCI_DEVFN(device
, 0),
201 if (ID
!= 0xFFFFFFFF) { /* device in slot */
202 dbg("%s: ID = %x\n", __FUNCTION__
, ID
);
203 rc
= pci_bus_read_config_byte(pci_bus
, PCI_DEVFN(device
, 0),
208 rc
= pci_bus_read_config_byte(pci_bus
, PCI_DEVFN(device
, 0),
209 PCI_HEADER_TYPE
, &header_type
);
213 dbg("class_code = %x, header_type = %x\n", class_code
, header_type
);
215 /* If multi-function device, set max_functions to 8 */
216 if (header_type
& 0x80)
225 dbg("%s: In do loop\n", __FUNCTION__
);
227 if ((header_type
& 0x7F) == PCI_HEADER_TYPE_BRIDGE
) { /* P-P Bridge */
228 /* Recurse the subordinate bus
229 * get the subordinate bus number
231 rc
= pci_bus_read_config_byte(pci_bus
,
232 PCI_DEVFN(device
, function
),
233 PCI_SECONDARY_BUS
, &secondary_bus
);
237 sub_bus
= (int) secondary_bus
;
239 /* Save secondary bus cfg spc with this recursive call. */
240 rc
= pciehp_save_config(ctrl
, sub_bus
, 0, 0);
247 new_slot
= pciehp_slot_find(busnumber
, device
, index
++);
249 dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
250 __FUNCTION__
, new_slot
, busnumber
, device
, index
-1);
252 while (new_slot
&& (new_slot
->function
!= (u8
) function
)) {
253 new_slot
= pciehp_slot_find(busnumber
, device
, index
++);
254 dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
255 __FUNCTION__
, new_slot
, busnumber
, device
, index
-1);
258 /* Setup slot structure. */
259 new_slot
= pciehp_slot_create(busnumber
);
260 dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
261 __FUNCTION__
, new_slot
, busnumber
, device
, function
);
263 if (new_slot
== NULL
)
267 new_slot
->bus
= (u8
) busnumber
;
268 new_slot
->device
= (u8
) device
;
269 new_slot
->function
= (u8
) function
;
270 new_slot
->is_a_board
= 1;
271 new_slot
->switch_save
= 0x10;
272 /* In case of unsupported board */
273 new_slot
->status
= DevError
;
274 new_slot
->pci_dev
= pci_find_slot(new_slot
->bus
,
275 (new_slot
->device
<< 3) | new_slot
->function
);
276 dbg("new_slot->pci_dev = %p\n", new_slot
->pci_dev
);
278 for (cloop
= 0; cloop
< 0x20; cloop
++) {
279 rc
= pci_bus_read_config_dword(pci_bus
,
280 PCI_DEVFN(device
, function
),
282 (u32
*) &(new_slot
->config_space
[cloop
]));
283 /* dbg("new_slot->config_space[%x] = %x\n",
284 cloop, new_slot->config_space[cloop]); */
293 /* this loop skips to the next present function
294 * reading in Class Code and Header type.
297 while ((function
< max_functions
)&&(!stop_it
)) {
298 dbg("%s: In while loop \n", __FUNCTION__
);
299 rc
= pci_bus_read_config_dword(pci_bus
,
300 PCI_DEVFN(device
, function
),
303 if (ID
== 0xFFFFFFFF) { /* nothing there. */
305 dbg("Nothing there\n");
306 } else { /* Something there */
307 rc
= pci_bus_read_config_byte(pci_bus
,
308 PCI_DEVFN(device
, function
),
313 rc
= pci_bus_read_config_byte(pci_bus
,
314 PCI_DEVFN(device
, function
),
315 PCI_HEADER_TYPE
, &header_type
);
319 dbg("class_code = %x, header_type = %x\n", class_code
, header_type
);
324 } while (function
< max_functions
);
325 /* End of IF (device in slot?) */
326 } else if (is_hot_plug
) {
327 /* Setup slot structure with entry for empty slot */
328 new_slot
= pciehp_slot_create(busnumber
);
330 if (new_slot
== NULL
) {
333 dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot
,
334 new_slot
->bus
, new_slot
->device
, new_slot
->function
);
336 new_slot
->bus
= (u8
) busnumber
;
337 new_slot
->device
= (u8
) device
;
338 new_slot
->function
= 0;
339 new_slot
->is_a_board
= 0;
340 new_slot
->presence_save
= 0;
341 new_slot
->switch_save
= 0;
343 } /* End of FOR loop */
345 dbg("%s: Exit\n", __FUNCTION__
);
351 * pciehp_save_slot_config
353 * Saves configuration info for all PCI devices in a given slot
354 * including subordinate busses.
356 * returns 0 if success
358 int pciehp_save_slot_config(struct controller
*ctrl
, struct pci_func
* new_slot
)
370 struct pci_bus lpci_bus
, *pci_bus
;
371 memcpy(&lpci_bus
, ctrl
->pci_dev
->subordinate
, sizeof(lpci_bus
));
373 pci_bus
->number
= new_slot
->bus
;
377 pci_bus_read_config_dword(pci_bus
, PCI_DEVFN(new_slot
->device
, 0),
380 if (ID
!= 0xFFFFFFFF) { /* device in slot */
381 pci_bus_read_config_byte(pci_bus
, PCI_DEVFN(new_slot
->device
, 0),
384 pci_bus_read_config_byte(pci_bus
, PCI_DEVFN(new_slot
->device
, 0),
385 PCI_HEADER_TYPE
, &header_type
);
387 if (header_type
& 0x80) /* Multi-function device */
395 if ((header_type
& 0x7F) == PCI_HEADER_TYPE_BRIDGE
) { /* PCI-PCI Bridge */
396 /* Recurse the subordinate bus */
397 pci_bus_read_config_byte(pci_bus
,
398 PCI_DEVFN(new_slot
->device
, function
),
399 PCI_SECONDARY_BUS
, &secondary_bus
);
401 sub_bus
= (int) secondary_bus
;
403 /* Save the config headers for the secondary bus. */
404 rc
= pciehp_save_config(ctrl
, sub_bus
, 0, 0);
411 new_slot
->status
= 0;
413 for (cloop
= 0; cloop
< 0x20; cloop
++) {
414 pci_bus_read_config_dword(pci_bus
,
415 PCI_DEVFN(new_slot
->device
, function
),
417 (u32
*) &(new_slot
->config_space
[cloop
]));
424 /* this loop skips to the next present function
425 * reading in the Class Code and the Header type.
428 while ((function
< max_functions
) && (!stop_it
)) {
429 pci_bus_read_config_dword(pci_bus
,
430 PCI_DEVFN(new_slot
->device
, function
),
433 if (ID
== 0xFFFFFFFF) { /* nothing there. */
435 } else { /* Something there */
436 pci_bus_read_config_byte(pci_bus
,
437 PCI_DEVFN(new_slot
->device
, function
),
440 pci_bus_read_config_byte(pci_bus
,
441 PCI_DEVFN(new_slot
->device
, function
),
442 PCI_HEADER_TYPE
, &header_type
);
448 } while (function
< max_functions
);
449 } /* End of IF (device in slot?) */
459 * pciehp_save_used_resources
461 * Stores used resource information for existing boards. this is
462 * for boards that were in the system when this driver was loaded.
463 * this function is for hot plug ADD
465 * returns 0 if success
466 * if disable == 1(DISABLE_CARD),
467 * it loops for all functions of the slot and disables them.
468 * else, it just get resources of the function and return.
470 int pciehp_save_used_resources(struct controller
*ctrl
, struct pci_func
*func
, int disable
)
478 u16 w_base
, w_length
;
485 struct pci_resource
*mem_node
= NULL
;
486 struct pci_resource
*p_mem_node
= NULL
;
487 struct pci_resource
*t_mem_node
;
488 struct pci_resource
*io_node
;
489 struct pci_resource
*bus_node
;
490 struct pci_bus lpci_bus
, *pci_bus
;
491 memcpy(&lpci_bus
, ctrl
->pci_dev
->subordinate
, sizeof(lpci_bus
));
495 func
= pciehp_slot_find(func
->bus
, func
->device
, index
++);
497 while ((func
!= NULL
) && func
->is_a_board
) {
498 pci_bus
->number
= func
->bus
;
499 devfn
= PCI_DEVFN(func
->device
, func
->function
);
501 /* Save the command register */
502 pci_bus_read_config_word(pci_bus
, devfn
, PCI_COMMAND
, &save_command
);
507 pci_bus_write_config_word(pci_bus
, devfn
, PCI_COMMAND
, command
);
510 /* Check for Bridge */
511 pci_bus_read_config_byte(pci_bus
, devfn
, PCI_HEADER_TYPE
, &header_type
);
513 if ((header_type
& 0x7F) == PCI_HEADER_TYPE_BRIDGE
) { /* PCI-PCI Bridge */
514 dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
515 func
->bus
, func
->device
, save_command
);
517 /* Clear Bridge Control Register */
519 pci_bus_write_config_word(pci_bus
, devfn
, PCI_BRIDGE_CONTROL
, command
);
522 pci_bus_read_config_byte(pci_bus
, devfn
, PCI_SECONDARY_BUS
, &secondary_bus
);
523 pci_bus_read_config_byte(pci_bus
, devfn
, PCI_SUBORDINATE_BUS
, &temp_byte
);
525 bus_node
= kmalloc(sizeof(struct pci_resource
),
530 bus_node
->base
= (ulong
)secondary_bus
;
531 bus_node
->length
= (ulong
)(temp_byte
- secondary_bus
+ 1);
533 bus_node
->next
= func
->bus_head
;
534 func
->bus_head
= bus_node
;
536 /* Save IO base and Limit registers */
537 pci_bus_read_config_byte(pci_bus
, devfn
, PCI_IO_BASE
, &temp_byte
);
539 pci_bus_read_config_byte(pci_bus
, devfn
, PCI_IO_LIMIT
, &temp_byte
);
542 if ((base
<= length
) && (!disable
|| (save_command
& PCI_COMMAND_IO
))) {
543 io_node
= kmalloc(sizeof(struct pci_resource
),
548 io_node
->base
= (ulong
)(base
& PCI_IO_RANGE_MASK
) << 8;
549 io_node
->length
= (ulong
)(length
- base
+ 0x10) << 8;
551 io_node
->next
= func
->io_head
;
552 func
->io_head
= io_node
;
555 /* Save memory base and Limit registers */
556 pci_bus_read_config_word(pci_bus
, devfn
, PCI_MEMORY_BASE
, &w_base
);
557 pci_bus_read_config_word(pci_bus
, devfn
, PCI_MEMORY_LIMIT
, &w_length
);
559 if ((w_base
<= w_length
) && (!disable
|| (save_command
& PCI_COMMAND_MEMORY
))) {
560 mem_node
= kmalloc(sizeof(struct pci_resource
),
565 mem_node
->base
= (ulong
)w_base
<< 16;
566 mem_node
->length
= (ulong
)(w_length
- w_base
+ 0x10) << 16;
568 mem_node
->next
= func
->mem_head
;
569 func
->mem_head
= mem_node
;
571 /* Save prefetchable memory base and Limit registers */
572 pci_bus_read_config_word(pci_bus
, devfn
, PCI_PREF_MEMORY_BASE
, &w_base
);
573 pci_bus_read_config_word(pci_bus
, devfn
, PCI_PREF_MEMORY_LIMIT
, &w_length
);
575 if ((w_base
<= w_length
) && (!disable
|| (save_command
& PCI_COMMAND_MEMORY
))) {
576 p_mem_node
= kmalloc(sizeof(struct pci_resource
),
581 p_mem_node
->base
= (ulong
)w_base
<< 16;
582 p_mem_node
->length
= (ulong
)(w_length
- w_base
+ 0x10) << 16;
584 p_mem_node
->next
= func
->p_mem_head
;
585 func
->p_mem_head
= p_mem_node
;
587 } else if ((header_type
& 0x7F) == PCI_HEADER_TYPE_NORMAL
) {
588 dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
589 func
->bus
, func
->device
, save_command
);
591 /* Figure out IO and memory base lengths */
592 for (cloop
= PCI_BASE_ADDRESS_0
; cloop
<= PCI_BASE_ADDRESS_5
; cloop
+= 4) {
593 pci_bus_read_config_dword(pci_bus
, devfn
, cloop
, &save_base
);
595 temp_register
= 0xFFFFFFFF;
596 pci_bus_write_config_dword(pci_bus
, devfn
, cloop
, temp_register
);
597 pci_bus_read_config_dword(pci_bus
, devfn
, cloop
, &temp_register
);
600 pci_bus_write_config_dword(pci_bus
, devfn
, cloop
, save_base
);
605 base
= temp_register
;
607 if ((base
& PCI_BASE_ADDRESS_SPACE_IO
) &&
608 (!disable
|| (save_command
& PCI_COMMAND_IO
))) {
610 /* set temp_register = amount of IO space requested */
611 base
= base
& 0xFFFFFFFCL
;
614 io_node
= kmalloc(sizeof (struct pci_resource
),
619 io_node
->base
= (ulong
)save_base
& PCI_BASE_ADDRESS_IO_MASK
;
620 io_node
->length
= (ulong
)base
;
621 dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
622 io_node
->base
, io_node
->length
);
624 io_node
->next
= func
->io_head
;
625 func
->io_head
= io_node
;
626 } else { /* map Memory */
627 int prefetchable
= 1;
628 /* struct pci_resources **res_node; */
629 char *res_type_str
= "PMEM";
632 t_mem_node
= kmalloc(sizeof (struct pci_resource
),
637 if (!(base
& PCI_BASE_ADDRESS_MEM_PREFETCH
) &&
638 (!disable
|| (save_command
& PCI_COMMAND_MEMORY
))) {
640 mem_node
= t_mem_node
;
643 p_mem_node
= t_mem_node
;
645 base
= base
& 0xFFFFFFF0L
;
648 switch (temp_register
& PCI_BASE_ADDRESS_MEM_TYPE_MASK
) {
649 case PCI_BASE_ADDRESS_MEM_TYPE_32
:
651 p_mem_node
->base
= (ulong
)save_base
& PCI_BASE_ADDRESS_MEM_MASK
;
652 p_mem_node
->length
= (ulong
)base
;
653 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
658 p_mem_node
->next
= func
->p_mem_head
;
659 func
->p_mem_head
= p_mem_node
;
661 mem_node
->base
= (ulong
)save_base
& PCI_BASE_ADDRESS_MEM_MASK
;
662 mem_node
->length
= (ulong
)base
;
663 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
668 mem_node
->next
= func
->mem_head
;
669 func
->mem_head
= mem_node
;
672 case PCI_BASE_ADDRESS_MEM_TYPE_64
:
673 pci_bus_read_config_dword(pci_bus
, devfn
, cloop
+4, &temp_register2
);
674 base64
= temp_register2
;
675 base64
= (base64
<< 32) | save_base
;
677 if (temp_register2
) {
678 dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
679 res_type_str
, temp_register2
, (u32
)base64
);
680 base64
&= 0x00000000FFFFFFFFL
;
684 p_mem_node
->base
= base64
& PCI_BASE_ADDRESS_MEM_MASK
;
685 p_mem_node
->length
= base
;
686 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
691 p_mem_node
->next
= func
->p_mem_head
;
692 func
->p_mem_head
= p_mem_node
;
694 mem_node
->base
= base64
& PCI_BASE_ADDRESS_MEM_MASK
;
695 mem_node
->length
= base
;
696 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
701 mem_node
->next
= func
->mem_head
;
702 func
->mem_head
= mem_node
;
707 dbg("asur: reserved BAR type=0x%x\n",
712 } /* End of base register loop */
713 } else { /* Some other unknown header type */
714 dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
715 func
->bus
, func
->device
);
718 /* find the next device in this slot */
721 func
= pciehp_slot_find(func
->bus
, func
->device
, index
++);
729 * kfree_resource_list: release memory of all list members
730 * @res: resource list to free
733 return_resource_list(struct pci_resource
**func
, struct pci_resource
**res
)
735 struct pci_resource
*node
;
736 struct pci_resource
*t_node
;
742 return_resource(res
, node
);
748 * pciehp_return_board_resources
750 * this routine returns all resources allocated to a board to
751 * the available pool.
753 * returns 0 if success
755 int pciehp_return_board_resources(struct pci_func
* func
,
756 struct resource_lists
* resources
)
760 dbg("%s\n", __FUNCTION__
);
765 return_resource_list(&(func
->io_head
),&(resources
->io_head
));
766 return_resource_list(&(func
->mem_head
),&(resources
->mem_head
));
767 return_resource_list(&(func
->p_mem_head
),&(resources
->p_mem_head
));
768 return_resource_list(&(func
->bus_head
),&(resources
->bus_head
));
770 rc
= pciehp_resource_sort_and_combine(&(resources
->mem_head
));
771 rc
|= pciehp_resource_sort_and_combine(&(resources
->p_mem_head
));
772 rc
|= pciehp_resource_sort_and_combine(&(resources
->io_head
));
773 rc
|= pciehp_resource_sort_and_combine(&(resources
->bus_head
));
779 * kfree_resource_list: release memory of all list members
780 * @res: resource list to free
783 kfree_resource_list(struct pci_resource
**r
)
785 struct pci_resource
*res
, *tres
;
798 * pciehp_destroy_resource_list: put node back in the resource list
799 * @resources: list to put nodes back
801 void pciehp_destroy_resource_list(struct resource_lists
* resources
)
803 kfree_resource_list(&(resources
->io_head
));
804 kfree_resource_list(&(resources
->mem_head
));
805 kfree_resource_list(&(resources
->p_mem_head
));
806 kfree_resource_list(&(resources
->bus_head
));
810 * pciehp_destroy_board_resources: put node back in the resource list
811 * @resources: list to put nodes back
813 void pciehp_destroy_board_resources(struct pci_func
* func
)
815 kfree_resource_list(&(func
->io_head
));
816 kfree_resource_list(&(func
->mem_head
));
817 kfree_resource_list(&(func
->p_mem_head
));
818 kfree_resource_list(&(func
->bus_head
));