PageRenderTime 1527ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/pci/hotplug/ibmphp_res.c

https://github.com/Mengqi/linux-2.6
C | 1861 lines | 1486 code | 152 blank | 223 comment | 403 complexity | 0476f8493219772833d816ceceeb0835 MD5 | raw file
  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. #include <linux/module.h>
  30. #include <linux/slab.h>
  31. #include <linux/pci.h>
  32. #include <linux/list.h>
  33. #include <linux/init.h>
  34. #include "ibmphp.h"
  35. static int flags = 0; /* for testing */
  36. static void update_resources (struct bus_node *bus_cur, int type, int rangeno);
  37. static int once_over (void);
  38. static int remove_ranges (struct bus_node *, struct bus_node *);
  39. static int update_bridge_ranges (struct bus_node **);
  40. static int add_bus_range (int type, struct range_node *, struct bus_node *);
  41. static void fix_resources (struct bus_node *);
  42. static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
  43. static LIST_HEAD(gbuses);
  44. static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag)
  45. {
  46. struct bus_node * newbus;
  47. if (!(curr) && !(flag)) {
  48. err ("NULL pointer passed\n");
  49. return NULL;
  50. }
  51. newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
  52. if (!newbus) {
  53. err ("out of system memory\n");
  54. return NULL;
  55. }
  56. if (flag)
  57. newbus->busno = busno;
  58. else
  59. newbus->busno = curr->bus_num;
  60. list_add_tail (&newbus->bus_list, &gbuses);
  61. return newbus;
  62. }
  63. static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr)
  64. {
  65. struct resource_node *rs;
  66. if (!curr) {
  67. err ("NULL passed to allocate\n");
  68. return NULL;
  69. }
  70. rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
  71. if (!rs) {
  72. err ("out of system memory\n");
  73. return NULL;
  74. }
  75. rs->busno = curr->bus_num;
  76. rs->devfunc = curr->dev_fun;
  77. rs->start = curr->start_addr;
  78. rs->end = curr->end_addr;
  79. rs->len = curr->end_addr - curr->start_addr + 1;
  80. return rs;
  81. }
  82. 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)
  83. {
  84. struct bus_node * newbus;
  85. struct range_node *newrange;
  86. u8 num_ranges = 0;
  87. if (first_bus) {
  88. newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL);
  89. if (!newbus) {
  90. err ("out of system memory.\n");
  91. return -ENOMEM;
  92. }
  93. newbus->busno = curr->bus_num;
  94. } else {
  95. newbus = *new_bus;
  96. switch (flag) {
  97. case MEM:
  98. num_ranges = newbus->noMemRanges;
  99. break;
  100. case PFMEM:
  101. num_ranges = newbus->noPFMemRanges;
  102. break;
  103. case IO:
  104. num_ranges = newbus->noIORanges;
  105. break;
  106. }
  107. }
  108. newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL);
  109. if (!newrange) {
  110. if (first_bus)
  111. kfree (newbus);
  112. err ("out of system memory\n");
  113. return -ENOMEM;
  114. }
  115. newrange->start = curr->start_addr;
  116. newrange->end = curr->end_addr;
  117. if (first_bus || (!num_ranges))
  118. newrange->rangeno = 1;
  119. else {
  120. /* need to insert our range */
  121. add_bus_range (flag, newrange, newbus);
  122. debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
  123. }
  124. switch (flag) {
  125. case MEM:
  126. newbus->rangeMem = newrange;
  127. if (first_bus)
  128. newbus->noMemRanges = 1;
  129. else {
  130. debug ("First Memory Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  131. ++newbus->noMemRanges;
  132. fix_resources (newbus);
  133. }
  134. break;
  135. case IO:
  136. newbus->rangeIO = newrange;
  137. if (first_bus)
  138. newbus->noIORanges = 1;
  139. else {
  140. debug ("First IO Primary on bus %x, [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  141. ++newbus->noIORanges;
  142. fix_resources (newbus);
  143. }
  144. break;
  145. case PFMEM:
  146. newbus->rangePFMem = newrange;
  147. if (first_bus)
  148. newbus->noPFMemRanges = 1;
  149. else {
  150. debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  151. ++newbus->noPFMemRanges;
  152. fix_resources (newbus);
  153. }
  154. break;
  155. }
  156. *new_bus = newbus;
  157. *new_range = newrange;
  158. return 0;
  159. }
  160. /* Notes:
  161. * 1. The ranges are ordered. The buses are not ordered. (First come)
  162. *
  163. * 2. If cannot allocate out of PFMem range, allocate from Mem ranges. PFmemFromMem
  164. * are not sorted. (no need since use mem node). To not change the entire code, we
  165. * also add mem node whenever this case happens so as not to change
  166. * ibmphp_check_mem_resource etc (and since it really is taking Mem resource)
  167. */
  168. /*****************************************************************************
  169. * This is the Resource Management initialization function. It will go through
  170. * the Resource list taken from EBDA and fill in this module's data structures
  171. *
  172. * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES,
  173. * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW
  174. *
  175. * Input: ptr to the head of the resource list from EBDA
  176. * Output: 0, -1 or error codes
  177. ***************************************************************************/
  178. int __init ibmphp_rsrc_init (void)
  179. {
  180. struct ebda_pci_rsrc *curr;
  181. struct range_node *newrange = NULL;
  182. struct bus_node *newbus = NULL;
  183. struct bus_node *bus_cur;
  184. struct bus_node *bus_prev;
  185. struct list_head *tmp;
  186. struct resource_node *new_io = NULL;
  187. struct resource_node *new_mem = NULL;
  188. struct resource_node *new_pfmem = NULL;
  189. int rc;
  190. struct list_head *tmp_ebda;
  191. list_for_each (tmp_ebda, &ibmphp_ebda_pci_rsrc_head) {
  192. curr = list_entry (tmp_ebda, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
  193. if (!(curr->rsrc_type & PCIDEVMASK)) {
  194. /* EBDA still lists non PCI devices, so ignore... */
  195. debug ("this is not a PCI DEVICE in rsrc_init, please take care\n");
  196. // continue;
  197. }
  198. /* this is a primary bus resource */
  199. if (curr->rsrc_type & PRIMARYBUSMASK) {
  200. /* memory */
  201. if ((curr->rsrc_type & RESTYPE) == MMASK) {
  202. /* no bus structure exists in place yet */
  203. if (list_empty (&gbuses)) {
  204. if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
  205. return rc;
  206. list_add_tail (&newbus->bus_list, &gbuses);
  207. debug ("gbuses = NULL, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  208. } else {
  209. bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
  210. /* found our bus */
  211. if (bus_cur) {
  212. rc = alloc_bus_range (&bus_cur, &newrange, curr, MEM, 0);
  213. if (rc)
  214. return rc;
  215. } else {
  216. /* went through all the buses and didn't find ours, need to create a new bus node */
  217. if ((rc = alloc_bus_range (&newbus, &newrange, curr, MEM, 1)))
  218. return rc;
  219. list_add_tail (&newbus->bus_list, &gbuses);
  220. debug ("New Bus, Memory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  221. }
  222. }
  223. } else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
  224. /* prefetchable memory */
  225. if (list_empty (&gbuses)) {
  226. /* no bus structure exists in place yet */
  227. if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
  228. return rc;
  229. list_add_tail (&newbus->bus_list, &gbuses);
  230. debug ("gbuses = NULL, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  231. } else {
  232. bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
  233. if (bus_cur) {
  234. /* found our bus */
  235. rc = alloc_bus_range (&bus_cur, &newrange, curr, PFMEM, 0);
  236. if (rc)
  237. return rc;
  238. } else {
  239. /* went through all the buses and didn't find ours, need to create a new bus node */
  240. if ((rc = alloc_bus_range (&newbus, &newrange, curr, PFMEM, 1)))
  241. return rc;
  242. list_add_tail (&newbus->bus_list, &gbuses);
  243. debug ("1st Bus, PFMemory Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  244. }
  245. }
  246. } else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
  247. /* IO */
  248. if (list_empty (&gbuses)) {
  249. /* no bus structure exists in place yet */
  250. if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
  251. return rc;
  252. list_add_tail (&newbus->bus_list, &gbuses);
  253. debug ("gbuses = NULL, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  254. } else {
  255. bus_cur = find_bus_wprev (curr->bus_num, &bus_prev, 1);
  256. if (bus_cur) {
  257. rc = alloc_bus_range (&bus_cur, &newrange, curr, IO, 0);
  258. if (rc)
  259. return rc;
  260. } else {
  261. /* went through all the buses and didn't find ours, need to create a new bus node */
  262. if ((rc = alloc_bus_range (&newbus, &newrange, curr, IO, 1)))
  263. return rc;
  264. list_add_tail (&newbus->bus_list, &gbuses);
  265. debug ("1st Bus, IO Primary Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);
  266. }
  267. }
  268. } else {
  269. ; /* type is reserved WHAT TO DO IN THIS CASE???
  270. NOTHING TO DO??? */
  271. }
  272. } else {
  273. /* regular pci device resource */
  274. if ((curr->rsrc_type & RESTYPE) == MMASK) {
  275. /* Memory resource */
  276. new_mem = alloc_resources (curr);
  277. if (!new_mem)
  278. return -ENOMEM;
  279. new_mem->type = MEM;
  280. /*
  281. * if it didn't find the bus, means PCI dev
  282. * came b4 the Primary Bus info, so need to
  283. * create a bus rangeno becomes a problem...
  284. * assign a -1 and then update once the range
  285. * actually appears...
  286. */
  287. if (ibmphp_add_resource (new_mem) < 0) {
  288. newbus = alloc_error_bus (curr, 0, 0);
  289. if (!newbus)
  290. return -ENOMEM;
  291. newbus->firstMem = new_mem;
  292. ++newbus->needMemUpdate;
  293. new_mem->rangeno = -1;
  294. }
  295. debug ("Memory resource for device %x, bus %x, [%x - %x]\n", new_mem->devfunc, new_mem->busno, new_mem->start, new_mem->end);
  296. } else if ((curr->rsrc_type & RESTYPE) == PFMASK) {
  297. /* PFMemory resource */
  298. new_pfmem = alloc_resources (curr);
  299. if (!new_pfmem)
  300. return -ENOMEM;
  301. new_pfmem->type = PFMEM;
  302. new_pfmem->fromMem = 0;
  303. if (ibmphp_add_resource (new_pfmem) < 0) {
  304. newbus = alloc_error_bus (curr, 0, 0);
  305. if (!newbus)
  306. return -ENOMEM;
  307. newbus->firstPFMem = new_pfmem;
  308. ++newbus->needPFMemUpdate;
  309. new_pfmem->rangeno = -1;
  310. }
  311. debug ("PFMemory resource for device %x, bus %x, [%x - %x]\n", new_pfmem->devfunc, new_pfmem->busno, new_pfmem->start, new_pfmem->end);
  312. } else if ((curr->rsrc_type & RESTYPE) == IOMASK) {
  313. /* IO resource */
  314. new_io = alloc_resources (curr);
  315. if (!new_io)
  316. return -ENOMEM;
  317. new_io->type = IO;
  318. /*
  319. * if it didn't find the bus, means PCI dev
  320. * came b4 the Primary Bus info, so need to
  321. * create a bus rangeno becomes a problem...
  322. * Can assign a -1 and then update once the
  323. * range actually appears...
  324. */
  325. if (ibmphp_add_resource (new_io) < 0) {
  326. newbus = alloc_error_bus (curr, 0, 0);
  327. if (!newbus)
  328. return -ENOMEM;
  329. newbus->firstIO = new_io;
  330. ++newbus->needIOUpdate;
  331. new_io->rangeno = -1;
  332. }
  333. debug ("IO resource for device %x, bus %x, [%x - %x]\n", new_io->devfunc, new_io->busno, new_io->start, new_io->end);
  334. }
  335. }
  336. }
  337. list_for_each (tmp, &gbuses) {
  338. bus_cur = list_entry (tmp, struct bus_node, bus_list);
  339. /* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */
  340. rc = update_bridge_ranges (&bus_cur);
  341. if (rc)
  342. return rc;
  343. }
  344. rc = once_over (); /* This is to align ranges (so no -1) */
  345. if (rc)
  346. return rc;
  347. return 0;
  348. }
  349. /********************************************************************************
  350. * This function adds a range into a sorted list of ranges per bus for a particular
  351. * range type, it then calls another routine to update the range numbers on the
  352. * pci devices' resources for the appropriate resource
  353. *
  354. * Input: type of the resource, range to add, current bus
  355. * Output: 0 or -1, bus and range ptrs
  356. ********************************************************************************/
  357. static int add_bus_range (int type, struct range_node *range, struct bus_node *bus_cur)
  358. {
  359. struct range_node *range_cur = NULL;
  360. struct range_node *range_prev;
  361. int count = 0, i_init;
  362. int noRanges = 0;
  363. switch (type) {
  364. case MEM:
  365. range_cur = bus_cur->rangeMem;
  366. noRanges = bus_cur->noMemRanges;
  367. break;
  368. case PFMEM:
  369. range_cur = bus_cur->rangePFMem;
  370. noRanges = bus_cur->noPFMemRanges;
  371. break;
  372. case IO:
  373. range_cur = bus_cur->rangeIO;
  374. noRanges = bus_cur->noIORanges;
  375. break;
  376. }
  377. range_prev = NULL;
  378. while (range_cur) {
  379. if (range->start < range_cur->start)
  380. break;
  381. range_prev = range_cur;
  382. range_cur = range_cur->next;
  383. count = count + 1;
  384. }
  385. if (!count) {
  386. /* our range will go at the beginning of the list */
  387. switch (type) {
  388. case MEM:
  389. bus_cur->rangeMem = range;
  390. break;
  391. case PFMEM:
  392. bus_cur->rangePFMem = range;
  393. break;
  394. case IO:
  395. bus_cur->rangeIO = range;
  396. break;
  397. }
  398. range->next = range_cur;
  399. range->rangeno = 1;
  400. i_init = 0;
  401. } else if (!range_cur) {
  402. /* our range will go at the end of the list */
  403. range->next = NULL;
  404. range_prev->next = range;
  405. range->rangeno = range_prev->rangeno + 1;
  406. return 0;
  407. } else {
  408. /* the range is in the middle */
  409. range_prev->next = range;
  410. range->next = range_cur;
  411. range->rangeno = range_cur->rangeno;
  412. i_init = range_prev->rangeno;
  413. }
  414. for (count = i_init; count < noRanges; ++count) {
  415. ++range_cur->rangeno;
  416. range_cur = range_cur->next;
  417. }
  418. update_resources (bus_cur, type, i_init + 1);
  419. return 0;
  420. }
  421. /*******************************************************************************
  422. * This routine goes through the list of resources of type 'type' and updates
  423. * the range numbers that they correspond to. It was called from add_bus_range fnc
  424. *
  425. * Input: bus, type of the resource, the rangeno starting from which to update
  426. ******************************************************************************/
  427. static void update_resources (struct bus_node *bus_cur, int type, int rangeno)
  428. {
  429. struct resource_node *res = NULL;
  430. u8 eol = 0; /* end of list indicator */
  431. switch (type) {
  432. case MEM:
  433. if (bus_cur->firstMem)
  434. res = bus_cur->firstMem;
  435. break;
  436. case PFMEM:
  437. if (bus_cur->firstPFMem)
  438. res = bus_cur->firstPFMem;
  439. break;
  440. case IO:
  441. if (bus_cur->firstIO)
  442. res = bus_cur->firstIO;
  443. break;
  444. }
  445. if (res) {
  446. while (res) {
  447. if (res->rangeno == rangeno)
  448. break;
  449. if (res->next)
  450. res = res->next;
  451. else if (res->nextRange)
  452. res = res->nextRange;
  453. else {
  454. eol = 1;
  455. break;
  456. }
  457. }
  458. if (!eol) {
  459. /* found the range */
  460. while (res) {
  461. ++res->rangeno;
  462. res = res->next;
  463. }
  464. }
  465. }
  466. }
  467. static void fix_me (struct resource_node *res, struct bus_node *bus_cur, struct range_node *range)
  468. {
  469. char * str = "";
  470. switch (res->type) {
  471. case IO:
  472. str = "io";
  473. break;
  474. case MEM:
  475. str = "mem";
  476. break;
  477. case PFMEM:
  478. str = "pfmem";
  479. break;
  480. }
  481. while (res) {
  482. if (res->rangeno == -1) {
  483. while (range) {
  484. if ((res->start >= range->start) && (res->end <= range->end)) {
  485. res->rangeno = range->rangeno;
  486. debug ("%s->rangeno in fix_resources is %d\n", str, res->rangeno);
  487. switch (res->type) {
  488. case IO:
  489. --bus_cur->needIOUpdate;
  490. break;
  491. case MEM:
  492. --bus_cur->needMemUpdate;
  493. break;
  494. case PFMEM:
  495. --bus_cur->needPFMemUpdate;
  496. break;
  497. }
  498. break;
  499. }
  500. range = range->next;
  501. }
  502. }
  503. if (res->next)
  504. res = res->next;
  505. else
  506. res = res->nextRange;
  507. }
  508. }
  509. /*****************************************************************************
  510. * This routine reassigns the range numbers to the resources that had a -1
  511. * This case can happen only if upon initialization, resources taken by pci dev
  512. * appear in EBDA before the resources allocated for that bus, since we don't
  513. * know the range, we assign -1, and this routine is called after a new range
  514. * is assigned to see the resources with unknown range belong to the added range
  515. *
  516. * Input: current bus
  517. * Output: none, list of resources for that bus are fixed if can be
  518. *******************************************************************************/
  519. static void fix_resources (struct bus_node *bus_cur)
  520. {
  521. struct range_node *range;
  522. struct resource_node *res;
  523. debug ("%s - bus_cur->busno = %d\n", __func__, bus_cur->busno);
  524. if (bus_cur->needIOUpdate) {
  525. res = bus_cur->firstIO;
  526. range = bus_cur->rangeIO;
  527. fix_me (res, bus_cur, range);
  528. }
  529. if (bus_cur->needMemUpdate) {
  530. res = bus_cur->firstMem;
  531. range = bus_cur->rangeMem;
  532. fix_me (res, bus_cur, range);
  533. }
  534. if (bus_cur->needPFMemUpdate) {
  535. res = bus_cur->firstPFMem;
  536. range = bus_cur->rangePFMem;
  537. fix_me (res, bus_cur, range);
  538. }
  539. }
  540. /*******************************************************************************
  541. * This routine adds a resource to the list of resources to the appropriate bus
  542. * based on their resource type and sorted by their starting addresses. It assigns
  543. * the ptrs to next and nextRange if needed.
  544. *
  545. * Input: resource ptr
  546. * Output: ptrs assigned (to the node)
  547. * 0 or -1
  548. *******************************************************************************/
  549. int ibmphp_add_resource (struct resource_node *res)
  550. {
  551. struct resource_node *res_cur;
  552. struct resource_node *res_prev;
  553. struct bus_node *bus_cur;
  554. struct range_node *range_cur = NULL;
  555. struct resource_node *res_start = NULL;
  556. debug ("%s - enter\n", __func__);
  557. if (!res) {
  558. err ("NULL passed to add\n");
  559. return -ENODEV;
  560. }
  561. bus_cur = find_bus_wprev (res->busno, NULL, 0);
  562. if (!bus_cur) {
  563. /* didn't find a bus, smth's wrong!!! */
  564. debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
  565. return -ENODEV;
  566. }
  567. /* Normal case */
  568. switch (res->type) {
  569. case IO:
  570. range_cur = bus_cur->rangeIO;
  571. res_start = bus_cur->firstIO;
  572. break;
  573. case MEM:
  574. range_cur = bus_cur->rangeMem;
  575. res_start = bus_cur->firstMem;
  576. break;
  577. case PFMEM:
  578. range_cur = bus_cur->rangePFMem;
  579. res_start = bus_cur->firstPFMem;
  580. break;
  581. default:
  582. err ("cannot read the type of the resource to add... problem\n");
  583. return -EINVAL;
  584. }
  585. while (range_cur) {
  586. if ((res->start >= range_cur->start) && (res->end <= range_cur->end)) {
  587. res->rangeno = range_cur->rangeno;
  588. break;
  589. }
  590. range_cur = range_cur->next;
  591. }
  592. /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  593. * this is again the case of rangeno = -1
  594. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  595. */
  596. if (!range_cur) {
  597. switch (res->type) {
  598. case IO:
  599. ++bus_cur->needIOUpdate;
  600. break;
  601. case MEM:
  602. ++bus_cur->needMemUpdate;
  603. break;
  604. case PFMEM:
  605. ++bus_cur->needPFMemUpdate;
  606. break;
  607. }
  608. res->rangeno = -1;
  609. }
  610. debug ("The range is %d\n", res->rangeno);
  611. if (!res_start) {
  612. /* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */
  613. switch (res->type) {
  614. case IO:
  615. bus_cur->firstIO = res;
  616. break;
  617. case MEM:
  618. bus_cur->firstMem = res;
  619. break;
  620. case PFMEM:
  621. bus_cur->firstPFMem = res;
  622. break;
  623. }
  624. res->next = NULL;
  625. res->nextRange = NULL;
  626. } else {
  627. res_cur = res_start;
  628. res_prev = NULL;
  629. debug ("res_cur->rangeno is %d\n", res_cur->rangeno);
  630. while (res_cur) {
  631. if (res_cur->rangeno >= res->rangeno)
  632. break;
  633. res_prev = res_cur;
  634. if (res_cur->next)
  635. res_cur = res_cur->next;
  636. else
  637. res_cur = res_cur->nextRange;
  638. }
  639. if (!res_cur) {
  640. /* at the end of the resource list */
  641. debug ("i should be here, [%x - %x]\n", res->start, res->end);
  642. res_prev->nextRange = res;
  643. res->next = NULL;
  644. res->nextRange = NULL;
  645. } else if (res_cur->rangeno == res->rangeno) {
  646. /* in the same range */
  647. while (res_cur) {
  648. if (res->start < res_cur->start)
  649. break;
  650. res_prev = res_cur;
  651. res_cur = res_cur->next;
  652. }
  653. if (!res_cur) {
  654. /* the last resource in this range */
  655. res_prev->next = res;
  656. res->next = NULL;
  657. res->nextRange = res_prev->nextRange;
  658. res_prev->nextRange = NULL;
  659. } else if (res->start < res_cur->start) {
  660. /* at the beginning or middle of the range */
  661. if (!res_prev) {
  662. switch (res->type) {
  663. case IO:
  664. bus_cur->firstIO = res;
  665. break;
  666. case MEM:
  667. bus_cur->firstMem = res;
  668. break;
  669. case PFMEM:
  670. bus_cur->firstPFMem = res;
  671. break;
  672. }
  673. } else if (res_prev->rangeno == res_cur->rangeno)
  674. res_prev->next = res;
  675. else
  676. res_prev->nextRange = res;
  677. res->next = res_cur;
  678. res->nextRange = NULL;
  679. }
  680. } else {
  681. /* this is the case where it is 1st occurrence of the range */
  682. if (!res_prev) {
  683. /* at the beginning of the resource list */
  684. res->next = NULL;
  685. switch (res->type) {
  686. case IO:
  687. res->nextRange = bus_cur->firstIO;
  688. bus_cur->firstIO = res;
  689. break;
  690. case MEM:
  691. res->nextRange = bus_cur->firstMem;
  692. bus_cur->firstMem = res;
  693. break;
  694. case PFMEM:
  695. res->nextRange = bus_cur->firstPFMem;
  696. bus_cur->firstPFMem = res;
  697. break;
  698. }
  699. } else if (res_cur->rangeno > res->rangeno) {
  700. /* in the middle of the resource list */
  701. res_prev->nextRange = res;
  702. res->next = NULL;
  703. res->nextRange = res_cur;
  704. }
  705. }
  706. }
  707. debug ("%s - exit\n", __func__);
  708. return 0;
  709. }
  710. /****************************************************************************
  711. * This routine will remove the resource from the list of resources
  712. *
  713. * Input: io, mem, and/or pfmem resource to be deleted
  714. * Ouput: modified resource list
  715. * 0 or error code
  716. ****************************************************************************/
  717. int ibmphp_remove_resource (struct resource_node *res)
  718. {
  719. struct bus_node *bus_cur;
  720. struct resource_node *res_cur = NULL;
  721. struct resource_node *res_prev;
  722. struct resource_node *mem_cur;
  723. char * type = "";
  724. if (!res) {
  725. err ("resource to remove is NULL\n");
  726. return -ENODEV;
  727. }
  728. bus_cur = find_bus_wprev (res->busno, NULL, 0);
  729. if (!bus_cur) {
  730. err ("cannot find corresponding bus of the io resource to remove "
  731. "bailing out...\n");
  732. return -ENODEV;
  733. }
  734. switch (res->type) {
  735. case IO:
  736. res_cur = bus_cur->firstIO;
  737. type = "io";
  738. break;
  739. case MEM:
  740. res_cur = bus_cur->firstMem;
  741. type = "mem";
  742. break;
  743. case PFMEM:
  744. res_cur = bus_cur->firstPFMem;
  745. type = "pfmem";
  746. break;
  747. default:
  748. err ("unknown type for resource to remove\n");
  749. return -EINVAL;
  750. }
  751. res_prev = NULL;
  752. while (res_cur) {
  753. if ((res_cur->start == res->start) && (res_cur->end == res->end))
  754. break;
  755. res_prev = res_cur;
  756. if (res_cur->next)
  757. res_cur = res_cur->next;
  758. else
  759. res_cur = res_cur->nextRange;
  760. }
  761. if (!res_cur) {
  762. if (res->type == PFMEM) {
  763. /*
  764. * case where pfmem might be in the PFMemFromMem list
  765. * so will also need to remove the corresponding mem
  766. * entry
  767. */
  768. res_cur = bus_cur->firstPFMemFromMem;
  769. res_prev = NULL;
  770. while (res_cur) {
  771. if ((res_cur->start == res->start) && (res_cur->end == res->end)) {
  772. mem_cur = bus_cur->firstMem;
  773. while (mem_cur) {
  774. if ((mem_cur->start == res_cur->start)
  775. && (mem_cur->end == res_cur->end))
  776. break;
  777. if (mem_cur->next)
  778. mem_cur = mem_cur->next;
  779. else
  780. mem_cur = mem_cur->nextRange;
  781. }
  782. if (!mem_cur) {
  783. err ("cannot find corresponding mem node for pfmem...\n");
  784. return -EINVAL;
  785. }
  786. ibmphp_remove_resource (mem_cur);
  787. if (!res_prev)
  788. bus_cur->firstPFMemFromMem = res_cur->next;
  789. else
  790. res_prev->next = res_cur->next;
  791. kfree (res_cur);
  792. return 0;
  793. }
  794. res_prev = res_cur;
  795. if (res_cur->next)
  796. res_cur = res_cur->next;
  797. else
  798. res_cur = res_cur->nextRange;
  799. }
  800. if (!res_cur) {
  801. err ("cannot find pfmem to delete...\n");
  802. return -EINVAL;
  803. }
  804. } else {
  805. err ("the %s resource is not in the list to be deleted...\n", type);
  806. return -EINVAL;
  807. }
  808. }
  809. if (!res_prev) {
  810. /* first device to be deleted */
  811. if (res_cur->next) {
  812. switch (res->type) {
  813. case IO:
  814. bus_cur->firstIO = res_cur->next;
  815. break;
  816. case MEM:
  817. bus_cur->firstMem = res_cur->next;
  818. break;
  819. case PFMEM:
  820. bus_cur->firstPFMem = res_cur->next;
  821. break;
  822. }
  823. } else if (res_cur->nextRange) {
  824. switch (res->type) {
  825. case IO:
  826. bus_cur->firstIO = res_cur->nextRange;
  827. break;
  828. case MEM:
  829. bus_cur->firstMem = res_cur->nextRange;
  830. break;
  831. case PFMEM:
  832. bus_cur->firstPFMem = res_cur->nextRange;
  833. break;
  834. }
  835. } else {
  836. switch (res->type) {
  837. case IO:
  838. bus_cur->firstIO = NULL;
  839. break;
  840. case MEM:
  841. bus_cur->firstMem = NULL;
  842. break;
  843. case PFMEM:
  844. bus_cur->firstPFMem = NULL;
  845. break;
  846. }
  847. }
  848. kfree (res_cur);
  849. return 0;
  850. } else {
  851. if (res_cur->next) {
  852. if (res_prev->rangeno == res_cur->rangeno)
  853. res_prev->next = res_cur->next;
  854. else
  855. res_prev->nextRange = res_cur->next;
  856. } else if (res_cur->nextRange) {
  857. res_prev->next = NULL;
  858. res_prev->nextRange = res_cur->nextRange;
  859. } else {
  860. res_prev->next = NULL;
  861. res_prev->nextRange = NULL;
  862. }
  863. kfree (res_cur);
  864. return 0;
  865. }
  866. return 0;
  867. }
  868. static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res)
  869. {
  870. struct range_node * range = NULL;
  871. switch (res->type) {
  872. case IO:
  873. range = bus_cur->rangeIO;
  874. break;
  875. case MEM:
  876. range = bus_cur->rangeMem;
  877. break;
  878. case PFMEM:
  879. range = bus_cur->rangePFMem;
  880. break;
  881. default:
  882. err ("cannot read resource type in find_range\n");
  883. }
  884. while (range) {
  885. if (res->rangeno == range->rangeno)
  886. break;
  887. range = range->next;
  888. }
  889. return range;
  890. }
  891. /*****************************************************************************
  892. * This routine will check to make sure the io/mem/pfmem->len that the device asked for
  893. * can fit w/i our list of available IO/MEM/PFMEM resources. If cannot, returns -EINVAL,
  894. * otherwise, returns 0
  895. *
  896. * Input: resource
  897. * Ouput: the correct start and end address are inputted into the resource node,
  898. * 0 or -EINVAL
  899. *****************************************************************************/
  900. int ibmphp_check_resource (struct resource_node *res, u8 bridge)
  901. {
  902. struct bus_node *bus_cur;
  903. struct range_node *range = NULL;
  904. struct resource_node *res_prev;
  905. struct resource_node *res_cur = NULL;
  906. u32 len_cur = 0, start_cur = 0, len_tmp = 0;
  907. int noranges = 0;
  908. u32 tmp_start; /* this is to make sure start address is divisible by the length needed */
  909. u32 tmp_divide;
  910. u8 flag = 0;
  911. if (!res)
  912. return -EINVAL;
  913. if (bridge) {
  914. /* The rules for bridges are different, 4K divisible for IO, 1M for (pf)mem*/
  915. if (res->type == IO)
  916. tmp_divide = IOBRIDGE;
  917. else
  918. tmp_divide = MEMBRIDGE;
  919. } else
  920. tmp_divide = res->len;
  921. bus_cur = find_bus_wprev (res->busno, NULL, 0);
  922. if (!bus_cur) {
  923. /* didn't find a bus, smth's wrong!!! */
  924. debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");
  925. return -EINVAL;
  926. }
  927. debug ("%s - enter\n", __func__);
  928. debug ("bus_cur->busno is %d\n", bus_cur->busno);
  929. /* This is a quick fix to not mess up with the code very much. i.e.,
  930. * 2000-2fff, len = 1000, but when we compare, we need it to be fff */
  931. res->len -= 1;
  932. switch (res->type) {
  933. case IO:
  934. res_cur = bus_cur->firstIO;
  935. noranges = bus_cur->noIORanges;
  936. break;
  937. case MEM:
  938. res_cur = bus_cur->firstMem;
  939. noranges = bus_cur->noMemRanges;
  940. break;
  941. case PFMEM:
  942. res_cur = bus_cur->firstPFMem;
  943. noranges = bus_cur->noPFMemRanges;
  944. break;
  945. default:
  946. err ("wrong type of resource to check\n");
  947. return -EINVAL;
  948. }
  949. res_prev = NULL;
  950. while (res_cur) {
  951. range = find_range (bus_cur, res_cur);
  952. debug ("%s - rangeno = %d\n", __func__, res_cur->rangeno);
  953. if (!range) {
  954. err ("no range for the device exists... bailing out...\n");
  955. return -EINVAL;
  956. }
  957. /* found our range */
  958. if (!res_prev) {
  959. /* first time in the loop */
  960. if ((res_cur->start != range->start) && ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
  961. debug ("len_tmp = %x\n", len_tmp);
  962. if ((len_tmp < len_cur) || (len_cur == 0)) {
  963. if ((range->start % tmp_divide) == 0) {
  964. /* just perfect, starting address is divisible by length */
  965. flag = 1;
  966. len_cur = len_tmp;
  967. start_cur = range->start;
  968. } else {
  969. /* Needs adjusting */
  970. tmp_start = range->start;
  971. flag = 0;
  972. while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
  973. if ((tmp_start % tmp_divide) == 0) {
  974. flag = 1;
  975. len_cur = len_tmp;
  976. start_cur = tmp_start;
  977. break;
  978. }
  979. tmp_start += tmp_divide - tmp_start % tmp_divide;
  980. if (tmp_start >= res_cur->start - 1)
  981. break;
  982. }
  983. }
  984. if (flag && len_cur == res->len) {
  985. debug ("but we are not here, right?\n");
  986. res->start = start_cur;
  987. res->len += 1; /* To restore the balance */
  988. res->end = res->start + res->len - 1;
  989. return 0;
  990. }
  991. }
  992. }
  993. }
  994. if (!res_cur->next) {
  995. /* last device on the range */
  996. if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) {
  997. debug ("len_tmp = %x\n", len_tmp);
  998. if ((len_tmp < len_cur) || (len_cur == 0)) {
  999. if (((res_cur->end + 1) % tmp_divide) == 0) {
  1000. /* just perfect, starting address is divisible by length */
  1001. flag = 1;
  1002. len_cur = len_tmp;
  1003. start_cur = res_cur->end + 1;
  1004. } else {
  1005. /* Needs adjusting */
  1006. tmp_start = res_cur->end + 1;
  1007. flag = 0;
  1008. while ((len_tmp = range->end - tmp_start) >= res->len) {
  1009. if ((tmp_start % tmp_divide) == 0) {
  1010. flag = 1;
  1011. len_cur = len_tmp;
  1012. start_cur = tmp_start;
  1013. break;
  1014. }
  1015. tmp_start += tmp_divide - tmp_start % tmp_divide;
  1016. if (tmp_start >= range->end)
  1017. break;
  1018. }
  1019. }
  1020. if (flag && len_cur == res->len) {
  1021. res->start = start_cur;
  1022. res->len += 1; /* To restore the balance */
  1023. res->end = res->start + res->len - 1;
  1024. return 0;
  1025. }
  1026. }
  1027. }
  1028. }
  1029. if (res_prev) {
  1030. if (res_prev->rangeno != res_cur->rangeno) {
  1031. /* 1st device on this range */
  1032. if ((res_cur->start != range->start) &&
  1033. ((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {
  1034. if ((len_tmp < len_cur) || (len_cur == 0)) {
  1035. if ((range->start % tmp_divide) == 0) {
  1036. /* just perfect, starting address is divisible by length */
  1037. flag = 1;
  1038. len_cur = len_tmp;
  1039. start_cur = range->start;
  1040. } else {
  1041. /* Needs adjusting */
  1042. tmp_start = range->start;
  1043. flag = 0;
  1044. while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
  1045. if ((tmp_start % tmp_divide) == 0) {
  1046. flag = 1;
  1047. len_cur = len_tmp;
  1048. start_cur = tmp_start;
  1049. break;
  1050. }
  1051. tmp_start += tmp_divide - tmp_start % tmp_divide;
  1052. if (tmp_start >= res_cur->start - 1)
  1053. break;
  1054. }
  1055. }
  1056. if (flag && len_cur == res->len) {
  1057. res->start = start_cur;
  1058. res->len += 1; /* To restore the balance */
  1059. res->end = res->start + res->len - 1;
  1060. return 0;
  1061. }
  1062. }
  1063. }
  1064. } else {
  1065. /* in the same range */
  1066. if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) {
  1067. if ((len_tmp < len_cur) || (len_cur == 0)) {
  1068. if (((res_prev->end + 1) % tmp_divide) == 0) {
  1069. /* just perfect, starting address's divisible by length */
  1070. flag = 1;
  1071. len_cur = len_tmp;
  1072. start_cur = res_prev->end + 1;
  1073. } else {
  1074. /* Needs adjusting */
  1075. tmp_start = res_prev->end + 1;
  1076. flag = 0;
  1077. while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {
  1078. if ((tmp_start % tmp_divide) == 0) {
  1079. flag = 1;
  1080. len_cur = len_tmp;
  1081. start_cur = tmp_start;
  1082. break;
  1083. }
  1084. tmp_start += tmp_divide - tmp_start % tmp_divide;
  1085. if (tmp_start >= res_cur->start - 1)
  1086. break;
  1087. }
  1088. }
  1089. if (flag && len_cur == res->len) {
  1090. res->start = start_cur;
  1091. res->len += 1; /* To restore the balance */
  1092. res->end = res->start + res->len - 1;
  1093. return 0;
  1094. }
  1095. }
  1096. }
  1097. }
  1098. }
  1099. /* end if (res_prev) */
  1100. res_prev = res_cur;
  1101. if (res_cur->next)
  1102. res_cur = res_cur->next;
  1103. else
  1104. res_cur = res_cur->nextRange;
  1105. } /* end of while */
  1106. if (!res_prev) {
  1107. /* 1st device ever */
  1108. /* need to find appropriate range */
  1109. switch (res->type) {
  1110. case IO:
  1111. range = bus_cur->rangeIO;
  1112. break;
  1113. case MEM:
  1114. range = bus_cur->rangeMem;
  1115. break;
  1116. case PFMEM:
  1117. range = bus_cur->rangePFMem;
  1118. break;
  1119. }
  1120. while (range) {
  1121. if ((len_tmp = range->end - range->start) >= res->len) {
  1122. if ((len_tmp < len_cur) || (len_cur == 0)) {
  1123. if ((range->start % tmp_divide) == 0) {
  1124. /* just perfect, starting address's 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. while ((len_tmp = range->end - tmp_start) >= res->len) {
  1133. if ((tmp_start % tmp_divide) == 0) {
  1134. flag = 1;
  1135. len_cur = len_tmp;
  1136. start_cur = tmp_start;
  1137. break;
  1138. }
  1139. tmp_start += tmp_divide - tmp_start % tmp_divide;
  1140. if (tmp_start >= range->end)
  1141. break;
  1142. }
  1143. }
  1144. if (flag && len_cur == res->len) {
  1145. res->start = start_cur;
  1146. res->len += 1; /* To restore the balance */
  1147. res->end = res->start + res->len - 1;
  1148. return 0;
  1149. }
  1150. }
  1151. }
  1152. range = range->next;
  1153. } /* end of while */
  1154. if ((!range) && (len_cur == 0)) {
  1155. /* have gone through the list of devices and ranges and haven't found n.e.thing */
  1156. err ("no appropriate range.. bailing out...\n");
  1157. return -EINVAL;
  1158. } else if (len_cur) {
  1159. res->start = start_cur;
  1160. res->len += 1; /* To restore the balance */
  1161. res->end = res->start + res->len - 1;
  1162. return 0;
  1163. }
  1164. }
  1165. if (!res_cur) {
  1166. debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);
  1167. if (res_prev->rangeno < noranges) {
  1168. /* if there're more ranges out there to check */
  1169. switch (res->type) {
  1170. case IO:
  1171. range = bus_cur->rangeIO;
  1172. break;
  1173. case MEM:
  1174. range = bus_cur->rangeMem;
  1175. break;
  1176. case PFMEM:
  1177. range = bus_cur->rangePFMem;
  1178. break;
  1179. }
  1180. while (range) {
  1181. if ((len_tmp = range->end - range->start) >= res->len) {
  1182. if ((len_tmp < len_cur) || (len_cur == 0)) {
  1183. if ((range->start % tmp_divide) == 0) {
  1184. /* just perfect, starting address's divisible by length */
  1185. flag = 1;
  1186. len_cur = len_tmp;
  1187. start_cur = range->start;
  1188. } else {
  1189. /* Needs adjusting */
  1190. tmp_start = range->start;
  1191. flag = 0;
  1192. while ((len_tmp = range->end - tmp_start) >= res->len) {
  1193. if ((tmp_start % tmp_divide) == 0) {
  1194. flag = 1;
  1195. len_cur = len_tmp;
  1196. start_cur = tmp_start;
  1197. break;
  1198. }
  1199. tmp_start += tmp_divide - tmp_start % tmp_divide;
  1200. if (tmp_start >= range->end)
  1201. break;
  1202. }
  1203. }
  1204. if (flag && len_cur == res->len) {
  1205. res->start = start_cur;
  1206. res->len += 1; /* To restore the balance */
  1207. res->end = res->start + res->len - 1;
  1208. return 0;
  1209. }
  1210. }
  1211. }
  1212. range = range->next;
  1213. } /* end of while */
  1214. if ((!range) && (len_cur == 0)) {
  1215. /* have gone through the list of devices and ranges and haven't found n.e.thing */
  1216. err ("no appropriate range.. bailing out...\n");
  1217. return -EINVAL;
  1218. } else if (len_cur) {
  1219. res->start = start_cur;
  1220. res->len += 1; /* To restore the balance */
  1221. res->end = res->start + res->len - 1;
  1222. return 0;
  1223. }
  1224. } else {
  1225. /* no more ranges to check on */
  1226. if (len_cur) {
  1227. res->start = start_cur;
  1228. res->len += 1; /* To restore the balance */
  1229. res->end = res->start + res->len - 1;
  1230. return 0;
  1231. } else {
  1232. /* have gone through the list of devices and haven't found n.e.thing */
  1233. err ("no appropriate range.. bailing out...\n");
  1234. return -EINVAL;
  1235. }
  1236. }
  1237. } /* end if(!res_cur) */
  1238. return -EINVAL;
  1239. }
  1240. /********************************************************************************
  1241. * This routine is called from remove_card if the card contained PPB.
  1242. * It will remove all the resources on the bus as well as the bus itself
  1243. * Input: Bus
  1244. * Ouput: 0, -ENODEV
  1245. ********************************************************************************/
  1246. int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)
  1247. {
  1248. struct resource_node *res_cur;
  1249. struct resource_node *res_tmp;
  1250. struct bus_node *prev_bus;
  1251. int rc;
  1252. prev_bus = find_bus_wprev (parent_busno, NULL, 0);
  1253. if (!prev_bus) {
  1254. debug ("something terribly wrong. Cannot find parent bus to the one to remove\n");
  1255. return -ENODEV;
  1256. }
  1257. debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);
  1258. rc = remove_ranges (bus, prev_bus);
  1259. if (rc)
  1260. return rc;
  1261. if (bus->firstIO) {
  1262. res_cur = bus->firstIO;
  1263. while (res_cur) {
  1264. res_tmp = res_cur;
  1265. if (res_cur->next)
  1266. res_cur = res_cur->next;
  1267. else
  1268. res_cur = res_cur->nextRange;
  1269. kfree (res_tmp);
  1270. res_tmp = NULL;
  1271. }
  1272. bus->firstIO = NULL;
  1273. }
  1274. if (bus->firstMem) {
  1275. res_cur = bus->firstMem;
  1276. while (res_cur) {
  1277. res_tmp = res_cur;
  1278. if (res_cur->next)
  1279. res_cur = res_cur->next;
  1280. else
  1281. res_cur = res_cur->nextRange;
  1282. kfree (res_tmp);
  1283. res_tmp = NULL;
  1284. }
  1285. bus->firstMem = NULL;
  1286. }
  1287. if (bus->firstPFMem) {
  1288. res_cur = bus->firstPFMem;
  1289. while (res_cur) {
  1290. res_tmp = res_cur;
  1291. if (res_cur->next)
  1292. res_cur = res_cur->next;
  1293. else
  1294. res_cur = res_cur->nextRange;
  1295. kfree (res_tmp);
  1296. res_tmp = NULL;
  1297. }
  1298. bus->firstPFMem = NULL;
  1299. }
  1300. if (bus->firstPFMemFromMem) {
  1301. res_cur = bus->firstPFMemFromMem;
  1302. while (res_cur) {
  1303. res_tmp = res_cur;
  1304. res_cur = res_cur->next;
  1305. kfree (res_tmp);
  1306. res_tmp = NULL;
  1307. }
  1308. bus->firstPFMemFromMem = NULL;
  1309. }
  1310. list_del (&bus->bus_list);
  1311. kfree (bus);
  1312. return 0;
  1313. }
  1314. /******************************************************************************
  1315. * This routine deletes the ranges from a given bus, and the entries from the
  1316. * parent's bus in the resources
  1317. * Input: current bus, previous bus
  1318. * Output: 0, -EINVAL
  1319. ******************************************************************************/
  1320. static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)
  1321. {
  1322. struct range_node *range_cur;
  1323. struct range_node *range_tmp;
  1324. int i;
  1325. struct resource_node *res = NULL;
  1326. if (bus_cur->noIORanges) {
  1327. range_cur = bus_cur->rangeIO;
  1328. for (i = 0; i < bus_cur->noIORanges; i++) {
  1329. if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0)
  1330. return -EINVAL;
  1331. ibmphp_remove_resource (res);
  1332. range_tmp = range_cur;
  1333. range_cur = range_cur->next;
  1334. kfree (range_tmp);
  1335. range_tmp = NULL;
  1336. }
  1337. bus_cur->rangeIO = NULL;
  1338. }
  1339. if (bus_cur->noMemRanges) {
  1340. range_cur = bus_cur->rangeMem;
  1341. for (i = 0; i < bus_cur->noMemRanges; i++) {
  1342. if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0)
  1343. return -EINVAL;
  1344. ibmphp_remove_resource (res);
  1345. range_tmp = range_cur;
  1346. range_cur = range_cur->next;
  1347. kfree (range_tmp);
  1348. range_tmp = NULL;
  1349. }
  1350. bus_cur->rangeMem = NULL;
  1351. }
  1352. if (bus_cur->noPFMemRanges) {
  1353. range_cur = bus_cur->rangePFMem;
  1354. for (i = 0; i < bus_cur->noPFMemRanges; i++) {
  1355. if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0)
  1356. return -EINVAL;
  1357. ibmphp_remove_resource (res);
  1358. range_tmp = range_cur;
  1359. range_cur = range_cur->next;
  1360. kfree (range_tmp);
  1361. range_tmp = NULL;
  1362. }
  1363. bus_cur->rangePFMem = NULL;
  1364. }
  1365. return 0;
  1366. }
  1367. /*
  1368. * find the resource node in the bus
  1369. * Input: Resource needed, start address of the resource, type of resource
  1370. */
  1371. int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag)
  1372. {
  1373. struct resource_node *res_cur = NULL;
  1374. char * type = "";
  1375. if (!bus) {
  1376. err ("The bus passed in NULL to find resource\n");
  1377. return -ENODEV;
  1378. }
  1379. switch (flag) {
  1380. case IO:
  1381. res_cur = bus->firstIO;
  1382. type = "io";
  1383. break;
  1384. case MEM:
  1385. res_cur = bus->firstMem;
  1386. type = "mem";
  1387. break;
  1388. case PFMEM:
  1389. res_cur = bus->firstPFMem;
  1390. type = "pfmem";
  1391. break;
  1392. default:
  1393. err ("wrong type of flag\n");
  1394. return -EINVAL;
  1395. }
  1396. while (res_cur) {
  1397. if (res_cur->start == start_address) {
  1398. *res = res_cur;
  1399. break;
  1400. }
  1401. if (res_cur->next)
  1402. res_cur = res_cur->next;
  1403. else
  1404. res_cur = res_cur->nextRange;
  1405. }
  1406. if (!res_cur) {
  1407. if (flag == PFMEM) {
  1408. res_cur = bus->firstPFMemFromMem;
  1409. while (res_cur) {
  1410. if (res_cur->start == start_address) {
  1411. *res = res_cur;
  1412. break;
  1413. }
  1414. res_cur = res_cur->next;
  1415. }
  1416. if (!res_cur) {
  1417. debug ("SOS...cannot find %s resource in the bus.\n", type);
  1418. return -EINVAL;
  1419. }
  1420. } else {
  1421. debug ("SOS... cannot find %s resource in the bus.\n", type);
  1422. return -EINVAL;
  1423. }
  1424. }
  1425. if (*res)
  1426. debug ("*res->start = %x\n", (*res)->start);
  1427. return 0;
  1428. }
  1429. /***********************************************************************
  1430. * This routine will free the resource structures used by the
  1431. * system. It is called from cleanup routine for the module
  1432. * Parameters: none
  1433. * Returns: none
  1434. ***********************************************************************/
  1435. void ibmphp_free_resources (void)
  1436. {
  1437. struct bus_node *bus_cur = NULL;
  1438. struct bus_node *bus_tmp;
  1439. struct range_node *range_cur;
  1440. struct range_node *range_tmp;
  1441. struct resource_node *res_cur;
  1442. struct resource_node *res_tmp;
  1443. struct list_head *tmp;
  1444. struct list_head *next;
  1445. int i = 0;
  1446. flags = 1;
  1447. list_for_each_safe (tmp, next, &gbuses) {
  1448. bus_cur = list_entry (tmp, struct bus_node, bus_list);
  1449. if (bus_cur->noIORanges) {
  1450. range_cur = bus_cur->rangeIO;
  1451. for (i = 0; i < bus_cur->noIORanges; i++) {
  1452. if (!range_cur)
  1453. break;
  1454. range_tmp = range_cur;
  1455. range_cur = range_cur->next;
  1456. kfree (range_tmp);
  1457. range_tmp = NULL;
  1458. }
  1459. }
  1460. if (bus_cur->noMemRanges) {
  1461. range_cur = bus_cur->rangeMem;
  1462. for (i = 0; i < bus_cur->noMemRanges; i++) {
  1463. if (!range_cur)
  1464. break;
  1465. range_tmp = range_cur;
  1466. range_cur = range_cur->next;
  1467. kfree (range_tmp);
  1468. range_tmp = NULL;
  1469. }
  1470. }
  1471. if (bus_cur->noPFMemRanges) {
  1472. range_cur = bus_cur->rangePFMem;
  1473. for (i = 0; i < bus_cur->noPFMemRanges; i++) {
  1474. if (!range_cur)
  1475. break;
  1476. range_tmp = range_cur;
  1477. range_cur = range_cur->next;
  1478. kfree (range_tmp);
  1479. range_tmp = NULL;
  1480. }
  1481. }
  1482. if (bus_cur->firstIO) {
  1483. res_cur = bus_cur->firstIO;
  1484. while (res_cur) {
  1485. res_tmp = res_cur;
  1486. if (res_cur->next)
  1487. res_cur = res_cur->next;
  1488. else
  1489. res_cur = res_cur->nextRange;
  1490. kfree (res_tmp);
  1491. res_tmp = NULL;
  1492. }
  1493. bus_cur->firstIO = NULL;
  1494. }
  1495. if (bus_cur->firstMem) {
  1496. res_cur = bus_cur->firstMem;
  1497. while (res_cur) {
  1498. res_tmp = res_cur;
  1499. if (res_cur->next)
  1500. res_cur = res_cur->next;
  1501. else
  1502. res_cur = res_cur->nextRange;
  1503. kfree (res_tmp);
  1504. res_tmp = NULL;
  1505. }
  1506. bus_cur->firstMem = NULL;
  1507. }
  1508. if (bus_cur->firstPFMem) {
  1509. res_cur = bus_cur->firstPFMem;
  1510. while (res_cur) {
  1511. res_tmp = res_cur;
  1512. if (res_cur->next)
  1513. res_cur = res_cur->next;
  1514. else
  1515. res_cur = res_cur->nextRange;
  1516. kfree (res_tmp);
  1517. res_tmp = NULL;
  1518. }
  1519. bus_cur->firstPFMem = NULL;
  1520. }
  1521. if (bus_cur->firstPFMemFromMem) {
  1522. res_cur = bus_cur->firstPFMemFromMem;
  1523. while (res_cur) {
  1524. res_tmp = res_cur;
  1525. res_cur = res_cur->next;
  1526. kfree (res_tmp);
  1527. res_tmp = NULL;
  1528. }
  1529. bus_cur->firstPFMemFromMem = NULL;
  1530. }
  1531. bus_tmp = bus_cur;
  1532. list_del (&bus_cur->bus_list);
  1533. kfree (bus_tmp);
  1534. bus_tmp = NULL;
  1535. }
  1536. }
  1537. /*********************************************************************************
  1538. * This function will go over the PFmem resources to check if the EBDA allocated
  1539. * pfmem out of memory buckets of the bus. If so, it will change the range numbers
  1540. * and a flag to indicate that this resource is out of memory. It will also move the
  1541. * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create
  1542. * a new Mem node
  1543. * This routine is called right after initialization
  1544. *******************************************************************************/
  1545. static int __init once_over (void)
  1546. {
  1547. struct resource_node *pfmem_cur;
  1548. struct resource_node *pfmem_prev;
  1549. struct resource_node *mem;
  1550. struct bus_node *bus_cur;
  1551. struct list_head *tmp;
  1552. list_for_each (tmp, &gbuses) {
  1553. bus_cur = list_entry (tmp, struct bus_node, bus_list);
  1554. if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {
  1555. for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {
  1556. pfmem_cur->fromMem = 1;
  1557. if (pfmem_prev)
  1558. pfmem_prev->next = pfmem_cur->next;
  1559. else
  1560. bus_cur->firstPFMem = pfmem_cur->next;
  1561. if (!bus_cur->firstPFMemFromMem)
  1562. pfmem_cur->next = NULL;
  1563. else
  1564. /* we don't need to sort PFMemFromMem since we're using mem node for
  1565. all the real work anyways, so just insert at the beginning of the
  1566. list
  1567. */
  1568. pfmem_cur->next = bus_cur->firstPFMemFromMem;
  1569. bus_cur->firstPFMemFromMem = pfmem_cur;
  1570. mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
  1571. if (!mem) {
  1572. err ("out of system memory\n");
  1573. return -ENOMEM;
  1574. }
  1575. mem->type = MEM;
  1576. mem->busno = pfmem_cur->busno;
  1577. mem->devfunc = pfmem_cur->devfunc;
  1578. mem->start = pfmem_cur->start;
  1579. mem->end = pfmem_cur->end;
  1580. mem->len = pfmem_cur->len;
  1581. if (ibmphp_add_resource (mem) < 0)
  1582. err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");
  1583. pfmem_cur->rangeno = mem->rangeno;
  1584. } /* end for pfmem */
  1585. } /* end if */
  1586. } /* end list_for_each bus */
  1587. return 0;
  1588. }
  1589. int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem)
  1590. {
  1591. struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0);
  1592. if (!bus_cur) {
  1593. err ("cannot find bus of pfmem to add...\n");
  1594. return -ENODEV;
  1595. }
  1596. if (bus_cur->firstPFMemFromMem)
  1597. pfmem->next = bus_cur->firstPFMemFromMem;
  1598. else
  1599. pfmem->next = NULL;
  1600. bus_cur->firstPFMemFromMem = pfmem;
  1601. return 0;
  1602. }
  1603. /* This routine just goes through the buses to see if the bus already exists.
  1604. * It is called from ibmphp_find_sec_number, to find out a secondary bus number for
  1605. * bridged cards
  1606. * Parameters: bus_number
  1607. * Returns: Bus pointer or NULL
  1608. */
  1609. struct bus_node *ibmphp_find_res_bus (u8 bus_number)
  1610. {
  1611. return find_bus_wprev (bus_number, NULL, 0);
  1612. }
  1613. static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
  1614. {
  1615. struct bus_node *bus_cur;
  1616. struct list_head *tmp;
  1617. struct list_head *tmp_prev;
  1618. list_for_each (tmp, &gbuses) {
  1619. tmp_prev = tmp->prev;
  1620. bus_cur = list_entry (tmp, struct bus_node, bus_list);
  1621. if (flag)
  1622. *prev = list_entry (tmp_prev, struct bus_node, bus_list);
  1623. if (bus_cur->busno == bus_number)
  1624. return bus_cur;
  1625. }
  1626. return NULL;
  1627. }
  1628. void ibmphp_print_test (void)
  1629. {
  1630. int i = 0;
  1631. struct bus_node *bus_cur = NULL;
  1632. struct range_node *range;
  1633. struct resource_node *res;
  1634. struct list_head *tmp;
  1635. debug_pci ("*****************START**********************\n");
  1636. if ((!list_empty(&gbuses)) && flags) {
  1637. err ("The GBUSES is not NULL?!?!?!?!?\n");
  1638. return;
  1639. }
  1640. list_for_each (tmp, &gbuses) {
  1641. bus_cur = list_entry (tmp, struct bus_node, bus_list);
  1642. debug_pci ("This is bus # %d. There are\n", bus_cur->busno);
  1643. debug_pci ("IORanges = %d\t", bus_cur->noIORanges);
  1644. debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);
  1645. debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);
  1646. debug_pci ("The IO Ranges are as follows:\n");
  1647. if (bus_cur->rangeIO) {
  1648. range = bus_cur->rangeIO;
  1649. for (i = 0; i < bus_cur->noIORanges; i++) {
  1650. debug_pci ("rangeno is %d\n", range->rangeno);
  1651. debug_pci ("[%x - %x]\n", range->start, range->end);
  1652. range = range->next;
  1653. }
  1654. }
  1655. debug_pci ("The Mem Ranges are as follows:\n");
  1656. if (bus_cur->rangeMem) {
  1657. range = bus_cur->rangeMem;
  1658. for (i = 0; i < bus_cur->noMemRanges; i++) {
  1659. debug_pci ("rangeno is %d\n", range->rangeno);
  1660. debug_pci ("[%x - %x]\n", range->start, range->end);
  1661. range = range->next;
  1662. }
  1663. }
  1664. debug_pci ("The PFMem Ranges are as follows:\n");
  1665. if (bus_cur->rangePFMem) {
  1666. range = bus_cur->rangePFMem;
  1667. for (i = 0; i < bus_cur->noPFMemRanges; i++) {
  1668. debug_pci ("rangeno is %d\n", range->rangeno);
  1669. debug_pci ("[%x - %x]\n", range->start, range->end);
  1670. range = range->next;
  1671. }
  1672. }
  1673. debug_pci ("The resources on this bus are as follows\n");
  1674. debug_pci ("IO...\n");
  1675. if (bus_cur->firstIO) {
  1676. res = bus_cur->firstIO;
  1677. while (res) {
  1678. debug_pci ("The range # is %d\n", res->rangeno);
  1679. debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
  1680. debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
  1681. if (res->next)
  1682. res = res->next;
  1683. else if (res->nextRange)
  1684. res = res->nextRange;
  1685. else
  1686. break;
  1687. }
  1688. }
  1689. debug_pci ("Mem...\n");
  1690. if (bus_cur->firstMem) {
  1691. res = bus_cur->firstMem;
  1692. while (res) {
  1693. debug_pci ("The range # is %d\n", res->rangeno);
  1694. debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);
  1695. debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);
  1696. if (res->next)
  1697. res = res->next;
  1698. else if (res->nextRange)
  1699. res = res->nextRange;
  1700. else
  1701. break;
  1702. }
  1703. }
  1704. debug_pci ("PFMem...\n");
  1705. if (bus_cur->firstPFMem) {
  1706. res = bus_cur->firstPFMem;
  1707. while (res) {
  1708. debug_pci ("The range # is %d\n", res->rangeno);
  1709. debug_pci ("The bus