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