aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_pci.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/pci/hotplug/pciehp_pci.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/pci/hotplug/pciehp_pci.c')
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c827
1 files changed, 827 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
new file mode 100644
index 000000000000..723b12c0bb7c
--- /dev/null
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -0,0 +1,827 @@
1/*
2 * PCI Express Hot Plug Controller Driver
3 *
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
8 *
9 * All rights reserved.
10 *
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.
15 *
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.
21 *
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.
25 *
26 * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
27 *
28 */
29
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
43
44
45int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)
46{
47 unsigned char bus;
48 struct pci_bus *child;
49 int num;
50
51 if (func->pci_dev == NULL)
52 func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
53
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__);
57
58 num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
59
60 if (num)
61 pci_bus_add_devices(ctrl->pci_dev->subordinate);
62
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;
67 }
68 }
69
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);
74
75 }
76
77 return 0;
78}
79
80
81int pciehp_unconfigure_device(struct pci_func* func)
82{
83 int rc = 0;
84 int j;
85 struct pci_bus *pbus;
86
87 dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
88 func->device, func->function);
89 pbus = func->pci_dev->bus;
90
91 for (j=0; j<8 ; j++) {
92 struct pci_dev* temp = pci_find_slot(func->bus,
93 (func->device << 3) | j);
94 if (temp) {
95 pci_remove_bus_device(temp);
96 }
97 }
98 /*
99 * Some PCI Express root ports require fixup after hot-plug operation.
100 */
101 if (pcie_mch_quirk)
102 pci_fixup_device(pci_fixup_final, pbus->self);
103
104 return rc;
105}
106
107/*
108 * pciehp_set_irq
109 *
110 * @bus_num: bus number of PCI device
111 * @dev_num: device number of PCI device
112 * @slot: pointer to u8 where slot number will be returned
113 */
114int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
115{
116#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
117 int rc;
118 u16 temp_word;
119 struct pci_dev fakedev;
120 struct pci_bus fakebus;
121
122 fakedev.devfn = dev_num << 3;
123 fakedev.bus = &fakebus;
124 fakebus.number = bus_num;
125 dbg("%s: dev %d, bus %d, pin %d, num %d\n",
126 __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
127 rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
128 dbg("%s: rc %d\n", __FUNCTION__, rc);
129 if (!rc)
130 return !rc;
131
132 /* set the Edge Level Control Register (ELCR) */
133 temp_word = inb(0x4d0);
134 temp_word |= inb(0x4d1) << 8;
135
136 temp_word |= 0x01 << irq_num;
137
138 /* This should only be for x86 as it sets the Edge Level Control Register */
139 outb((u8) (temp_word & 0xFF), 0x4d0);
140 outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
141#endif
142 return 0;
143}
144
145/* More PCI configuration routines; this time centered around hotplug controller */
146
147
148/*
149 * pciehp_save_config
150 *
151 * Reads configuration for all slots in a PCI bus and saves info.
152 *
153 * Note: For non-hot plug busses, the slot # saved is the device #
154 *
155 * returns 0 if success
156 */
157int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
158{
159 int rc;
160 u8 class_code;
161 u8 header_type;
162 u32 ID;
163 u8 secondary_bus;
164 struct pci_func *new_slot;
165 int sub_bus;
166 int max_functions;
167 int function;
168 u8 DevError;
169 int device = 0;
170 int cloop = 0;
171 int stop_it;
172 int index;
173 int is_hot_plug = num_ctlr_slots || first_device_num;
174 struct pci_bus lpci_bus, *pci_bus;
175 int FirstSupported, LastSupported;
176
177 dbg("%s: Enter\n", __FUNCTION__);
178
179 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
180 pci_bus = &lpci_bus;
181
182 dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
183 num_ctlr_slots, first_device_num);
184
185 /* Decide which slots are supported */
186 if (is_hot_plug) {
187 /*********************************
188 * is_hot_plug is the slot mask
189 *********************************/
190 FirstSupported = first_device_num;
191 LastSupported = FirstSupported + num_ctlr_slots - 1;
192 } else {
193 FirstSupported = 0;
194 LastSupported = 0x1F;
195 }
196
197 dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
198 LastSupported);
199
200 /* Save PCI configuration space for all devices in supported slots */
201 dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
202 pci_bus->number = busnumber;
203 dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
204 for (device = FirstSupported; device <= LastSupported; device++) {
205 ID = 0xFFFFFFFF;
206 rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
207 PCI_VENDOR_ID, &ID);
208
209 if (ID != 0xFFFFFFFF) { /* device in slot */
210 dbg("%s: ID = %x\n", __FUNCTION__, ID);
211 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
212 0x0B, &class_code);
213 if (rc)
214 return rc;
215
216 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
217 PCI_HEADER_TYPE, &header_type);
218 if (rc)
219 return rc;
220
221 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
222
223 /* If multi-function device, set max_functions to 8 */
224 if (header_type & 0x80)
225 max_functions = 8;
226 else
227 max_functions = 1;
228
229 function = 0;
230
231 do {
232 DevError = 0;
233 dbg("%s: In do loop\n", __FUNCTION__);
234
235 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
236 /* Recurse the subordinate bus
237 * get the subordinate bus number
238 */
239 rc = pci_bus_read_config_byte(pci_bus,
240 PCI_DEVFN(device, function),
241 PCI_SECONDARY_BUS, &secondary_bus);
242 if (rc) {
243 return rc;
244 } else {
245 sub_bus = (int) secondary_bus;
246
247 /* Save secondary bus cfg spc with this recursive call. */
248 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
249 if (rc)
250 return rc;
251 }
252 }
253
254 index = 0;
255 new_slot = pciehp_slot_find(busnumber, device, index++);
256
257 dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
258 __FUNCTION__, new_slot, busnumber, device, index-1);
259
260 while (new_slot && (new_slot->function != (u8) function)) {
261 new_slot = pciehp_slot_find(busnumber, device, index++);
262 dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
263 __FUNCTION__, new_slot, busnumber, device, index-1);
264 }
265 if (!new_slot) {
266 /* Setup slot structure. */
267 new_slot = pciehp_slot_create(busnumber);
268 dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
269 __FUNCTION__, new_slot, busnumber, device, function);
270
271 if (new_slot == NULL)
272 return(1);
273 }
274
275 new_slot->bus = (u8) busnumber;
276 new_slot->device = (u8) device;
277 new_slot->function = (u8) function;
278 new_slot->is_a_board = 1;
279 new_slot->switch_save = 0x10;
280 /* In case of unsupported board */
281 new_slot->status = DevError;
282 new_slot->pci_dev = pci_find_slot(new_slot->bus,
283 (new_slot->device << 3) | new_slot->function);
284 dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
285
286 for (cloop = 0; cloop < 0x20; cloop++) {
287 rc = pci_bus_read_config_dword(pci_bus,
288 PCI_DEVFN(device, function),
289 cloop << 2,
290 (u32 *) &(new_slot->config_space [cloop]));
291 /* dbg("new_slot->config_space[%x] = %x\n",
292 cloop, new_slot->config_space[cloop]); */
293 if (rc)
294 return rc;
295 }
296
297 function++;
298
299 stop_it = 0;
300
301 /* this loop skips to the next present function
302 * reading in Class Code and Header type.
303 */
304
305 while ((function < max_functions)&&(!stop_it)) {
306 dbg("%s: In while loop \n", __FUNCTION__);
307 rc = pci_bus_read_config_dword(pci_bus,
308 PCI_DEVFN(device, function),
309 PCI_VENDOR_ID, &ID);
310
311 if (ID == 0xFFFFFFFF) { /* nothing there. */
312 function++;
313 dbg("Nothing there\n");
314 } else { /* Something there */
315 rc = pci_bus_read_config_byte(pci_bus,
316 PCI_DEVFN(device, function),
317 0x0B, &class_code);
318 if (rc)
319 return rc;
320
321 rc = pci_bus_read_config_byte(pci_bus,
322 PCI_DEVFN(device, function),
323 PCI_HEADER_TYPE, &header_type);
324 if (rc)
325 return rc;
326
327 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
328 stop_it++;
329 }
330 }
331
332 } while (function < max_functions);
333 /* End of IF (device in slot?) */
334 } else if (is_hot_plug) {
335 /* Setup slot structure with entry for empty slot */
336 new_slot = pciehp_slot_create(busnumber);
337
338 if (new_slot == NULL) {
339 return(1);
340 }
341 dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
342 new_slot->bus, new_slot->device, new_slot->function);
343
344 new_slot->bus = (u8) busnumber;
345 new_slot->device = (u8) device;
346 new_slot->function = 0;
347 new_slot->is_a_board = 0;
348 new_slot->presence_save = 0;
349 new_slot->switch_save = 0;
350 }
351 } /* End of FOR loop */
352
353 dbg("%s: Exit\n", __FUNCTION__);
354 return(0);
355}
356
357
358/*
359 * pciehp_save_slot_config
360 *
361 * Saves configuration info for all PCI devices in a given slot
362 * including subordinate busses.
363 *
364 * returns 0 if success
365 */
366int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
367{
368 int rc;
369 u8 class_code;
370 u8 header_type;
371 u32 ID;
372 u8 secondary_bus;
373 int sub_bus;
374 int max_functions;
375 int function;
376 int cloop = 0;
377 int stop_it;
378 struct pci_bus lpci_bus, *pci_bus;
379 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
380 pci_bus = &lpci_bus;
381 pci_bus->number = new_slot->bus;
382
383 ID = 0xFFFFFFFF;
384
385 pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
386 PCI_VENDOR_ID, &ID);
387
388 if (ID != 0xFFFFFFFF) { /* device in slot */
389 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
390 0x0B, &class_code);
391
392 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
393 PCI_HEADER_TYPE, &header_type);
394
395 if (header_type & 0x80) /* Multi-function device */
396 max_functions = 8;
397 else
398 max_functions = 1;
399
400 function = 0;
401
402 do {
403 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
404 /* Recurse the subordinate bus */
405 pci_bus_read_config_byte(pci_bus,
406 PCI_DEVFN(new_slot->device, function),
407 PCI_SECONDARY_BUS, &secondary_bus);
408
409 sub_bus = (int) secondary_bus;
410
411 /* Save the config headers for the secondary bus. */
412 rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
413
414 if (rc)
415 return rc;
416
417 } /* End of IF */
418
419 new_slot->status = 0;
420
421 for (cloop = 0; cloop < 0x20; cloop++) {
422 pci_bus_read_config_dword(pci_bus,
423 PCI_DEVFN(new_slot->device, function),
424 cloop << 2,
425 (u32 *) &(new_slot->config_space [cloop]));
426 }
427
428 function++;
429
430 stop_it = 0;
431
432 /* this loop skips to the next present function
433 * reading in the Class Code and the Header type.
434 */
435
436 while ((function < max_functions) && (!stop_it)) {
437 pci_bus_read_config_dword(pci_bus,
438 PCI_DEVFN(new_slot->device, function),
439 PCI_VENDOR_ID, &ID);
440
441 if (ID == 0xFFFFFFFF) { /* nothing there. */
442 function++;
443 } else { /* Something there */
444 pci_bus_read_config_byte(pci_bus,
445 PCI_DEVFN(new_slot->device, function),
446 0x0B, &class_code);
447
448 pci_bus_read_config_byte(pci_bus,
449 PCI_DEVFN(new_slot->device, function),
450 PCI_HEADER_TYPE, &header_type);
451
452 stop_it++;
453 }
454 }
455
456 } while (function < max_functions);
457 } /* End of IF (device in slot?) */
458 else {
459 return 2;
460 }
461
462 return 0;
463}
464
465
466/*
467 * pciehp_save_used_resources
468 *
469 * Stores used resource information for existing boards. this is
470 * for boards that were in the system when this driver was loaded.
471 * this function is for hot plug ADD
472 *
473 * returns 0 if success
474 * if disable == 1(DISABLE_CARD),
475 * it loops for all functions of the slot and disables them.
476 * else, it just get resources of the function and return.
477 */
478int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
479{
480 u8 cloop;
481 u8 header_type;
482 u8 secondary_bus;
483 u8 temp_byte;
484 u16 command;
485 u16 save_command;
486 u16 w_base, w_length;
487 u32 temp_register;
488 u32 save_base;
489 u32 base, length;
490 u64 base64 = 0;
491 int index = 0;
492 unsigned int devfn;
493 struct pci_resource *mem_node = NULL;
494 struct pci_resource *p_mem_node = NULL;
495 struct pci_resource *t_mem_node;
496 struct pci_resource *io_node;
497 struct pci_resource *bus_node;
498 struct pci_bus lpci_bus, *pci_bus;
499 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
500 pci_bus = &lpci_bus;
501
502 if (disable)
503 func = pciehp_slot_find(func->bus, func->device, index++);
504
505 while ((func != NULL) && func->is_a_board) {
506 pci_bus->number = func->bus;
507 devfn = PCI_DEVFN(func->device, func->function);
508
509 /* Save the command register */
510 pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
511
512 if (disable) {
513 /* disable card */
514 command = 0x00;
515 pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
516 }
517
518 /* Check for Bridge */
519 pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
520
521 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
522 dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
523 func->bus, func->device, save_command);
524 if (disable) {
525 /* Clear Bridge Control Register */
526 command = 0x00;
527 pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
528 }
529
530 pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
531 pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
532
533 bus_node = kmalloc(sizeof(struct pci_resource),
534 GFP_KERNEL);
535 if (!bus_node)
536 return -ENOMEM;
537
538 bus_node->base = (ulong)secondary_bus;
539 bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
540
541 bus_node->next = func->bus_head;
542 func->bus_head = bus_node;
543
544 /* Save IO base and Limit registers */
545 pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
546 base = temp_byte;
547 pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
548 length = temp_byte;
549
550 if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
551 io_node = kmalloc(sizeof(struct pci_resource),
552 GFP_KERNEL);
553 if (!io_node)
554 return -ENOMEM;
555
556 io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
557 io_node->length = (ulong)(length - base + 0x10) << 8;
558
559 io_node->next = func->io_head;
560 func->io_head = io_node;
561 }
562
563 /* Save memory base and Limit registers */
564 pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
565 pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
566
567 if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
568 mem_node = kmalloc(sizeof(struct pci_resource),
569 GFP_KERNEL);
570 if (!mem_node)
571 return -ENOMEM;
572
573 mem_node->base = (ulong)w_base << 16;
574 mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
575
576 mem_node->next = func->mem_head;
577 func->mem_head = mem_node;
578 }
579 /* Save prefetchable memory base and Limit registers */
580 pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
581 pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
582
583 if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
584 p_mem_node = kmalloc(sizeof(struct pci_resource),
585 GFP_KERNEL);
586 if (!p_mem_node)
587 return -ENOMEM;
588
589 p_mem_node->base = (ulong)w_base << 16;
590 p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
591
592 p_mem_node->next = func->p_mem_head;
593 func->p_mem_head = p_mem_node;
594 }
595 } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
596 dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
597 func->bus, func->device, save_command);
598
599 /* Figure out IO and memory base lengths */
600 for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
601 pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
602
603 temp_register = 0xFFFFFFFF;
604 pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
605 pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
606
607 if (!disable)
608 pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
609
610 if (!temp_register)
611 continue;
612
613 base = temp_register;
614
615 if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
616 (!disable || (save_command & PCI_COMMAND_IO))) {
617 /* IO base */
618 /* set temp_register = amount of IO space requested */
619 base = base & 0xFFFFFFFCL;
620 base = (~base) + 1;
621
622 io_node = kmalloc(sizeof (struct pci_resource),
623 GFP_KERNEL);
624 if (!io_node)
625 return -ENOMEM;
626
627 io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
628 io_node->length = (ulong)base;
629 dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
630 io_node->base, io_node->length);
631
632 io_node->next = func->io_head;
633 func->io_head = io_node;
634 } else { /* map Memory */
635 int prefetchable = 1;
636 /* struct pci_resources **res_node; */
637 char *res_type_str = "PMEM";
638 u32 temp_register2;
639
640 t_mem_node = kmalloc(sizeof (struct pci_resource),
641 GFP_KERNEL);
642 if (!t_mem_node)
643 return -ENOMEM;
644
645 if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
646 (!disable || (save_command & PCI_COMMAND_MEMORY))) {
647 prefetchable = 0;
648 mem_node = t_mem_node;
649 res_type_str++;
650 } else
651 p_mem_node = t_mem_node;
652
653 base = base & 0xFFFFFFF0L;
654 base = (~base) + 1;
655
656 switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
657 case PCI_BASE_ADDRESS_MEM_TYPE_32:
658 if (prefetchable) {
659 p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
660 p_mem_node->length = (ulong)base;
661 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
662 res_type_str,
663 p_mem_node->base,
664 p_mem_node->length);
665
666 p_mem_node->next = func->p_mem_head;
667 func->p_mem_head = p_mem_node;
668 } else {
669 mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
670 mem_node->length = (ulong)base;
671 dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
672 res_type_str,
673 mem_node->base,
674 mem_node->length);
675
676 mem_node->next = func->mem_head;
677 func->mem_head = mem_node;
678 }
679 break;
680 case PCI_BASE_ADDRESS_MEM_TYPE_64:
681 pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
682 base64 = temp_register2;
683 base64 = (base64 << 32) | save_base;
684
685 if (temp_register2) {
686 dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
687 res_type_str, temp_register2, (u32)base64);
688 base64 &= 0x00000000FFFFFFFFL;
689 }
690
691 if (prefetchable) {
692 p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
693 p_mem_node->length = base;
694 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
695 res_type_str,
696 p_mem_node->base,
697 p_mem_node->length);
698
699 p_mem_node->next = func->p_mem_head;
700 func->p_mem_head = p_mem_node;
701 } else {
702 mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
703 mem_node->length = base;
704 dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
705 res_type_str,
706 mem_node->base,
707 mem_node->length);
708
709 mem_node->next = func->mem_head;
710 func->mem_head = mem_node;
711 }
712 cloop += 4;
713 break;
714 default:
715 dbg("asur: reserved BAR type=0x%x\n",
716 temp_register);
717 break;
718 }
719 }
720 } /* End of base register loop */
721 } else { /* Some other unknown header type */
722 dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
723 func->bus, func->device);
724 }
725
726 /* find the next device in this slot */
727 if (!disable)
728 break;
729 func = pciehp_slot_find(func->bus, func->device, index++);
730 }
731
732 return 0;
733}
734
735
736/**
737 * kfree_resource_list: release memory of all list members
738 * @res: resource list to free
739 */
740static inline void
741return_resource_list(struct pci_resource **func, struct pci_resource **res)
742{
743 struct pci_resource *node;
744 struct pci_resource *t_node;
745
746 node = *func;
747 *func = NULL;
748 while (node) {
749 t_node = node->next;
750 return_resource(res, node);
751 node = t_node;
752 }
753}
754
755/*
756 * pciehp_return_board_resources
757 *
758 * this routine returns all resources allocated to a board to
759 * the available pool.
760 *
761 * returns 0 if success
762 */
763int pciehp_return_board_resources(struct pci_func * func,
764 struct resource_lists * resources)
765{
766 int rc;
767
768 dbg("%s\n", __FUNCTION__);
769
770 if (!func)
771 return 1;
772
773 return_resource_list(&(func->io_head),&(resources->io_head));
774 return_resource_list(&(func->mem_head),&(resources->mem_head));
775 return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
776 return_resource_list(&(func->bus_head),&(resources->bus_head));
777
778 rc = pciehp_resource_sort_and_combine(&(resources->mem_head));
779 rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head));
780 rc |= pciehp_resource_sort_and_combine(&(resources->io_head));
781 rc |= pciehp_resource_sort_and_combine(&(resources->bus_head));
782
783 return rc;
784}
785
786/**
787 * kfree_resource_list: release memory of all list members
788 * @res: resource list to free
789 */
790static inline void
791kfree_resource_list(struct pci_resource **r)
792{
793 struct pci_resource *res, *tres;
794
795 res = *r;
796 *r = NULL;
797
798 while (res) {
799 tres = res;
800 res = res->next;
801 kfree(tres);
802 }
803}
804
805/**
806 * pciehp_destroy_resource_list: put node back in the resource list
807 * @resources: list to put nodes back
808 */
809void pciehp_destroy_resource_list(struct resource_lists * resources)
810{
811 kfree_resource_list(&(resources->io_head));
812 kfree_resource_list(&(resources->mem_head));
813 kfree_resource_list(&(resources->p_mem_head));
814 kfree_resource_list(&(resources->bus_head));
815}
816
817/**
818 * pciehp_destroy_board_resources: put node back in the resource list
819 * @resources: list to put nodes back
820 */
821void pciehp_destroy_board_resources(struct pci_func * func)
822{
823 kfree_resource_list(&(func->io_head));
824 kfree_resource_list(&(func->mem_head));
825 kfree_resource_list(&(func->p_mem_head));
826 kfree_resource_list(&(func->bus_head));
827}