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