ibmphp_res.c 57 KB

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