1 /* 2 * IBM Hot Plug Controller Driver 3 * 4 * Written By: Irene Zubarev, IBM Corporation 5 * 6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 7 * Copyright (C) 2001,2002 IBM Corp. 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 <gregkh@us.ibm.com> 27 * 28 */ 29 30 #include <linux/module.h> 31 #include <linux/slab.h> 32 #include <linux/pci.h> 33 #include <linux/list.h> 34 #include <linux/init.h> 35 #include "ibmphp.h" 36 37 static int flags = 0; /* for testing */ 38 39 static void update_resources (struct bus_node *bus_cur, int type, int rangeno); 40 static int once_over (void); 41 static int remove_ranges (struct bus_node *, struct bus_node *); 42 static int update_bridge_ranges (struct bus_node **); 43 static int add_range (int type, struct range_node *, struct bus_node *); 44 static void fix_resources (struct bus_node *); 45 static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); 46 47 static LIST_HEAD(gbuses); 48 49 static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag) 50 { 51 struct bus_node * newbus; 52 53 if (!(curr) && !(flag)) { 54 err ("NULL pointer passed\n"); 55 return NULL; 56 } 57 58 newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); 59 if (!newbus) { 60 err ("out of system memory\n"); 61 return NULL; 62 } 63 64 memset (newbus, 0, sizeof (struct bus_node)); 65 if (flag) 66 newbus->busno = busno; 67 else 68 newbus->busno = curr->bus_num; 69 list_add_tail (&newbus->bus_list, &gbuses); 70 return newbus; 71 } 72 73 static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr) 74 { 75 struct resource_node *rs; 76 77 if (!curr) { 78 err ("NULL passed to allocate\n"); 79 return NULL; 80 } 81 82 rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); 83 if (!rs) { 84 err ("out of system memory\n"); 85 return NULL; 86 } 87 memset (rs, 0, sizeof (struct resource_node)); 88 rs->busno = curr->bus_num; 89 rs->devfunc = curr->dev_fun; 90 rs->start = curr->start_addr; 91 rs->end = curr->end_addr; 92 rs->len = curr->end_addr - curr->start_addr + 1; 93 return rs; 94 } 95 96 static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus) 97 { 98 struct bus_node * newbus; 99 struct range_node *newrange; 100 u8 num_ranges = 0; 101 102 if (first_bus) { 103 newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); 104 if (!newbus) { 105 err ("out of system memory.\n"); 106 return -ENOMEM; 107 } 108 memset (newbus, 0, sizeof (struct bus_node)); 109 newbus->busno = curr->bus_num; 110 } else { 111 newbus = *new_bus; 112 switch (flag) { 113 case MEM: 114 num_ranges = newbus->noMemRanges; 115 break; 116 case PFMEM: 117 num_ranges = newbus->noPFMemRanges; 118 break; 119 case IO: 120 num_ranges = newbus->noIORanges; 121 break; 122 } 123 } 124 125 newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL); 126 if (!newrange) { 127 if (first_bus) 128 kfree (newbus); 129 err ("out of system memory\n"); 130 return -ENOMEM; 131 } 132 memset (newrange, 0, sizeof (struct range_node)); 133 newrange->start = curr->start_addr; 134 newrange->end = curr->end_addr; 135 136 if (first_bus || (!num_ranges)) 137 newrange->rangeno = 1; 138 else { 139 /* need to insert our range */ 140 add_range (flag, newrange, newbus); 141 debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end); 142 } 143 144 switch (flag) { 145 case MEM: 146 newbus->rangeMem = newrange; 147 if (first_bus) 148 newbus->noMemRanges = 1; 149 else { 150 debug ("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 151 ++newbus->noMemRanges; 152 fix_resources (newbus); 153 } 154 break; 155 case IO: 156 newbus->rangeIO = newrange; 157 if (first_bus) 158 newbus->noIORanges = 1; 159 else { 160 debug ("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 161 ++newbus->noIORanges; 162 fix_resources (newbus); 163 } 164 break; 165 case PFMEM: 166 newbus->rangePFMem = newrange; 167 if (first_bus) 168 newbus->noPFMemRanges = 1; 169 else { 170 debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 171 ++newbus->noPFMemRanges; 172 fix_resources (newbus); 173 } 174 175 break; 176 } 177 178 *new_bus = newbus; 179 *new_range = newrange; 180 return 0; 181 } 182 183 184 /* Notes: 185 * 1. The ranges are ordered. The buses are not ordered. (First come) 186 * 187 * 2. If cannot allocate out of PFMem range, allocate from Mem ranges. PFmemFromMem 188 * are not sorted. (no need since use mem node). To not change the entire code, we 189 * also add mem node whenever this case happens so as not to change 190 * ibmphp_check_mem_resource etc (and since it really is taking Mem resource) 191 */ 192 193 /***************************************************************************** 194 * This is the Resource Management initialization function. It will go through 195 * the Resource list taken from EBDA and fill in this module's data structures 196 * 197 * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES, 198 * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW 199 * 200 * Input: ptr to the head of the resource list from EBDA 201 * Output: 0, -1 or error codes 202 ***************************************************************************/ 203 int __init ibmphp_rsrc_init (void) 204 { 205 struct ebda_pci_rsrc *curr; 206 struct range_node *newrange = NULL; 207 struct bus_node *newbus = NULL; 208 struct bus_node *bus_cur; 209 struct bus_node *bus_prev; 210 struct list_head *tmp; 211 struct resource_node *new_io = NULL; 212 struct resource_node *new_mem = NULL; 213 struct resource_node *new_pfmem = NULL; 214 int rc; 215 struct list_head *tmp_ebda; 216 217 list_for_each (tmp_ebda, &ibmphp_ebda_pci_rsrc_head) { 218 curr = list_entry (tmp_ebda, struct ebda_pci_rsrc, ebda_pci_rsrc_list); 219 if (!(curr->rsrc_type & PCIDEVMASK)) { 220 /* EBDA still lists non PCI devices, so ignore... */ 221 debug ("this is not a PCI DEVICE in rsrc_init, please take care\n"); 222 // continue; 223 } 224 225 /* this is a primary bus resource */ 226 if (curr->rsrc_type & PRIMARYBUSMASK) { 227 /* memory */ 228 if ((curr->rsrc_type & RESTYPE) == MMASK) { 229 /* no bus structure exists in place yet */ 230 if (list_empty (&gbuses)) { 231 if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1))) 232 return rc; 233 list_add_tail (&newbus->bus_list, &gbuses); 234 debug ("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 235 } else { 236 bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1); 237 /* found our bus */ 238 if (bus_cur) { 239 rc = alloc_bus_range (&bus_cur, &newrange, curr, MEM, 0); 240 if (rc) 241 return rc; 242 } else { 243 /* went through all the buses and didn't find ours, need to create a new bus node */ 244 if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1))) 245 return rc; 246 247 list_add_tail (&newbus->bus_list, &gbuses); 248 debug ("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 249 } 250 } 251 } else if ((curr->rsrc_type & RESTYPE) == PFMASK) { 252 /* prefetchable memory */ 253 if (list_empty (&gbuses)) { 254 /* no bus structure exists in place yet */ 255 if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1))) 256 return rc; 257 list_add_tail (&newbus->bus_list, &gbuses); 258 debug ("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 259 } else { 260 bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1); 261 if (bus_cur) { 262 /* found our bus */ 263 rc = alloc_bus_range (&bus_cur, &newrange, curr, PFMEM, 0); 264 if (rc) 265 return rc; 266 } else { 267 /* went through all the buses and didn't find ours, need to create a new bus node */ 268 if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1))) 269 return rc; 270 list_add_tail (&newbus->bus_list, &gbuses); 271 debug ("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 272 } 273 } 274 } else if ((curr->rsrc_type & RESTYPE) == IOMASK) { 275 /* IO */ 276 if (list_empty (&gbuses)) { 277 /* no bus structure exists in place yet */ 278 if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1))) 279 return rc; 280 list_add_tail (&newbus->bus_list, &gbuses); 281 debug ("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 282 } else { 283 bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1); 284 if (bus_cur) { 285 rc = alloc_bus_range (&bus_cur, &newrange, curr, IO, 0); 286 if (rc) 287 return rc; 288 } else { 289 /* went through all the buses and didn't find ours, need to create a new bus node */ 290 if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1))) 291 return rc; 292 list_add_tail (&newbus->bus_list, &gbuses); 293 debug ("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end); 294 } 295 } 296 297 } else { 298 ; /* type is reserved WHAT TO DO IN THIS CASE??? 299 NOTHING TO DO??? */ 300 } 301 } else { 302 /* regular pci device resource */ 303 if ((curr->rsrc_type & RESTYPE) == MMASK) { 304 /* Memory resource */ 305 new_mem = alloc_resources (curr); 306 if (!new_mem) 307 return -ENOMEM; 308 new_mem->type = MEM; 309 /* 310 * if it didn't find the bus, means PCI dev 311 * came b4 the Primary Bus info, so need to 312 * create a bus rangeno becomes a problem... 313 * assign a -1 and then update once the range 314 * actually appears... 315 */ 316 if (ibmphp_add_resource (new_mem) < 0) { 317 newbus = alloc_error_bus (curr, 0, 0); 318 if (!newbus) 319 return -ENOMEM; 320 newbus->firstMem = new_mem; 321 ++newbus->needMemUpdate; 322 new_mem->rangeno = -1; 323 } 324 debug ("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end); 325 326 } else if ((curr->rsrc_type & RESTYPE) == PFMASK) { 327 /* PFMemory resource */ 328 new_pfmem = alloc_resources (curr); 329 if (!new_pfmem) 330 return -ENOMEM; 331 new_pfmem->type = PFMEM; 332 new_pfmem->fromMem = FALSE; 333 if (ibmphp_add_resource (new_pfmem) < 0) { 334 newbus = alloc_error_bus (curr, 0, 0); 335 if (!newbus) 336 return -ENOMEM; 337 newbus->firstPFMem = new_pfmem; 338 ++newbus->needPFMemUpdate; 339 new_pfmem->rangeno = -1; 340 } 341 342 debug ("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end); 343 } else if ((curr->rsrc_type & RESTYPE) == IOMASK) { 344 /* IO resource */ 345 new_io = alloc_resources (curr); 346 if (!new_io) 347 return -ENOMEM; 348 new_io->type = IO; 349 350 /* 351 * if it didn't find the bus, means PCI dev 352 * came b4 the Primary Bus info, so need to 353 * create a bus rangeno becomes a problem... 354 * Can assign a -1 and then update once the 355 * range actually appears... 356 */ 357 if (ibmphp_add_resource (new_io) < 0) { 358 newbus = alloc_error_bus (curr, 0, 0); 359 if (!newbus) 360 return -ENOMEM; 361 newbus->firstIO = new_io; 362 ++newbus->needIOUpdate; 363 new_io->rangeno = -1; 364 } 365 debug ("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end); 366 } 367 } 368 } 369 370 list_for_each (tmp, &gbuses) { 371 bus_cur = list_entry (tmp, struct bus_node, bus_list); 372 /* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */ 373 rc = update_bridge_ranges (&bus_cur); 374 if (rc) 375 return rc; 376 } 377 rc = once_over (); /* This is to align ranges (so no -1) */ 378 if (rc) 379 return rc; 380 return 0; 381 } 382 383 /******************************************************************************** 384 * This function adds a range into a sorted list of ranges per bus for a particular 385 * range type, it then calls another routine to update the range numbers on the 386 * pci devices' resources for the appropriate resource 387 * 388 * Input: type of the resource, range to add, current bus 389 * Output: 0 or -1, bus and range ptrs 390 ********************************************************************************/ 391 static int add_range (int type, struct range_node *range, struct bus_node *bus_cur) 392 { 393 struct range_node *range_cur = NULL; 394 struct range_node *range_prev; 395 int count = 0, i_init; 396 int noRanges = 0; 397 398 switch (type) { 399 case MEM: 400 range_cur = bus_cur->rangeMem; 401 noRanges = bus_cur->noMemRanges; 402 break; 403 case PFMEM: 404 range_cur = bus_cur->rangePFMem; 405 noRanges = bus_cur->noPFMemRanges; 406 break; 407 case IO: 408 range_cur = bus_cur->rangeIO; 409 noRanges = bus_cur->noIORanges; 410 break; 411 } 412 413 range_prev = NULL; 414 while (range_cur) { 415 if (range->start < range_cur->start) 416 break; 417 range_prev = range_cur; 418 range_cur = range_cur->next; 419 count = count + 1; 420 } 421 if (!count) { 422 /* our range will go at the beginning of the list */ 423 switch (type) { 424 case MEM: 425 bus_cur->rangeMem = range; 426 break; 427 case PFMEM: 428 bus_cur->rangePFMem = range; 429 break; 430 case IO: 431 bus_cur->rangeIO = range; 432 break; 433 } 434 range->next = range_cur; 435 range->rangeno = 1; 436 i_init = 0; 437 } else if (!range_cur) { 438 /* our range will go at the end of the list */ 439 range->next = NULL; 440 range_prev->next = range; 441 range->rangeno = range_prev->rangeno + 1; 442 return 0; 443 } else { 444 /* the range is in the middle */ 445 range_prev->next = range; 446 range->next = range_cur; 447 range->rangeno = range_cur->rangeno; 448 i_init = range_prev->rangeno; 449 } 450 451 for (count = i_init; count < noRanges; ++count) { 452 ++range_cur->rangeno; 453 range_cur = range_cur->next; 454 } 455 456 update_resources (bus_cur, type, i_init + 1); 457 return 0; 458 } 459 460 /******************************************************************************* 461 * This routine goes through the list of resources of type 'type' and updates 462 * the range numbers that they correspond to. It was called from add_range fnc 463 * 464 * Input: bus, type of the resource, the rangeno starting from which to update 465 ******************************************************************************/ 466 static void update_resources (struct bus_node *bus_cur, int type, int rangeno) 467 { 468 struct resource_node *res = NULL; 469 u8 eol = FALSE; /* end of list indicator */ 470 471 switch (type) { 472 case MEM: 473 if (bus_cur->firstMem) 474 res = bus_cur->firstMem; 475 break; 476 case PFMEM: 477 if (bus_cur->firstPFMem) 478 res = bus_cur->firstPFMem; 479 break; 480 case IO: 481 if (bus_cur->firstIO) 482 res = bus_cur->firstIO; 483 break; 484 } 485 486 if (res) { 487 while (res) { 488 if (res->rangeno == rangeno) 489 break; 490 if (res->next) 491 res = res->next; 492 else if (res->nextRange) 493 res = res->nextRange; 494 else { 495 eol = TRUE; 496 break; 497 } 498 } 499 500 if (!eol) { 501 /* found the range */ 502 while (res) { 503 ++res->rangeno; 504 res = res->next; 505 } 506 } 507 } 508 } 509 510 static void fix_me (struct resource_node *res, struct bus_node *bus_cur, struct range_node *range) 511 { 512 char * str = ""; 513 switch (res->type) { 514 case IO: 515 str = "io"; 516 break; 517 case MEM: 518 str = "mem"; 519 break; 520 case PFMEM: 521 str = "pfmem"; 522 break; 523 } 524 525 while (res) { 526 if (res->rangeno == -1) { 527 while (range) { 528 if ((res->start >= range->start) && (res->end <= range->end)) { 529 res->rangeno = range->rangeno; 530 debug ("%s->rangeno in fix_resources is %d\n", str, res->rangeno); 531 switch (res->type) { 532 case IO: 533 --bus_cur->needIOUpdate; 534 break; 535 case MEM: 536 --bus_cur->needMemUpdate; 537 break; 538 case PFMEM: 539 --bus_cur->needPFMemUpdate; 540 break; 541 } 542 break; 543 } 544 range = range->next; 545 } 546 } 547 if (res->next) 548 res = res->next; 549 else 550 res = res->nextRange; 551 } 552 553 } 554 555 /***************************************************************************** 556 * This routine reassigns the range numbers to the resources that had a -1 557 * This case can happen only if upon initialization, resources taken by pci dev 558 * appear in EBDA before the resources allocated for that bus, since we don't 559 * know the range, we assign -1, and this routine is called after a new range 560 * is assigned to see the resources with unknown range belong to the added range 561 * 562 * Input: current bus 563 * Output: none, list of resources for that bus are fixed if can be 564 *******************************************************************************/ 565 static void fix_resources (struct bus_node *bus_cur) 566 { 567 struct range_node *range; 568 struct resource_node *res; 569 570 debug ("%s - bus_cur->busno = %d\n", __FUNCTION__, bus_cur->busno); 571 572 if (bus_cur->needIOUpdate) { 573 res = bus_cur->firstIO; 574 range = bus_cur->rangeIO; 575 fix_me (res, bus_cur, range); 576 } 577 if (bus_cur->needMemUpdate) { 578 res = bus_cur->firstMem; 579 range = bus_cur->rangeMem; 580 fix_me (res, bus_cur, range); 581 } 582 if (bus_cur->needPFMemUpdate) { 583 res = bus_cur->firstPFMem; 584 range = bus_cur->rangePFMem; 585 fix_me (res, bus_cur, range); 586 } 587 } 588 589 /******************************************************************************* 590 * This routine adds a resource to the list of resources to the appropriate bus 591 * based on their resource type and sorted by their starting addresses. It assigns 592 * the ptrs to next and nextRange if needed. 593 * 594 * Input: resource ptr 595 * Output: ptrs assigned (to the node) 596 * 0 or -1 597 *******************************************************************************/ 598 int ibmphp_add_resource (struct resource_node *res) 599 { 600 struct resource_node *res_cur; 601 struct resource_node *res_prev; 602 struct bus_node *bus_cur; 603 struct range_node *range_cur = NULL; 604 struct resource_node *res_start = NULL; 605 606 debug ("%s - enter\n", __FUNCTION__); 607 608 if (!res) { 609 err ("NULL passed to add\n"); 610 return -ENODEV; 611 } 612 613 bus_cur = find_bus_wprev (res->busno, NULL, 0); 614 615 if (!bus_cur) { 616 /* didn't find a bus, smth's wrong!!! */ 617 debug ("no bus in the system, either pci_dev's wrong or allocation failed\n"); 618 return -ENODEV; 619 } 620 621 /* Normal case */ 622 switch (res->type) { 623 case IO: 624 range_cur = bus_cur->rangeIO; 625 res_start = bus_cur->firstIO; 626 break; 627 case MEM: 628 range_cur = bus_cur->rangeMem; 629 res_start = bus_cur->firstMem; 630 break; 631 case PFMEM: 632 range_cur = bus_cur->rangePFMem; 633 res_start = bus_cur->firstPFMem; 634 break; 635 default: 636 err ("cannot read the type of the resource to add... problem\n"); 637 return -EINVAL; 638 } 639 while (range_cur) { 640 if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) { 641 res->rangeno = range_cur->rangeno; 642 break; 643 } 644 range_cur = range_cur->next; 645 } 646 647 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 648 * this is again the case of rangeno = -1 649 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 650 */ 651 652 if (!range_cur) { 653 switch (res->type) { 654 case IO: 655 ++bus_cur->needIOUpdate; 656 break; 657 case MEM: 658 ++bus_cur->needMemUpdate; 659 break; 660 case PFMEM: 661 ++bus_cur->needPFMemUpdate; 662 break; 663 } 664 res->rangeno = -1; 665 } 666 667 debug ("The range is %d\n", res->rangeno); 668 if (!res_start) { 669 /* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */ 670 switch (res->type) { 671 case IO: 672 bus_cur->firstIO = res; 673 break; 674 case MEM: 675 bus_cur->firstMem = res; 676 break; 677 case PFMEM: 678 bus_cur->firstPFMem = res; 679 break; 680 } 681 res->next = NULL; 682 res->nextRange = NULL; 683 } else { 684 res_cur = res_start; 685 res_prev = NULL; 686 687 debug ("res_cur->rangeno is %d\n", res_cur->rangeno); 688 689 while (res_cur) { 690 if (res_cur->rangeno >= res->rangeno) 691 break; 692 res_prev = res_cur; 693 if (res_cur->next) 694 res_cur = res_cur->next; 695 else 696 res_cur = res_cur->nextRange; 697 } 698 699 if (!res_cur) { 700 /* at the end of the resource list */ 701 debug ("i should be here, [%x - %x]\n", res->start, res->end); 702 res_prev->nextRange = res; 703 res->next = NULL; 704 res->nextRange = NULL; 705 } else if (res_cur->rangeno == res->rangeno) { 706 /* in the same range */ 707 while (res_cur) { 708 if (res->start < res_cur->start) 709 break; 710 res_prev = res_cur; 711 res_cur = res_cur->next; 712 } 713 if (!res_cur) { 714 /* the last resource in this range */ 715 res_prev->next = res; 716 res->next = NULL; 717 res->nextRange = res_prev->nextRange; 718 res_prev->nextRange = NULL; 719 } else if (res->start < res_cur->start) { 720 /* at the beginning or middle of the range */ 721 if (!res_prev) { 722 switch (res->type) { 723 case IO: 724 bus_cur->firstIO = res; 725 break; 726 case MEM: 727 bus_cur->firstMem = res; 728 break; 729 case PFMEM: 730 bus_cur->firstPFMem = res; 731 break; 732 } 733 } else if (res_prev->rangeno == res_cur->rangeno) 734 res_prev->next = res; 735 else 736 res_prev->nextRange = res; 737 738 res->next = res_cur; 739 res->nextRange = NULL; 740 } 741 } else { 742 /* this is the case where it is 1st occurrence of the range */ 743 if (!res_prev) { 744 /* at the beginning of the resource list */ 745 res->next = NULL; 746 switch (res->type) { 747 case IO: 748 res->nextRange = bus_cur->firstIO; 749 bus_cur->firstIO = res; 750 break; 751 case MEM: 752 res->nextRange = bus_cur->firstMem; 753 bus_cur->firstMem = res; 754 break; 755 case PFMEM: 756 res->nextRange = bus_cur->firstPFMem; 757 bus_cur->firstPFMem = res; 758 break; 759 } 760 } else if (res_cur->rangeno > res->rangeno) { 761 /* in the middle of the resource list */ 762 res_prev->nextRange = res; 763 res->next = NULL; 764 res->nextRange = res_cur; 765 } 766 } 767 } 768 769 debug ("%s - exit\n", __FUNCTION__); 770 return 0; 771 } 772 773 /**************************************************************************** 774 * This routine will remove the resource from the list of resources 775 * 776 * Input: io, mem, and/or pfmem resource to be deleted 777 * Ouput: modified resource list 778 * 0 or error code 779 ****************************************************************************/ 780 int ibmphp_remove_resource (struct resource_node *res) 781 { 782 struct bus_node *bus_cur; 783 struct resource_node *res_cur = NULL; 784 struct resource_node *res_prev; 785 struct resource_node *mem_cur; 786 char * type = ""; 787 788 if (!res) { 789 err ("resource to remove is NULL\n"); 790 return -ENODEV; 791 } 792 793 bus_cur = find_bus_wprev (res->busno, NULL, 0); 794 795 if (!bus_cur) { 796 err ("cannot find corresponding bus of the io resource to remove " 797 "bailing out...\n"); 798 return -ENODEV; 799 } 800 801 switch (res->type) { 802 case IO: 803 res_cur = bus_cur->firstIO; 804 type = "io"; 805 break; 806 case MEM: 807 res_cur = bus_cur->firstMem; 808 type = "mem"; 809 break; 810 case PFMEM: 811 res_cur = bus_cur->firstPFMem; 812 type = "pfmem"; 813 break; 814 default: 815 err ("unknown type for resource to remove\n"); 816 return -EINVAL; 817 } 818 res_prev = NULL; 819 820 while (res_cur) { 821 if ((res_cur->start == res->start) && (res_cur->end == res->end)) 822 break; 823 res_prev = res_cur; 824 if (res_cur->next) 825 res_cur = res_cur->next; 826 else 827 res_cur = res_cur->nextRange; 828 } 829 830 if (!res_cur) { 831 if (res->type == PFMEM) { 832 /* 833 * case where pfmem might be in the PFMemFromMem list 834 * so will also need to remove the corresponding mem 835 * entry 836 */ 837 res_cur = bus_cur->firstPFMemFromMem; 838 res_prev = NULL; 839 840 while (res_cur) { 841 if ((res_cur->start == res->start) && (res_cur->end == res->end)) { 842 mem_cur = bus_cur->firstMem; 843 while (mem_cur) { 844 if ((mem_cur->start == res_cur->start) 845 && (mem_cur->end == res_cur->end)) 846 break; 847 if (mem_cur->next) 848 mem_cur = mem_cur->next; 849 else 850 mem_cur = mem_cur->nextRange; 851 } 852 if (!mem_cur) { 853 err ("cannot find corresponding mem node for pfmem...\n"); 854 return -EINVAL; 855 } 856 857 ibmphp_remove_resource (mem_cur); 858 if (!res_prev) 859 bus_cur->firstPFMemFromMem = res_cur->next; 860 else 861 res_prev->next = res_cur->next; 862 kfree (res_cur); 863 return 0; 864 } 865 res_prev = res_cur; 866 if (res_cur->next) 867 res_cur = res_cur->next; 868 else 869 res_cur = res_cur->nextRange; 870 } 871 if (!res_cur) { 872 err ("cannot find pfmem to delete...\n"); 873 return -EINVAL; 874 } 875 } else { 876 err ("the %s resource is not in the list to be deleted...\n", type); 877 return -EINVAL; 878 } 879 } 880 if (!res_prev) { 881 /* first device to be deleted */ 882 if (res_cur->next) { 883 switch (res->type) { 884 case IO: 885 bus_cur->firstIO = res_cur->next; 886 break; 887 case MEM: 888 bus_cur->firstMem = res_cur->next; 889 break; 890 case PFMEM: 891 bus_cur->firstPFMem = res_cur->next; 892 break; 893 } 894 } else if (res_cur->nextRange) { 895 switch (res->type) { 896 case IO: 897 bus_cur->firstIO = res_cur->nextRange; 898 break; 899 case MEM: 900 bus_cur->firstMem = res_cur->nextRange; 901 break; 902 case PFMEM: 903 bus_cur->firstPFMem = res_cur->nextRange; 904 break; 905 } 906 } else { 907 switch (res->type) { 908 case IO: 909 bus_cur->firstIO = NULL; 910 break; 911 case MEM: 912 bus_cur->firstMem = NULL; 913 break; 914 case PFMEM: 915 bus_cur->firstPFMem = NULL; 916 break; 917 } 918 } 919 kfree (res_cur); 920 return 0; 921 } else { 922 if (res_cur->next) { 923 if (res_prev->rangeno == res_cur->rangeno) 924 res_prev->next = res_cur->next; 925 else 926 res_prev->nextRange = res_cur->next; 927 } else if (res_cur->nextRange) { 928 res_prev->next = NULL; 929 res_prev->nextRange = res_cur->nextRange; 930 } else { 931 res_prev->next = NULL; 932 res_prev->nextRange = NULL; 933 } 934 kfree (res_cur); 935 return 0; 936 } 937 938 return 0; 939 } 940 941 static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res) 942 { 943 struct range_node * range = NULL; 944 945 switch (res->type) { 946 case IO: 947 range = bus_cur->rangeIO; 948 break; 949 case MEM: 950 range = bus_cur->rangeMem; 951 break; 952 case PFMEM: 953 range = bus_cur->rangePFMem; 954 break; 955 default: 956 err ("cannot read resource type in find_range\n"); 957 } 958 959 while (range) { 960 if (res->rangeno == range->rangeno) 961 break; 962 range = range->next; 963 } 964 return range; 965 } 966 967 /***************************************************************************** 968 * This routine will check to make sure the io/mem/pfmem->len that the device asked for 969 * can fit w/i our list of available IO/MEM/PFMEM resources. If cannot, returns -EINVAL, 970 * otherwise, returns 0 971 * 972 * Input: resource 973 * Ouput: the correct start and end address are inputted into the resource node, 974 * 0 or -EINVAL 975 *****************************************************************************/ 976 int ibmphp_check_resource (struct resource_node *res, u8 bridge) 977 { 978 struct bus_node *bus_cur; 979 struct range_node *range = NULL; 980 struct resource_node *res_prev; 981 struct resource_node *res_cur = NULL; 982 u32 len_cur = 0, start_cur = 0, len_tmp = 0; 983 int noranges = 0; 984 u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ 985 u32 tmp_divide; 986 u8 flag = FALSE; 987 988 if (!res) 989 return -EINVAL; 990 991 if (bridge) { 992 /* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/ 993 if (res->type == IO) 994 tmp_divide = IOBRIDGE; 995 else 996 tmp_divide = MEMBRIDGE; 997 } else 998 tmp_divide = res->len; 999 1000 bus_cur = find_bus_wprev (res->busno, NULL, 0); 1001 1002 if (!bus_cur) { 1003 /* didn't find a bus, smth's wrong!!! */ 1004 debug ("no bus in the system, either pci_dev's wrong or allocation failed\n"); 1005 return -EINVAL; 1006 } 1007 1008 debug ("%s - enter\n", __FUNCTION__); 1009 debug ("bus_cur->busno is %d\n", bus_cur->busno); 1010 1011 /* This is a quick fix to not mess up with the code very much. i.e., 1012 * 2000-2fff, len = 1000, but when we compare, we need it to be fff */ 1013 res->len -= 1; 1014 1015 switch (res->type) { 1016 case IO: 1017 res_cur = bus_cur->firstIO; 1018 noranges = bus_cur->noIORanges; 1019 break; 1020 case MEM: 1021 res_cur = bus_cur->firstMem; 1022 noranges = bus_cur->noMemRanges; 1023 break; 1024 case PFMEM: 1025 res_cur = bus_cur->firstPFMem; 1026 noranges = bus_cur->noPFMemRanges; 1027 break; 1028 default: 1029 err ("wrong type of resource to check\n"); 1030 return -EINVAL; 1031 } 1032 res_prev = NULL; 1033 1034 while (res_cur) { 1035 range = find_range (bus_cur, res_cur); 1036 debug ("%s - rangeno = %d\n", __FUNCTION__, res_cur->rangeno); 1037 1038 if (!range) { 1039 err ("no range for the device exists... bailing out...\n"); 1040 return -EINVAL; 1041 } 1042 1043 /* found our range */ 1044 if (!res_prev) { 1045 /* first time in the loop */ 1046 if ((res_cur->start != range->start) && ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) { 1047 debug ("len_tmp = %x\n", len_tmp); 1048 1049 if ((len_tmp < len_cur) || (len_cur == 0)) { 1050 1051 if ((range->start % tmp_divide) == 0) { 1052 /* just perfect, starting address is divisible by length */ 1053 flag = TRUE; 1054 len_cur = len_tmp; 1055 start_cur = range->start; 1056 } else { 1057 /* Needs adjusting */ 1058 tmp_start = range->start; 1059 flag = FALSE; 1060 1061 while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { 1062 if ((tmp_start % tmp_divide) == 0) { 1063 flag = TRUE; 1064 len_cur = len_tmp; 1065 start_cur = tmp_start; 1066 break; 1067 } 1068 tmp_start += tmp_divide - tmp_start % tmp_divide; 1069 if (tmp_start >= res_cur->start - 1) 1070 break; 1071 } 1072 } 1073 1074 if (flag && len_cur == res->len) { 1075 debug ("but we are not here, right?\n"); 1076 res->start = start_cur; 1077 res->len += 1; /* To restore the balance */ 1078 res->end = res->start + res->len - 1; 1079 return 0; 1080 } 1081 } 1082 } 1083 } 1084 if (!res_cur->next) { 1085 /* last device on the range */ 1086 if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) { 1087 debug ("len_tmp = %x\n", len_tmp); 1088 if ((len_tmp < len_cur) || (len_cur == 0)) { 1089 1090 if (((res_cur->end + 1) % tmp_divide) == 0) { 1091 /* just perfect, starting address is divisible by length */ 1092 flag = TRUE; 1093 len_cur = len_tmp; 1094 start_cur = res_cur->end + 1; 1095 } else { 1096 /* Needs adjusting */ 1097 tmp_start = res_cur->end + 1; 1098 flag = FALSE; 1099 1100 while ((len_tmp = range->end - tmp_start) >= res->len) { 1101 if ((tmp_start % tmp_divide) == 0) { 1102 flag = TRUE; 1103 len_cur = len_tmp; 1104 start_cur = tmp_start; 1105 break; 1106 } 1107 tmp_start += tmp_divide - tmp_start % tmp_divide; 1108 if (tmp_start >= range->end) 1109 break; 1110 } 1111 } 1112 if (flag && len_cur == res->len) { 1113 res->start = start_cur; 1114 res->len += 1; /* To restore the balance */ 1115 res->end = res->start + res->len - 1; 1116 return 0; 1117 } 1118 } 1119 } 1120 } 1121 1122 if (res_prev) { 1123 if (res_prev->rangeno != res_cur->rangeno) { 1124 /* 1st device on this range */ 1125 if ((res_cur->start != range->start) && 1126 ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) { 1127 if ((len_tmp < len_cur) || (len_cur == 0)) { 1128 if ((range->start % tmp_divide) == 0) { 1129 /* just perfect, starting address is divisible by length */ 1130 flag = TRUE; 1131 len_cur = len_tmp; 1132 start_cur = range->start; 1133 } else { 1134 /* Needs adjusting */ 1135 tmp_start = range->start; 1136 flag = FALSE; 1137 1138 while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { 1139 if ((tmp_start % tmp_divide) == 0) { 1140 flag = TRUE; 1141 len_cur = len_tmp; 1142 start_cur = tmp_start; 1143 break; 1144 } 1145 tmp_start += tmp_divide - tmp_start % tmp_divide; 1146 if (tmp_start >= res_cur->start - 1) 1147 break; 1148 } 1149 } 1150 1151 if (flag && len_cur == res->len) { 1152 res->start = start_cur; 1153 res->len += 1; /* To restore the balance */ 1154 res->end = res->start + res->len - 1; 1155 return 0; 1156 } 1157 } 1158 } 1159 } else { 1160 /* in the same range */ 1161 if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) { 1162 if ((len_tmp < len_cur) || (len_cur == 0)) { 1163 if (((res_prev->end + 1) % tmp_divide) == 0) { 1164 /* just perfect, starting address's divisible by length */ 1165 flag = TRUE; 1166 len_cur = len_tmp; 1167 start_cur = res_prev->end + 1; 1168 } else { 1169 /* Needs adjusting */ 1170 tmp_start = res_prev->end + 1; 1171 flag = FALSE; 1172 1173 while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { 1174 if ((tmp_start % tmp_divide) == 0) { 1175 flag = TRUE; 1176 len_cur = len_tmp; 1177 start_cur = tmp_start; 1178 break; 1179 } 1180 tmp_start += tmp_divide - tmp_start % tmp_divide; 1181 if (tmp_start >= res_cur->start - 1) 1182 break; 1183 } 1184 } 1185 1186 if (flag && len_cur == res->len) { 1187 res->start = start_cur; 1188 res->len += 1; /* To restore the balance */ 1189 res->end = res->start + res->len - 1; 1190 return 0; 1191 } 1192 } 1193 } 1194 } 1195 } 1196 /* end if (res_prev) */ 1197 res_prev = res_cur; 1198 if (res_cur->next) 1199 res_cur = res_cur->next; 1200 else 1201 res_cur = res_cur->nextRange; 1202 } /* end of while */ 1203 1204 1205 if (!res_prev) { 1206 /* 1st device ever */ 1207 /* need to find appropriate range */ 1208 switch (res->type) { 1209 case IO: 1210 range = bus_cur->rangeIO; 1211 break; 1212 case MEM: 1213 range = bus_cur->rangeMem; 1214 break; 1215 case PFMEM: 1216 range = bus_cur->rangePFMem; 1217 break; 1218 } 1219 while (range) { 1220 if ((len_tmp = range->end - range->start) >= res->len) { 1221 if ((len_tmp < len_cur) || (len_cur == 0)) { 1222 if ((range->start % tmp_divide) == 0) { 1223 /* just perfect, starting address's divisible by length */ 1224 flag = TRUE; 1225 len_cur = len_tmp; 1226 start_cur = range->start; 1227 } else { 1228 /* Needs adjusting */ 1229 tmp_start = range->start; 1230 flag = FALSE; 1231 1232 while ((len_tmp = range->end - tmp_start) >= res->len) { 1233 if ((tmp_start % tmp_divide) == 0) { 1234 flag = TRUE; 1235 len_cur = len_tmp; 1236 start_cur = tmp_start; 1237 break; 1238 } 1239 tmp_start += tmp_divide - tmp_start % tmp_divide; 1240 if (tmp_start >= range->end) 1241 break; 1242 } 1243 } 1244 1245 if (flag && len_cur == res->len) { 1246 res->start = start_cur; 1247 res->len += 1; /* To restore the balance */ 1248 res->end = res->start + res->len - 1; 1249 return 0; 1250 } 1251 } 1252 } 1253 range = range->next; 1254 } /* end of while */ 1255 1256 if ((!range) && (len_cur == 0)) { 1257 /* have gone through the list of devices and ranges and haven't found n.e.thing */ 1258 err ("no appropriate range.. bailing out...\n"); 1259 return -EINVAL; 1260 } else if (len_cur) { 1261 res->start = start_cur; 1262 res->len += 1; /* To restore the balance */ 1263 res->end = res->start + res->len - 1; 1264 return 0; 1265 } 1266 } 1267 1268 if (!res_cur) { 1269 debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges); 1270 if (res_prev->rangeno < noranges) { 1271 /* if there're more ranges out there to check */ 1272 switch (res->type) { 1273 case IO: 1274 range = bus_cur->rangeIO; 1275 break; 1276 case MEM: 1277 range = bus_cur->rangeMem; 1278 break; 1279 case PFMEM: 1280 range = bus_cur->rangePFMem; 1281 break; 1282 } 1283 while (range) { 1284 if ((len_tmp = range->end - range->start) >= res->len) { 1285 if ((len_tmp < len_cur) || (len_cur == 0)) { 1286 if ((range->start % tmp_divide) == 0) { 1287 /* just perfect, starting address's divisible by length */ 1288 flag = TRUE; 1289 len_cur = len_tmp; 1290 start_cur = range->start; 1291 } else { 1292 /* Needs adjusting */ 1293 tmp_start = range->start; 1294 flag = FALSE; 1295 1296 while ((len_tmp = range->end - tmp_start) >= res->len) { 1297 if ((tmp_start % tmp_divide) == 0) { 1298 flag = TRUE; 1299 len_cur = len_tmp; 1300 start_cur = tmp_start; 1301 break; 1302 } 1303 tmp_start += tmp_divide - tmp_start % tmp_divide; 1304 if (tmp_start >= range->end) 1305 break; 1306 } 1307 } 1308 1309 if (flag && len_cur == res->len) { 1310 res->start = start_cur; 1311 res->len += 1; /* To restore the balance */ 1312 res->end = res->start + res->len - 1; 1313 return 0; 1314 } 1315 } 1316 } 1317 range = range->next; 1318 } /* end of while */ 1319 1320 if ((!range) && (len_cur == 0)) { 1321 /* have gone through the list of devices and ranges and haven't found n.e.thing */ 1322 err ("no appropriate range.. bailing out...\n"); 1323 return -EINVAL; 1324 } else if (len_cur) { 1325 res->start = start_cur; 1326 res->len += 1; /* To restore the balance */ 1327 res->end = res->start + res->len - 1; 1328 return 0; 1329 } 1330 } else { 1331 /* no more ranges to check on */ 1332 if (len_cur) { 1333 res->start = start_cur; 1334 res->len += 1; /* To restore the balance */ 1335 res->end = res->start + res->len - 1; 1336 return 0; 1337 } else { 1338 /* have gone through the list of devices and haven't found n.e.thing */ 1339 err ("no appropriate range.. bailing out...\n"); 1340 return -EINVAL; 1341 } 1342 } 1343 } /* end if(!res_cur) */ 1344 return -EINVAL; 1345 } 1346 1347 /******************************************************************************** 1348 * This routine is called from remove_card if the card contained PPB. 1349 * It will remove all the resources on the bus as well as the bus itself 1350 * Input: Bus 1351 * Ouput: 0, -ENODEV 1352 ********************************************************************************/ 1353 int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno) 1354 { 1355 struct resource_node *res_cur; 1356 struct resource_node *res_tmp; 1357 struct bus_node *prev_bus; 1358 int rc; 1359 1360 prev_bus = find_bus_wprev (parent_busno, NULL, 0); 1361 1362 if (!prev_bus) { 1363 debug ("something terribly wrong. Cannot find parent bus to the one to remove\n"); 1364 return -ENODEV; 1365 } 1366 1367 debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno); 1368 1369 rc = remove_ranges (bus, prev_bus); 1370 if (rc) 1371 return rc; 1372 1373 if (bus->firstIO) { 1374 res_cur = bus->firstIO; 1375 while (res_cur) { 1376 res_tmp = res_cur; 1377 if (res_cur->next) 1378 res_cur = res_cur->next; 1379 else 1380 res_cur = res_cur->nextRange; 1381 kfree (res_tmp); 1382 res_tmp = NULL; 1383 } 1384 bus->firstIO = NULL; 1385 } 1386 if (bus->firstMem) { 1387 res_cur = bus->firstMem; 1388 while (res_cur) { 1389 res_tmp = res_cur; 1390 if (res_cur->next) 1391 res_cur = res_cur->next; 1392 else 1393 res_cur = res_cur->nextRange; 1394 kfree (res_tmp); 1395 res_tmp = NULL; 1396 } 1397 bus->firstMem = NULL; 1398 } 1399 if (bus->firstPFMem) { 1400 res_cur = bus->firstPFMem; 1401 while (res_cur) { 1402 res_tmp = res_cur; 1403 if (res_cur->next) 1404 res_cur = res_cur->next; 1405 else 1406 res_cur = res_cur->nextRange; 1407 kfree (res_tmp); 1408 res_tmp = NULL; 1409 } 1410 bus->firstPFMem = NULL; 1411 } 1412 1413 if (bus->firstPFMemFromMem) { 1414 res_cur = bus->firstPFMemFromMem; 1415 while (res_cur) { 1416 res_tmp = res_cur; 1417 res_cur = res_cur->next; 1418 1419 kfree (res_tmp); 1420 res_tmp = NULL; 1421 } 1422 bus->firstPFMemFromMem = NULL; 1423 } 1424 1425 list_del (&bus->bus_list); 1426 kfree (bus); 1427 return 0; 1428 } 1429 1430 /****************************************************************************** 1431 * This routine deletes the ranges from a given bus, and the entries from the 1432 * parent's bus in the resources 1433 * Input: current bus, previous bus 1434 * Output: 0, -EINVAL 1435 ******************************************************************************/ 1436 static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev) 1437 { 1438 struct range_node *range_cur; 1439 struct range_node *range_tmp; 1440 int i; 1441 struct resource_node *res = NULL; 1442 1443 if (bus_cur->noIORanges) { 1444 range_cur = bus_cur->rangeIO; 1445 for (i = 0; i < bus_cur->noIORanges; i++) { 1446 if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0) 1447 return -EINVAL; 1448 ibmphp_remove_resource (res); 1449 1450 range_tmp = range_cur; 1451 range_cur = range_cur->next; 1452 kfree (range_tmp); 1453 range_tmp = NULL; 1454 } 1455 bus_cur->rangeIO = NULL; 1456 } 1457 if (bus_cur->noMemRanges) { 1458 range_cur = bus_cur->rangeMem; 1459 for (i = 0; i < bus_cur->noMemRanges; i++) { 1460 if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0) 1461 return -EINVAL; 1462 1463 ibmphp_remove_resource (res); 1464 range_tmp = range_cur; 1465 range_cur = range_cur->next; 1466 kfree (range_tmp); 1467 range_tmp = NULL; 1468 } 1469 bus_cur->rangeMem = NULL; 1470 } 1471 if (bus_cur->noPFMemRanges) { 1472 range_cur = bus_cur->rangePFMem; 1473 for (i = 0; i < bus_cur->noPFMemRanges; i++) { 1474 if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0) 1475 return -EINVAL; 1476 1477 ibmphp_remove_resource (res); 1478 range_tmp = range_cur; 1479 range_cur = range_cur->next; 1480 kfree (range_tmp); 1481 range_tmp = NULL; 1482 } 1483 bus_cur->rangePFMem = NULL; 1484 } 1485 return 0; 1486 } 1487 1488 /* 1489 * find the resource node in the bus 1490 * Input: Resource needed, start address of the resource, type of resource 1491 */ 1492 int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag) 1493 { 1494 struct resource_node *res_cur = NULL; 1495 char * type = ""; 1496 1497 if (!bus) { 1498 err ("The bus passed in NULL to find resource\n"); 1499 return -ENODEV; 1500 } 1501 1502 switch (flag) { 1503 case IO: 1504 res_cur = bus->firstIO; 1505 type = "io"; 1506 break; 1507 case MEM: 1508 res_cur = bus->firstMem; 1509 type = "mem"; 1510 break; 1511 case PFMEM: 1512 res_cur = bus->firstPFMem; 1513 type = "pfmem"; 1514 break; 1515 default: 1516 err ("wrong type of flag\n"); 1517 return -EINVAL; 1518 } 1519 1520 while (res_cur) { 1521 if (res_cur->start == start_address) { 1522 *res = res_cur; 1523 break; 1524 } 1525 if (res_cur->next) 1526 res_cur = res_cur->next; 1527 else 1528 res_cur = res_cur->nextRange; 1529 } 1530 1531 if (!res_cur) { 1532 if (flag == PFMEM) { 1533 res_cur = bus->firstPFMemFromMem; 1534 while (res_cur) { 1535 if (res_cur->start == start_address) { 1536 *res = res_cur; 1537 break; 1538 } 1539 res_cur = res_cur->next; 1540 } 1541 if (!res_cur) { 1542 debug ("SOS...cannot find %s resource in the bus.\n", type); 1543 return -EINVAL; 1544 } 1545 } else { 1546 debug ("SOS... cannot find %s resource in the bus.\n", type); 1547 return -EINVAL; 1548 } 1549 } 1550 1551 if (*res) 1552 debug ("*res->start = %x\n", (*res)->start); 1553 1554 return 0; 1555 } 1556 1557 /*********************************************************************** 1558 * This routine will free the resource structures used by the 1559 * system. It is called from cleanup routine for the module 1560 * Parameters: none 1561 * Returns: none 1562 ***********************************************************************/ 1563 void ibmphp_free_resources (void) 1564 { 1565 struct bus_node *bus_cur = NULL; 1566 struct bus_node *bus_tmp; 1567 struct range_node *range_cur; 1568 struct range_node *range_tmp; 1569 struct resource_node *res_cur; 1570 struct resource_node *res_tmp; 1571 struct list_head *tmp; 1572 struct list_head *next; 1573 int i = 0; 1574 flags = 1; 1575 1576 list_for_each_safe (tmp, next, &gbuses) { 1577 bus_cur = list_entry (tmp, struct bus_node, bus_list); 1578 if (bus_cur->noIORanges) { 1579 range_cur = bus_cur->rangeIO; 1580 for (i = 0; i < bus_cur->noIORanges; i++) { 1581 if (!range_cur) 1582 break; 1583 range_tmp = range_cur; 1584 range_cur = range_cur->next; 1585 kfree (range_tmp); 1586 range_tmp = NULL; 1587 } 1588 } 1589 if (bus_cur->noMemRanges) { 1590 range_cur = bus_cur->rangeMem; 1591 for (i = 0; i < bus_cur->noMemRanges; i++) { 1592 if (!range_cur) 1593 break; 1594 range_tmp = range_cur; 1595 range_cur = range_cur->next; 1596 kfree (range_tmp); 1597 range_tmp = NULL; 1598 } 1599 } 1600 if (bus_cur->noPFMemRanges) { 1601 range_cur = bus_cur->rangePFMem; 1602 for (i = 0; i < bus_cur->noPFMemRanges; i++) { 1603 if (!range_cur) 1604 break; 1605 range_tmp = range_cur; 1606 range_cur = range_cur->next; 1607 kfree (range_tmp); 1608 range_tmp = NULL; 1609 } 1610 } 1611 1612 if (bus_cur->firstIO) { 1613 res_cur = bus_cur->firstIO; 1614 while (res_cur) { 1615 res_tmp = res_cur; 1616 if (res_cur->next) 1617 res_cur = res_cur->next; 1618 else 1619 res_cur = res_cur->nextRange; 1620 kfree (res_tmp); 1621 res_tmp = NULL; 1622 } 1623 bus_cur->firstIO = NULL; 1624 } 1625 if (bus_cur->firstMem) { 1626 res_cur = bus_cur->firstMem; 1627 while (res_cur) { 1628 res_tmp = res_cur; 1629 if (res_cur->next) 1630 res_cur = res_cur->next; 1631 else 1632 res_cur = res_cur->nextRange; 1633 kfree (res_tmp); 1634 res_tmp = NULL; 1635 } 1636 bus_cur->firstMem = NULL; 1637 } 1638 if (bus_cur->firstPFMem) { 1639 res_cur = bus_cur->firstPFMem; 1640 while (res_cur) { 1641 res_tmp = res_cur; 1642 if (res_cur->next) 1643 res_cur = res_cur->next; 1644 else 1645 res_cur = res_cur->nextRange; 1646 kfree (res_tmp); 1647 res_tmp = NULL; 1648 } 1649 bus_cur->firstPFMem = NULL; 1650 } 1651 1652 if (bus_cur->firstPFMemFromMem) { 1653 res_cur = bus_cur->firstPFMemFromMem; 1654 while (res_cur) { 1655 res_tmp = res_cur; 1656 res_cur = res_cur->next; 1657 1658 kfree (res_tmp); 1659 res_tmp = NULL; 1660 } 1661 bus_cur->firstPFMemFromMem = NULL; 1662 } 1663 1664 bus_tmp = bus_cur; 1665 list_del (&bus_cur->bus_list); 1666 kfree (bus_tmp); 1667 bus_tmp = NULL; 1668 } 1669 } 1670 1671 /********************************************************************************* 1672 * This function will go over the PFmem resources to check if the EBDA allocated 1673 * pfmem out of memory buckets of the bus. If so, it will change the range numbers 1674 * and a flag to indicate that this resource is out of memory. It will also move the 1675 * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create 1676 * a new Mem node 1677 * This routine is called right after initialization 1678 *******************************************************************************/ 1679 static int __init once_over (void) 1680 { 1681 struct resource_node *pfmem_cur; 1682 struct resource_node *pfmem_prev; 1683 struct resource_node *mem; 1684 struct bus_node *bus_cur; 1685 struct list_head *tmp; 1686 1687 list_for_each (tmp, &gbuses) { 1688 bus_cur = list_entry (tmp, struct bus_node, bus_list); 1689 if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { 1690 for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { 1691 pfmem_cur->fromMem = TRUE; 1692 if (pfmem_prev) 1693 pfmem_prev->next = pfmem_cur->next; 1694 else 1695 bus_cur->firstPFMem = pfmem_cur->next; 1696 1697 if (!bus_cur->firstPFMemFromMem) 1698 pfmem_cur->next = NULL; 1699 else 1700 /* we don't need to sort PFMemFromMem since we're using mem node for 1701 all the real work anyways, so just insert at the beginning of the 1702 list 1703 */ 1704 pfmem_cur->next = bus_cur->firstPFMemFromMem; 1705 1706 bus_cur->firstPFMemFromMem = pfmem_cur; 1707 1708 mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); 1709 if (!mem) { 1710 err ("out of system memory\n"); 1711 return -ENOMEM; 1712 } 1713 memset (mem, 0, sizeof (struct resource_node)); 1714 mem->type = MEM; 1715 mem->busno = pfmem_cur->busno; 1716 mem->devfunc = pfmem_cur->devfunc; 1717 mem->start = pfmem_cur->start; 1718 mem->end = pfmem_cur->end; 1719 mem->len = pfmem_cur->len; 1720 if (ibmphp_add_resource (mem) < 0) 1721 err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n"); 1722 pfmem_cur->rangeno = mem->rangeno; 1723 } /* end for pfmem */ 1724 } /* end if */ 1725 } /* end list_for_each bus */ 1726 return 0; 1727 } 1728 1729 int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem) 1730 { 1731 struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0); 1732 1733 if (!bus_cur) { 1734 err ("cannot find bus of pfmem to add...\n"); 1735 return -ENODEV; 1736 } 1737 1738 if (bus_cur->firstPFMemFromMem) 1739 pfmem->next = bus_cur->firstPFMemFromMem; 1740 else 1741 pfmem->next = NULL; 1742 1743 bus_cur->firstPFMemFromMem = pfmem; 1744 1745 return 0; 1746 } 1747 1748 /* This routine just goes through the buses to see if the bus already exists. 1749 * It is called from ibmphp_find_sec_number, to find out a secondary bus number for 1750 * bridged cards 1751 * Parameters: bus_number 1752 * Returns: Bus pointer or NULL 1753 */ 1754 struct bus_node *ibmphp_find_res_bus (u8 bus_number) 1755 { 1756 return find_bus_wprev (bus_number, NULL, 0); 1757 } 1758 1759 static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag) 1760 { 1761 struct bus_node *bus_cur; 1762 struct list_head *tmp; 1763 struct list_head *tmp_prev; 1764 1765 list_for_each (tmp, &gbuses) { 1766 tmp_prev = tmp->prev; 1767 bus_cur = list_entry (tmp, struct bus_node, bus_list); 1768 if (flag) 1769 *prev = list_entry (tmp_prev, struct bus_node, bus_list); 1770 if (bus_cur->busno == bus_number) 1771 return bus_cur; 1772 } 1773 1774 return NULL; 1775 } 1776 1777 void ibmphp_print_test (void) 1778 { 1779 int i = 0; 1780 struct bus_node *bus_cur = NULL; 1781 struct range_node *range; 1782 struct resource_node *res; 1783 struct list_head *tmp; 1784 1785 debug_pci ("*****************START**********************\n"); 1786 1787 if ((!list_empty(&gbuses)) && flags) { 1788 err ("The GBUSES is not NULL?!?!?!?!?\n"); 1789 return; 1790 } 1791 1792 list_for_each (tmp, &gbuses) { 1793 bus_cur = list_entry (tmp, struct bus_node, bus_list); 1794 debug_pci ("This is bus # %d. There are\n", bus_cur->busno); 1795 debug_pci ("IORanges = %d\t", bus_cur->noIORanges); 1796 debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges); 1797 debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges); 1798 debug_pci ("The IO Ranges are as follows:\n"); 1799 if (bus_cur->rangeIO) { 1800 range = bus_cur->rangeIO; 1801 for (i = 0; i < bus_cur->noIORanges; i++) { 1802 debug_pci ("rangeno is %d\n", range->rangeno); 1803 debug_pci ("[%x - %x]\n", range->start, range->end); 1804 range = range->next; 1805 } 1806 } 1807 1808 debug_pci ("The Mem Ranges are as follows:\n"); 1809 if (bus_cur->rangeMem) { 1810 range = bus_cur->rangeMem; 1811 for (i = 0; i < bus_cur->noMemRanges; i++) { 1812 debug_pci ("rangeno is %d\n", range->rangeno); 1813 debug_pci ("[%x - %x]\n", range->start, range->end); 1814 range = range->next; 1815 } 1816 } 1817 1818 debug_pci ("The PFMem Ranges are as follows:\n"); 1819 1820 if (bus_cur->rangePFMem) { 1821 range = bus_cur->rangePFMem; 1822 for (i = 0; i < bus_cur->noPFMemRanges; i++) { 1823 debug_pci ("rangeno is %d\n", range->rangeno); 1824 debug_pci ("[%x - %x]\n", range->start, range->end); 1825 range = range->next; 1826 } 1827 } 1828 1829 debug_pci ("The resources on this bus are as follows\n"); 1830 1831 debug_pci ("IO...\n"); 1832 if (bus_cur->firstIO) { 1833 res = bus_cur->firstIO; 1834 while (res) { 1835 debug_pci ("The range # is %d\n", res->rangeno); 1836 debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); 1837 debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); 1838 if (res->next) 1839 res = res->next; 1840 else if (res->nextRange) 1841 res = res->nextRange; 1842 else 1843 break; 1844 } 1845 } 1846 debug_pci ("Mem...\n"); 1847 if (bus_cur->firstMem) { 1848 res = bus_cur->firstMem; 1849 while (res) { 1850 debug_pci ("The range # is %d\n", res->rangeno); 1851 debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); 1852 debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); 1853 if (res->next) 1854 res = res->next; 1855 else if (res->nextRange) 1856 res = res->nextRange; 1857 else 1858 break; 1859 } 1860 } 1861 debug_pci ("PFMem...\n"); 1862 if (bus_cur->firstPFMem) { 1863 res = bus_cur->firstPFMem; 1864 while (res) { 1865 debug_pci ("The range # is %d\n", res->rangeno); 1866 debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); 1867 debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); 1868 if (res->next) 1869 res = res->next; 1870 else if (res->nextRange) 1871 res = res->nextRange; 1872 else 1873 break; 1874 } 1875 } 1876 1877 debug_pci ("PFMemFromMem...\n"); 1878 if (bus_cur->firstPFMemFromMem) { 1879 res = bus_cur->firstPFMemFromMem; 1880 while (res) { 1881 debug_pci ("The range # is %d\n", res->rangeno); 1882 debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); 1883 debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); 1884 res = res->next; 1885 } 1886 } 1887 } 1888 debug_pci ("***********************END***********************\n"); 1889 } 1890 1891 static int range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type) 1892 { 1893 struct range_node * range_cur = NULL; 1894 switch (type) { 1895 case IO: 1896 range_cur = bus_cur->rangeIO; 1897 break; 1898 case MEM: 1899 range_cur = bus_cur->rangeMem; 1900 break; 1901 case PFMEM: 1902 range_cur = bus_cur->rangePFMem; 1903 break; 1904 default: 1905 err ("wrong type passed to find out if range already exists\n"); 1906 return -ENODEV; 1907 } 1908 1909 while (range_cur) { 1910 if ((range_cur->start == range->start) && (range_cur->end == range->end)) 1911 return 1; 1912 range_cur = range_cur->next; 1913 } 1914 1915 return 0; 1916 } 1917 1918 /* This routine will read the windows for any PPB we have and update the 1919 * range info for the secondary bus, and will also input this info into 1920 * primary bus, since BIOS doesn't. This is for PPB that are in the system 1921 * on bootup. For bridged cards that were added during previous load of the 1922 * driver, only the ranges and the bus structure are added, the devices are 1923 * added from NVRAM 1924 * Input: primary busno 1925 * Returns: none 1926 * Note: this function doesn't take into account IO restrictions etc, 1927 * so will only work for bridges with no video/ISA devices behind them It 1928 * also will not work for onboard PPB's that can have more than 1 *bus 1929 * behind them All these are TO DO. 1930 * Also need to add more error checkings... (from fnc returns etc) 1931 */ 1932 static int __init update_bridge_ranges (struct bus_node **bus) 1933 { 1934 u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address; 1935 u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address; 1936 u32 start_address, end_address, upper_start, upper_end; 1937 struct bus_node *bus_sec; 1938 struct bus_node *bus_cur; 1939 struct resource_node *io; 1940 struct resource_node *mem; 1941 struct resource_node *pfmem; 1942 struct range_node *range; 1943 unsigned int devfn; 1944 1945 bus_cur = *bus; 1946 if (!bus_cur) 1947 return -ENODEV; 1948 ibmphp_pci_bus->number = bus_cur->busno; 1949 1950 debug ("inside %s\n", __FUNCTION__); 1951 debug ("bus_cur->busno = %x\n", bus_cur->busno); 1952 1953 for (device = 0; device < 32; device++) { 1954 for (function = 0x00; function < 0x08; function++) { 1955 devfn = PCI_DEVFN(device, function); 1956 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id); 1957 1958 if (vendor_id != PCI_VENDOR_ID_NOTVALID) { 1959 /* found correct device!!! */ 1960 pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type); 1961 1962 switch (hdr_type) { 1963 case PCI_HEADER_TYPE_NORMAL: 1964 function = 0x8; 1965 break; 1966 case PCI_HEADER_TYPE_MULTIDEVICE: 1967 break; 1968 case PCI_HEADER_TYPE_BRIDGE: 1969 function = 0x8; 1970 case PCI_HEADER_TYPE_MULTIBRIDGE: 1971 /* We assume here that only 1 bus behind the bridge 1972 TO DO: add functionality for several: 1973 temp = secondary; 1974 while (temp < subordinate) { 1975 ... 1976 temp++; 1977 } 1978 */ 1979 pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno); 1980 bus_sec = find_bus_wprev (sec_busno, NULL, 0); 1981 /* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */ 1982 if (!bus_sec) { 1983 bus_sec = alloc_error_bus (NULL, sec_busno, 1); 1984 /* the rest will be populated during NVRAM call */ 1985 return 0; 1986 } 1987 pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address); 1988 pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address); 1989 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start); 1990 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end); 1991 start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8; 1992 start_address |= (upper_io_start << 16); 1993 end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8; 1994 end_address |= (upper_io_end << 16); 1995 1996 if ((start_address) && (start_address <= end_address)) { 1997 range = kmalloc (sizeof (struct range_node), GFP_KERNEL); 1998 if (!range) { 1999 err ("out of system memory\n"); 2000 return -ENOMEM; 2001 } 2002 memset (range, 0, sizeof (struct range_node)); 2003 range->start = start_address; 2004 range->end = end_address + 0xfff; 2005 2006 if (bus_sec->noIORanges > 0) { 2007 if (!range_exists_already (range, bus_sec, IO)) { 2008 add_range (IO, range, bus_sec); 2009 ++bus_sec->noIORanges; 2010 } else { 2011 kfree (range); 2012 range = NULL; 2013 } 2014 } else { 2015 /* 1st IO Range on the bus */ 2016 range->rangeno = 1; 2017 bus_sec->rangeIO = range; 2018 ++bus_sec->noIORanges; 2019 } 2020 fix_resources (bus_sec); 2021 2022 if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { 2023 io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); 2024 if (!io) { 2025 kfree (range); 2026 err ("out of system memory\n"); 2027 return -ENOMEM; 2028 } 2029 memset (io, 0, sizeof (struct resource_node)); 2030 io->type = IO; 2031 io->busno = bus_cur->busno; 2032 io->devfunc = ((device << 3) | (function & 0x7)); 2033 io->start = start_address; 2034 io->end = end_address + 0xfff; 2035 io->len = io->end - io->start + 1; 2036 ibmphp_add_resource (io); 2037 } 2038 } 2039 2040 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address); 2041 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address); 2042 2043 start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16; 2044 end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16; 2045 2046 if ((start_address) && (start_address <= end_address)) { 2047 2048 range = kmalloc (sizeof (struct range_node), GFP_KERNEL); 2049 if (!range) { 2050 err ("out of system memory\n"); 2051 return -ENOMEM; 2052 } 2053 memset (range, 0, sizeof (struct range_node)); 2054 range->start = start_address; 2055 range->end = end_address + 0xfffff; 2056 2057 if (bus_sec->noMemRanges > 0) { 2058 if (!range_exists_already (range, bus_sec, MEM)) { 2059 add_range (MEM, range, bus_sec); 2060 ++bus_sec->noMemRanges; 2061 } else { 2062 kfree (range); 2063 range = NULL; 2064 } 2065 } else { 2066 /* 1st Mem Range on the bus */ 2067 range->rangeno = 1; 2068 bus_sec->rangeMem = range; 2069 ++bus_sec->noMemRanges; 2070 } 2071 2072 fix_resources (bus_sec); 2073 2074 if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { 2075 mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); 2076 if (!mem) { 2077 kfree (range); 2078 err ("out of system memory\n"); 2079 return -ENOMEM; 2080 } 2081 memset (mem, 0, sizeof (struct resource_node)); 2082 mem->type = MEM; 2083 mem->busno = bus_cur->busno; 2084 mem->devfunc = ((device << 3) | (function & 0x7)); 2085 mem->start = start_address; 2086 mem->end = end_address + 0xfffff; 2087 mem->len = mem->end - mem->start + 1; 2088 ibmphp_add_resource (mem); 2089 } 2090 } 2091 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address); 2092 pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address); 2093 pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start); 2094 pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end); 2095 start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16; 2096 end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16; 2097 #if BITS_PER_LONG == 64 2098 start_address |= ((long) upper_start) << 32; 2099 end_address |= ((long) upper_end) << 32; 2100 #endif 2101 2102 if ((start_address) && (start_address <= end_address)) { 2103 2104 range = kmalloc (sizeof (struct range_node), GFP_KERNEL); 2105 if (!range) { 2106 err ("out of system memory\n"); 2107 return -ENOMEM; 2108 } 2109 memset (range, 0, sizeof (struct range_node)); 2110 range->start = start_address; 2111 range->end = end_address + 0xfffff; 2112 2113 if (bus_sec->noPFMemRanges > 0) { 2114 if (!range_exists_already (range, bus_sec, PFMEM)) { 2115 add_range (PFMEM, range, bus_sec); 2116 ++bus_sec->noPFMemRanges; 2117 } else { 2118 kfree (range); 2119 range = NULL; 2120 } 2121 } else { 2122 /* 1st PFMem Range on the bus */ 2123 range->rangeno = 1; 2124 bus_sec->rangePFMem = range; 2125 ++bus_sec->noPFMemRanges; 2126 } 2127 2128 fix_resources (bus_sec); 2129 if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { 2130 pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); 2131 if (!pfmem) { 2132 kfree (range); 2133 err ("out of system memory\n"); 2134 return -ENOMEM; 2135 } 2136 memset (pfmem, 0, sizeof (struct resource_node)); 2137 pfmem->type = PFMEM; 2138 pfmem->busno = bus_cur->busno; 2139 pfmem->devfunc = ((device << 3) | (function & 0x7)); 2140 pfmem->start = start_address; 2141 pfmem->end = end_address + 0xfffff; 2142 pfmem->len = pfmem->end - pfmem->start + 1; 2143 pfmem->fromMem = FALSE; 2144 2145 ibmphp_add_resource (pfmem); 2146 } 2147 } 2148 break; 2149 } /* end of switch */ 2150 } /* end if vendor */ 2151 } /* end for function */ 2152 } /* end for device */ 2153 2154 bus = &bus_cur; 2155 return 0; 2156 } 2157