eeh_pseries.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /*
  2. * The file intends to implement the platform dependent EEH operations on pseries.
  3. * Actually, the pseries platform is built based on RTAS heavily. That means the
  4. * pseries platform dependent EEH operations will be built on RTAS calls. The functions
  5. * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has
  6. * been done.
  7. *
  8. * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011.
  9. * Copyright IBM Corporation 2001, 2005, 2006
  10. * Copyright Dave Engebretsen & Todd Inglett 2001
  11. * Copyright Linas Vepstas 2005, 2006
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. */
  27. #include <linux/atomic.h>
  28. #include <linux/delay.h>
  29. #include <linux/export.h>
  30. #include <linux/init.h>
  31. #include <linux/list.h>
  32. #include <linux/of.h>
  33. #include <linux/pci.h>
  34. #include <linux/proc_fs.h>
  35. #include <linux/rbtree.h>
  36. #include <linux/sched.h>
  37. #include <linux/seq_file.h>
  38. #include <linux/spinlock.h>
  39. #include <asm/eeh.h>
  40. #include <asm/eeh_event.h>
  41. #include <asm/io.h>
  42. #include <asm/machdep.h>
  43. #include <asm/ppc-pci.h>
  44. #include <asm/rtas.h>
  45. /* RTAS tokens */
  46. static int ibm_set_eeh_option;
  47. static int ibm_set_slot_reset;
  48. static int ibm_read_slot_reset_state;
  49. static int ibm_read_slot_reset_state2;
  50. static int ibm_slot_error_detail;
  51. static int ibm_get_config_addr_info;
  52. static int ibm_get_config_addr_info2;
  53. static int ibm_configure_bridge;
  54. static int ibm_configure_pe;
  55. /*
  56. * Buffer for reporting slot-error-detail rtas calls. Its here
  57. * in BSS, and not dynamically alloced, so that it ends up in
  58. * RMO where RTAS can access it.
  59. */
  60. static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
  61. static DEFINE_SPINLOCK(slot_errbuf_lock);
  62. static int eeh_error_buf_size;
  63. /**
  64. * pseries_eeh_init - EEH platform dependent initialization
  65. *
  66. * EEH platform dependent initialization on pseries.
  67. */
  68. static int pseries_eeh_init(void)
  69. {
  70. /* figure out EEH RTAS function call tokens */
  71. ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
  72. ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
  73. ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");
  74. ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
  75. ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
  76. ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
  77. ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
  78. ibm_configure_pe = rtas_token("ibm,configure-pe");
  79. ibm_configure_bridge = rtas_token("ibm,configure-bridge");
  80. /* necessary sanity check */
  81. if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
  82. pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",
  83. __func__);
  84. return -EINVAL;
  85. } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {
  86. pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n",
  87. __func__);
  88. return -EINVAL;
  89. } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
  90. ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) {
  91. pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and "
  92. "<ibm,read-slot-reset-state> invalid\n",
  93. __func__);
  94. return -EINVAL;
  95. } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) {
  96. pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",
  97. __func__);
  98. return -EINVAL;
  99. } else if (ibm_get_config_addr_info2 == RTAS_UNKNOWN_SERVICE &&
  100. ibm_get_config_addr_info == RTAS_UNKNOWN_SERVICE) {
  101. pr_warning("%s: RTAS service <ibm,get-config-addr-info2> and "
  102. "<ibm,get-config-addr-info> invalid\n",
  103. __func__);
  104. return -EINVAL;
  105. } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
  106. ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {
  107. pr_warning("%s: RTAS service <ibm,configure-pe> and "
  108. "<ibm,configure-bridge> invalid\n",
  109. __func__);
  110. return -EINVAL;
  111. }
  112. /* Initialize error log lock and size */
  113. spin_lock_init(&slot_errbuf_lock);
  114. eeh_error_buf_size = rtas_token("rtas-error-log-max");
  115. if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {
  116. pr_warning("%s: unknown EEH error log size\n",
  117. __func__);
  118. eeh_error_buf_size = 1024;
  119. } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
  120. pr_warning("%s: EEH error log size %d exceeds the maximal %d\n",
  121. __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX);
  122. eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
  123. }
  124. /* Set EEH probe mode */
  125. eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE);
  126. return 0;
  127. }
  128. /**
  129. * pseries_eeh_of_probe - EEH probe on the given device
  130. * @dn: OF node
  131. * @flag: Unused
  132. *
  133. * When EEH module is installed during system boot, all PCI devices
  134. * are checked one by one to see if it supports EEH. The function
  135. * is introduced for the purpose.
  136. */
  137. static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
  138. {
  139. struct eeh_dev *edev;
  140. struct eeh_pe pe;
  141. const u32 *class_code, *vendor_id, *device_id;
  142. const u32 *regs;
  143. int enable = 0;
  144. int ret;
  145. /* Retrieve OF node and eeh device */
  146. edev = of_node_to_eeh_dev(dn);
  147. if (!of_device_is_available(dn))
  148. return NULL;
  149. /* Retrieve class/vendor/device IDs */
  150. class_code = of_get_property(dn, "class-code", NULL);
  151. vendor_id = of_get_property(dn, "vendor-id", NULL);
  152. device_id = of_get_property(dn, "device-id", NULL);
  153. /* Skip for bad OF node or PCI-ISA bridge */
  154. if (!class_code || !vendor_id || !device_id)
  155. return NULL;
  156. if (dn->type && !strcmp(dn->type, "isa"))
  157. return NULL;
  158. /* Update class code and mode of eeh device */
  159. edev->class_code = *class_code;
  160. edev->mode = 0;
  161. /* Retrieve the device address */
  162. regs = of_get_property(dn, "reg", NULL);
  163. if (!regs) {
  164. pr_warning("%s: OF node property %s::reg not found\n",
  165. __func__, dn->full_name);
  166. return NULL;
  167. }
  168. /* Initialize the fake PE */
  169. memset(&pe, 0, sizeof(struct eeh_pe));
  170. pe.phb = edev->phb;
  171. pe.config_addr = regs[0];
  172. /* Enable EEH on the device */
  173. ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE);
  174. if (!ret) {
  175. edev->config_addr = regs[0];
  176. /* Retrieve PE address */
  177. edev->pe_config_addr = eeh_ops->get_pe_addr(&pe);
  178. pe.addr = edev->pe_config_addr;
  179. /* Some older systems (Power4) allow the ibm,set-eeh-option
  180. * call to succeed even on nodes where EEH is not supported.
  181. * Verify support explicitly.
  182. */
  183. ret = eeh_ops->get_state(&pe, NULL);
  184. if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
  185. enable = 1;
  186. if (enable) {
  187. eeh_subsystem_enabled = 1;
  188. eeh_add_to_parent_pe(edev);
  189. pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
  190. __func__, dn->full_name, pe.phb->global_number,
  191. pe.addr, pe.config_addr);
  192. } else if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
  193. (of_node_to_eeh_dev(dn->parent))->pe) {
  194. /* This device doesn't support EEH, but it may have an
  195. * EEH parent, in which case we mark it as supported.
  196. */
  197. edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
  198. edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr;
  199. eeh_add_to_parent_pe(edev);
  200. }
  201. }
  202. /* Save memory bars */
  203. eeh_save_bars(edev);
  204. return NULL;
  205. }
  206. /**
  207. * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
  208. * @pe: EEH PE
  209. * @option: operation to be issued
  210. *
  211. * The function is used to control the EEH functionality globally.
  212. * Currently, following options are support according to PAPR:
  213. * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
  214. */
  215. static int pseries_eeh_set_option(struct eeh_pe *pe, int option)
  216. {
  217. int ret = 0;
  218. int config_addr;
  219. /*
  220. * When we're enabling or disabling EEH functioality on
  221. * the particular PE, the PE config address is possibly
  222. * unavailable. Therefore, we have to figure it out from
  223. * the FDT node.
  224. */
  225. switch (option) {
  226. case EEH_OPT_DISABLE:
  227. case EEH_OPT_ENABLE:
  228. case EEH_OPT_THAW_MMIO:
  229. case EEH_OPT_THAW_DMA:
  230. config_addr = pe->config_addr;
  231. if (pe->addr)
  232. config_addr = pe->addr;
  233. break;
  234. default:
  235. pr_err("%s: Invalid option %d\n",
  236. __func__, option);
  237. return -EINVAL;
  238. }
  239. ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
  240. config_addr, BUID_HI(pe->phb->buid),
  241. BUID_LO(pe->phb->buid), option);
  242. return ret;
  243. }
  244. /**
  245. * pseries_eeh_get_pe_addr - Retrieve PE address
  246. * @pe: EEH PE
  247. *
  248. * Retrieve the assocated PE address. Actually, there're 2 RTAS
  249. * function calls dedicated for the purpose. We need implement
  250. * it through the new function and then the old one. Besides,
  251. * you should make sure the config address is figured out from
  252. * FDT node before calling the function.
  253. *
  254. * It's notable that zero'ed return value means invalid PE config
  255. * address.
  256. */
  257. static int pseries_eeh_get_pe_addr(struct eeh_pe *pe)
  258. {
  259. int ret = 0;
  260. int rets[3];
  261. if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
  262. /*
  263. * First of all, we need to make sure there has one PE
  264. * associated with the device. Otherwise, PE address is
  265. * meaningless.
  266. */
  267. ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
  268. pe->config_addr, BUID_HI(pe->phb->buid),
  269. BUID_LO(pe->phb->buid), 1);
  270. if (ret || (rets[0] == 0))
  271. return 0;
  272. /* Retrieve the associated PE config address */
  273. ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
  274. pe->config_addr, BUID_HI(pe->phb->buid),
  275. BUID_LO(pe->phb->buid), 0);
  276. if (ret) {
  277. pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
  278. __func__, pe->phb->global_number, pe->config_addr);
  279. return 0;
  280. }
  281. return rets[0];
  282. }
  283. if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
  284. ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets,
  285. pe->config_addr, BUID_HI(pe->phb->buid),
  286. BUID_LO(pe->phb->buid), 0);
  287. if (ret) {
  288. pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
  289. __func__, pe->phb->global_number, pe->config_addr);
  290. return 0;
  291. }
  292. return rets[0];
  293. }
  294. return ret;
  295. }
  296. /**
  297. * pseries_eeh_get_state - Retrieve PE state
  298. * @pe: EEH PE
  299. * @state: return value
  300. *
  301. * Retrieve the state of the specified PE. On RTAS compliant
  302. * pseries platform, there already has one dedicated RTAS function
  303. * for the purpose. It's notable that the associated PE config address
  304. * might be ready when calling the function. Therefore, endeavour to
  305. * use the PE config address if possible. Further more, there're 2
  306. * RTAS calls for the purpose, we need to try the new one and back
  307. * to the old one if the new one couldn't work properly.
  308. */
  309. static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
  310. {
  311. int config_addr;
  312. int ret;
  313. int rets[4];
  314. int result;
  315. /* Figure out PE config address if possible */
  316. config_addr = pe->config_addr;
  317. if (pe->addr)
  318. config_addr = pe->addr;
  319. if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
  320. ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets,
  321. config_addr, BUID_HI(pe->phb->buid),
  322. BUID_LO(pe->phb->buid));
  323. } else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) {
  324. /* Fake PE unavailable info */
  325. rets[2] = 0;
  326. ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
  327. config_addr, BUID_HI(pe->phb->buid),
  328. BUID_LO(pe->phb->buid));
  329. } else {
  330. return EEH_STATE_NOT_SUPPORT;
  331. }
  332. if (ret)
  333. return ret;
  334. /* Parse the result out */
  335. result = 0;
  336. if (rets[1]) {
  337. switch(rets[0]) {
  338. case 0:
  339. result &= ~EEH_STATE_RESET_ACTIVE;
  340. result |= EEH_STATE_MMIO_ACTIVE;
  341. result |= EEH_STATE_DMA_ACTIVE;
  342. break;
  343. case 1:
  344. result |= EEH_STATE_RESET_ACTIVE;
  345. result |= EEH_STATE_MMIO_ACTIVE;
  346. result |= EEH_STATE_DMA_ACTIVE;
  347. break;
  348. case 2:
  349. result &= ~EEH_STATE_RESET_ACTIVE;
  350. result &= ~EEH_STATE_MMIO_ACTIVE;
  351. result &= ~EEH_STATE_DMA_ACTIVE;
  352. break;
  353. case 4:
  354. result &= ~EEH_STATE_RESET_ACTIVE;
  355. result &= ~EEH_STATE_MMIO_ACTIVE;
  356. result &= ~EEH_STATE_DMA_ACTIVE;
  357. result |= EEH_STATE_MMIO_ENABLED;
  358. break;
  359. case 5:
  360. if (rets[2]) {
  361. if (state) *state = rets[2];
  362. result = EEH_STATE_UNAVAILABLE;
  363. } else {
  364. result = EEH_STATE_NOT_SUPPORT;
  365. }
  366. default:
  367. result = EEH_STATE_NOT_SUPPORT;
  368. }
  369. } else {
  370. result = EEH_STATE_NOT_SUPPORT;
  371. }
  372. return result;
  373. }
  374. /**
  375. * pseries_eeh_reset - Reset the specified PE
  376. * @pe: EEH PE
  377. * @option: reset option
  378. *
  379. * Reset the specified PE
  380. */
  381. static int pseries_eeh_reset(struct eeh_pe *pe, int option)
  382. {
  383. int config_addr;
  384. int ret;
  385. /* Figure out PE address */
  386. config_addr = pe->config_addr;
  387. if (pe->addr)
  388. config_addr = pe->addr;
  389. /* Reset PE through RTAS call */
  390. ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
  391. config_addr, BUID_HI(pe->phb->buid),
  392. BUID_LO(pe->phb->buid), option);
  393. /* If fundamental-reset not supported, try hot-reset */
  394. if (option == EEH_RESET_FUNDAMENTAL &&
  395. ret == -8) {
  396. ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
  397. config_addr, BUID_HI(pe->phb->buid),
  398. BUID_LO(pe->phb->buid), EEH_RESET_HOT);
  399. }
  400. return ret;
  401. }
  402. /**
  403. * pseries_eeh_wait_state - Wait for PE state
  404. * @pe: EEH PE
  405. * @max_wait: maximal period in microsecond
  406. *
  407. * Wait for the state of associated PE. It might take some time
  408. * to retrieve the PE's state.
  409. */
  410. static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait)
  411. {
  412. int ret;
  413. int mwait;
  414. /*
  415. * According to PAPR, the state of PE might be temporarily
  416. * unavailable. Under the circumstance, we have to wait
  417. * for indicated time determined by firmware. The maximal
  418. * wait time is 5 minutes, which is acquired from the original
  419. * EEH implementation. Also, the original implementation
  420. * also defined the minimal wait time as 1 second.
  421. */
  422. #define EEH_STATE_MIN_WAIT_TIME (1000)
  423. #define EEH_STATE_MAX_WAIT_TIME (300 * 1000)
  424. while (1) {
  425. ret = pseries_eeh_get_state(pe, &mwait);
  426. /*
  427. * If the PE's state is temporarily unavailable,
  428. * we have to wait for the specified time. Otherwise,
  429. * the PE's state will be returned immediately.
  430. */
  431. if (ret != EEH_STATE_UNAVAILABLE)
  432. return ret;
  433. if (max_wait <= 0) {
  434. pr_warning("%s: Timeout when getting PE's state (%d)\n",
  435. __func__, max_wait);
  436. return EEH_STATE_NOT_SUPPORT;
  437. }
  438. if (mwait <= 0) {
  439. pr_warning("%s: Firmware returned bad wait value %d\n",
  440. __func__, mwait);
  441. mwait = EEH_STATE_MIN_WAIT_TIME;
  442. } else if (mwait > EEH_STATE_MAX_WAIT_TIME) {
  443. pr_warning("%s: Firmware returned too long wait value %d\n",
  444. __func__, mwait);
  445. mwait = EEH_STATE_MAX_WAIT_TIME;
  446. }
  447. max_wait -= mwait;
  448. msleep(mwait);
  449. }
  450. return EEH_STATE_NOT_SUPPORT;
  451. }
  452. /**
  453. * pseries_eeh_get_log - Retrieve error log
  454. * @pe: EEH PE
  455. * @severity: temporary or permanent error log
  456. * @drv_log: driver log to be combined with retrieved error log
  457. * @len: length of driver log
  458. *
  459. * Retrieve the temporary or permanent error from the PE.
  460. * Actually, the error will be retrieved through the dedicated
  461. * RTAS call.
  462. */
  463. static int pseries_eeh_get_log(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len)
  464. {
  465. int config_addr;
  466. unsigned long flags;
  467. int ret;
  468. spin_lock_irqsave(&slot_errbuf_lock, flags);
  469. memset(slot_errbuf, 0, eeh_error_buf_size);
  470. /* Figure out the PE address */
  471. config_addr = pe->config_addr;
  472. if (pe->addr)
  473. config_addr = pe->addr;
  474. ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
  475. BUID_HI(pe->phb->buid), BUID_LO(pe->phb->buid),
  476. virt_to_phys(drv_log), len,
  477. virt_to_phys(slot_errbuf), eeh_error_buf_size,
  478. severity);
  479. if (!ret)
  480. log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
  481. spin_unlock_irqrestore(&slot_errbuf_lock, flags);
  482. return ret;
  483. }
  484. /**
  485. * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE
  486. * @pe: EEH PE
  487. *
  488. * The function will be called to reconfigure the bridges included
  489. * in the specified PE so that the mulfunctional PE would be recovered
  490. * again.
  491. */
  492. static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
  493. {
  494. int config_addr;
  495. int ret;
  496. /* Figure out the PE address */
  497. config_addr = pe->config_addr;
  498. if (pe->addr)
  499. config_addr = pe->addr;
  500. /* Use new configure-pe function, if supported */
  501. if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
  502. ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
  503. config_addr, BUID_HI(pe->phb->buid),
  504. BUID_LO(pe->phb->buid));
  505. } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
  506. ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
  507. config_addr, BUID_HI(pe->phb->buid),
  508. BUID_LO(pe->phb->buid));
  509. } else {
  510. return -EFAULT;
  511. }
  512. if (ret)
  513. pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
  514. __func__, pe->phb->global_number, pe->addr, ret);
  515. return ret;
  516. }
  517. /**
  518. * pseries_eeh_read_config - Read PCI config space
  519. * @dn: device node
  520. * @where: PCI address
  521. * @size: size to read
  522. * @val: return value
  523. *
  524. * Read config space from the speicifed device
  525. */
  526. static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val)
  527. {
  528. struct pci_dn *pdn;
  529. pdn = PCI_DN(dn);
  530. return rtas_read_config(pdn, where, size, val);
  531. }
  532. /**
  533. * pseries_eeh_write_config - Write PCI config space
  534. * @dn: device node
  535. * @where: PCI address
  536. * @size: size to write
  537. * @val: value to be written
  538. *
  539. * Write config space to the specified device
  540. */
  541. static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val)
  542. {
  543. struct pci_dn *pdn;
  544. pdn = PCI_DN(dn);
  545. return rtas_write_config(pdn, where, size, val);
  546. }
  547. static struct eeh_ops pseries_eeh_ops = {
  548. .name = "pseries",
  549. .init = pseries_eeh_init,
  550. .of_probe = pseries_eeh_of_probe,
  551. .dev_probe = NULL,
  552. .set_option = pseries_eeh_set_option,
  553. .get_pe_addr = pseries_eeh_get_pe_addr,
  554. .get_state = pseries_eeh_get_state,
  555. .reset = pseries_eeh_reset,
  556. .wait_state = pseries_eeh_wait_state,
  557. .get_log = pseries_eeh_get_log,
  558. .configure_bridge = pseries_eeh_configure_bridge,
  559. .read_config = pseries_eeh_read_config,
  560. .write_config = pseries_eeh_write_config
  561. };
  562. /**
  563. * eeh_pseries_init - Register platform dependent EEH operations
  564. *
  565. * EEH initialization on pseries platform. This function should be
  566. * called before any EEH related functions.
  567. */
  568. static int __init eeh_pseries_init(void)
  569. {
  570. int ret = -EINVAL;
  571. if (!machine_is(pseries))
  572. return ret;
  573. ret = eeh_ops_register(&pseries_eeh_ops);
  574. if (!ret)
  575. pr_info("EEH: pSeries platform initialized\n");
  576. else
  577. pr_info("EEH: pSeries platform initialization failure (%d)\n",
  578. ret);
  579. return ret;
  580. }
  581. early_initcall(eeh_pseries_init);