ibmphp_res.c 56 KB

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