MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / pci / hotplug / pciehp_pci.c
blob8aa17540f26dff2e51ad587e2af8e5bc41ef9f91
1 /*
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
9 * All rights reserved.
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
20 * details.
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>
38 #include "../pci.h"
39 #include "pciehp.h"
40 #ifndef CONFIG_IA64
41 #include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
42 #endif
45 int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)
47 unsigned char bus;
48 struct pci_bus *child;
49 int num;
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));
60 if (num)
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");
66 return 0;
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);
77 return 0;
81 int pciehp_unconfigure_device(struct pci_func* func)
83 int rc = 0;
84 int j;
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);
92 if (temp) {
93 pci_remove_bus_device(temp);
96 return rc;
100 * pciehp_set_irq
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)
109 int rc;
110 u16 temp_word;
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);
121 if (!rc)
122 return !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);
133 #endif
134 return 0;
137 /* More PCI configuration routines; this time centered around hotplug controller */
141 * pciehp_save_config
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)
151 int rc;
152 u8 class_code;
153 u8 header_type;
154 u32 ID;
155 u8 secondary_bus;
156 struct pci_func *new_slot;
157 int sub_bus;
158 int max_functions;
159 int function;
160 u8 DevError;
161 int device = 0;
162 int cloop = 0;
163 int stop_it;
164 int index;
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));
172 pci_bus = &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 */
178 if (is_hot_plug) {
179 /*********************************
180 * is_hot_plug is the slot mask
181 *********************************/
182 FirstSupported = first_device_num;
183 LastSupported = FirstSupported + num_ctlr_slots - 1;
184 } else {
185 FirstSupported = 0;
186 LastSupported = 0x1F;
189 dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
190 LastSupported);
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++) {
197 ID = 0xFFFFFFFF;
198 rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
199 PCI_VENDOR_ID, &ID);
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),
204 0x0B, &class_code);
205 if (rc)
206 return rc;
208 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
209 PCI_HEADER_TYPE, &header_type);
210 if (rc)
211 return rc;
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)
217 max_functions = 8;
218 else
219 max_functions = 1;
221 function = 0;
223 do {
224 DevError = 0;
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);
234 if (rc) {
235 return rc;
236 } else {
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);
241 if (rc)
242 return rc;
246 index = 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);
257 if (!new_slot) {
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)
264 return(1);
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),
281 cloop << 2,
282 (u32 *) &(new_slot->config_space [cloop]));
283 /* dbg("new_slot->config_space[%x] = %x\n",
284 cloop, new_slot->config_space[cloop]); */
285 if (rc)
286 return rc;
289 function++;
291 stop_it = 0;
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),
301 PCI_VENDOR_ID, &ID);
303 if (ID == 0xFFFFFFFF) { /* nothing there. */
304 function++;
305 dbg("Nothing there\n");
306 } else { /* Something there */
307 rc = pci_bus_read_config_byte(pci_bus,
308 PCI_DEVFN(device, function),
309 0x0B, &class_code);
310 if (rc)
311 return rc;
313 rc = pci_bus_read_config_byte(pci_bus,
314 PCI_DEVFN(device, function),
315 PCI_HEADER_TYPE, &header_type);
316 if (rc)
317 return rc;
319 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
320 stop_it++;
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) {
331 return(1);
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__);
346 return(0);
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)
360 int rc;
361 u8 class_code;
362 u8 header_type;
363 u32 ID;
364 u8 secondary_bus;
365 int sub_bus;
366 int max_functions;
367 int function;
368 int cloop = 0;
369 int stop_it;
370 struct pci_bus lpci_bus, *pci_bus;
371 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
372 pci_bus = &lpci_bus;
373 pci_bus->number = new_slot->bus;
375 ID = 0xFFFFFFFF;
377 pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
378 PCI_VENDOR_ID, &ID);
380 if (ID != 0xFFFFFFFF) { /* device in slot */
381 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
382 0x0B, &class_code);
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 */
388 max_functions = 8;
389 else
390 max_functions = 1;
392 function = 0;
394 do {
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);
406 if (rc)
407 return rc;
409 } /* End of IF */
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),
416 cloop << 2,
417 (u32 *) &(new_slot->config_space [cloop]));
420 function++;
422 stop_it = 0;
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),
431 PCI_VENDOR_ID, &ID);
433 if (ID == 0xFFFFFFFF) { /* nothing there. */
434 function++;
435 } else { /* Something there */
436 pci_bus_read_config_byte(pci_bus,
437 PCI_DEVFN(new_slot->device, function),
438 0x0B, &class_code);
440 pci_bus_read_config_byte(pci_bus,
441 PCI_DEVFN(new_slot->device, function),
442 PCI_HEADER_TYPE, &header_type);
444 stop_it++;
448 } while (function < max_functions);
449 } /* End of IF (device in slot?) */
450 else {
451 return 2;
454 return 0;
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)
472 u8 cloop;
473 u8 header_type;
474 u8 secondary_bus;
475 u8 temp_byte;
476 u16 command;
477 u16 save_command;
478 u16 w_base, w_length;
479 u32 temp_register;
480 u32 save_base;
481 u32 base, length;
482 u64 base64 = 0;
483 int index = 0;
484 unsigned int devfn;
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));
492 pci_bus = &lpci_bus;
494 if (disable)
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);
504 if (disable) {
505 /* disable card */
506 command = 0x00;
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);
516 if (disable) {
517 /* Clear Bridge Control Register */
518 command = 0x00;
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),
526 GFP_KERNEL);
527 if (!bus_node)
528 return -ENOMEM;
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);
538 base = temp_byte;
539 pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
540 length = temp_byte;
542 if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
543 io_node = kmalloc(sizeof(struct pci_resource),
544 GFP_KERNEL);
545 if (!io_node)
546 return -ENOMEM;
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),
561 GFP_KERNEL);
562 if (!mem_node)
563 return -ENOMEM;
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),
577 GFP_KERNEL);
578 if (!p_mem_node)
579 return -ENOMEM;
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);
599 if (!disable)
600 pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
602 if (!temp_register)
603 continue;
605 base = temp_register;
607 if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
608 (!disable || (save_command & PCI_COMMAND_IO))) {
609 /* IO base */
610 /* set temp_register = amount of IO space requested */
611 base = base & 0xFFFFFFFCL;
612 base = (~base) + 1;
614 io_node = kmalloc(sizeof (struct pci_resource),
615 GFP_KERNEL);
616 if (!io_node)
617 return -ENOMEM;
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";
630 u32 temp_register2;
632 t_mem_node = kmalloc(sizeof (struct pci_resource),
633 GFP_KERNEL);
634 if (!t_mem_node)
635 return -ENOMEM;
637 if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
638 (!disable || (save_command & PCI_COMMAND_MEMORY))) {
639 prefetchable = 0;
640 mem_node = t_mem_node;
641 res_type_str++;
642 } else
643 p_mem_node = t_mem_node;
645 base = base & 0xFFFFFFF0L;
646 base = (~base) + 1;
648 switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
649 case PCI_BASE_ADDRESS_MEM_TYPE_32:
650 if (prefetchable) {
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",
654 res_type_str,
655 p_mem_node->base,
656 p_mem_node->length);
658 p_mem_node->next = func->p_mem_head;
659 func->p_mem_head = p_mem_node;
660 } else {
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",
664 res_type_str,
665 mem_node->base,
666 mem_node->length);
668 mem_node->next = func->mem_head;
669 func->mem_head = mem_node;
671 break;
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;
683 if (prefetchable) {
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",
687 res_type_str,
688 p_mem_node->base,
689 p_mem_node->length);
691 p_mem_node->next = func->p_mem_head;
692 func->p_mem_head = p_mem_node;
693 } else {
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",
697 res_type_str,
698 mem_node->base,
699 mem_node->length);
701 mem_node->next = func->mem_head;
702 func->mem_head = mem_node;
704 cloop += 4;
705 break;
706 default:
707 dbg("asur: reserved BAR type=0x%x\n",
708 temp_register);
709 break;
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 */
719 if (!disable)
720 break;
721 func = pciehp_slot_find(func->bus, func->device, index++);
724 return 0;
729 * kfree_resource_list: release memory of all list members
730 * @res: resource list to free
732 static inline void
733 return_resource_list(struct pci_resource **func, struct pci_resource **res)
735 struct pci_resource *node;
736 struct pci_resource *t_node;
738 node = *func;
739 *func = NULL;
740 while (node) {
741 t_node = node->next;
742 return_resource(res, node);
743 node = t_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)
758 int rc;
760 dbg("%s\n", __FUNCTION__);
762 if (!func)
763 return 1;
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));
775 return rc;
779 * kfree_resource_list: release memory of all list members
780 * @res: resource list to free
782 static inline void
783 kfree_resource_list(struct pci_resource **r)
785 struct pci_resource *res, *tres;
787 res = *r;
788 *r = NULL;
790 while (res) {
791 tres = res;
792 res = res->next;
793 kfree(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));