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