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