eeh-powernv.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * The file intends to implement the platform dependent EEH operations on
  3. * powernv platform. Actually, the powernv was created in order to fully
  4. * hypervisor support.
  5. *
  6. * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2013.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <linux/atomic.h>
  14. #include <linux/delay.h>
  15. #include <linux/export.h>
  16. #include <linux/init.h>
  17. #include <linux/list.h>
  18. #include <linux/msi.h>
  19. #include <linux/of.h>
  20. #include <linux/pci.h>
  21. #include <linux/proc_fs.h>
  22. #include <linux/rbtree.h>
  23. #include <linux/sched.h>
  24. #include <linux/seq_file.h>
  25. #include <linux/spinlock.h>
  26. #include <asm/eeh.h>
  27. #include <asm/eeh_event.h>
  28. #include <asm/firmware.h>
  29. #include <asm/io.h>
  30. #include <asm/iommu.h>
  31. #include <asm/machdep.h>
  32. #include <asm/msi_bitmap.h>
  33. #include <asm/opal.h>
  34. #include <asm/ppc-pci.h>
  35. #include "powernv.h"
  36. #include "pci.h"
  37. /**
  38. * powernv_eeh_init - EEH platform dependent initialization
  39. *
  40. * EEH platform dependent initialization on powernv
  41. */
  42. static int powernv_eeh_init(void)
  43. {
  44. /* We require OPALv3 */
  45. if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
  46. pr_warning("%s: OPALv3 is required !\n", __func__);
  47. return -EINVAL;
  48. }
  49. /* Set EEH probe mode */
  50. eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
  51. return 0;
  52. }
  53. /**
  54. * powernv_eeh_post_init - EEH platform dependent post initialization
  55. *
  56. * EEH platform dependent post initialization on powernv. When
  57. * the function is called, the EEH PEs and devices should have
  58. * been built. If the I/O cache staff has been built, EEH is
  59. * ready to supply service.
  60. */
  61. static int powernv_eeh_post_init(void)
  62. {
  63. struct pci_controller *hose;
  64. struct pnv_phb *phb;
  65. int ret = 0;
  66. list_for_each_entry(hose, &hose_list, list_node) {
  67. phb = hose->private_data;
  68. if (phb->eeh_ops && phb->eeh_ops->post_init) {
  69. ret = phb->eeh_ops->post_init(hose);
  70. if (ret)
  71. break;
  72. }
  73. }
  74. return ret;
  75. }
  76. /**
  77. * powernv_eeh_dev_probe - Do probe on PCI device
  78. * @dev: PCI device
  79. * @flag: unused
  80. *
  81. * When EEH module is installed during system boot, all PCI devices
  82. * are checked one by one to see if it supports EEH. The function
  83. * is introduced for the purpose. By default, EEH has been enabled
  84. * on all PCI devices. That's to say, we only need do necessary
  85. * initialization on the corresponding eeh device and create PE
  86. * accordingly.
  87. *
  88. * It's notable that's unsafe to retrieve the EEH device through
  89. * the corresponding PCI device. During the PCI device hotplug, which
  90. * was possiblly triggered by EEH core, the binding between EEH device
  91. * and the PCI device isn't built yet.
  92. */
  93. static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
  94. {
  95. struct pci_controller *hose = pci_bus_to_host(dev->bus);
  96. struct pnv_phb *phb = hose->private_data;
  97. struct device_node *dn = pci_device_to_OF_node(dev);
  98. struct eeh_dev *edev = of_node_to_eeh_dev(dn);
  99. /*
  100. * When probing the root bridge, which doesn't have any
  101. * subordinate PCI devices. We don't have OF node for
  102. * the root bridge. So it's not reasonable to continue
  103. * the probing.
  104. */
  105. if (!dn || !edev || edev->pe)
  106. return 0;
  107. /* Skip for PCI-ISA bridge */
  108. if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
  109. return 0;
  110. /* Initialize eeh device */
  111. edev->class_code = dev->class;
  112. edev->mode &= 0xFFFFFF00;
  113. if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
  114. edev->mode |= EEH_DEV_BRIDGE;
  115. if (pci_is_pcie(dev)) {
  116. edev->pcie_cap = pci_pcie_cap(dev);
  117. if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
  118. edev->mode |= EEH_DEV_ROOT_PORT;
  119. else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
  120. edev->mode |= EEH_DEV_DS_PORT;
  121. }
  122. edev->config_addr = ((dev->bus->number << 8) | dev->devfn);
  123. edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff);
  124. /* Create PE */
  125. eeh_add_to_parent_pe(edev);
  126. /*
  127. * Enable EEH explicitly so that we will do EEH check
  128. * while accessing I/O stuff
  129. */
  130. eeh_subsystem_enabled = 1;
  131. /* Save memory bars */
  132. eeh_save_bars(edev);
  133. return 0;
  134. }
  135. /**
  136. * powernv_eeh_set_option - Initialize EEH or MMIO/DMA reenable
  137. * @pe: EEH PE
  138. * @option: operation to be issued
  139. *
  140. * The function is used to control the EEH functionality globally.
  141. * Currently, following options are support according to PAPR:
  142. * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
  143. */
  144. static int powernv_eeh_set_option(struct eeh_pe *pe, int option)
  145. {
  146. struct pci_controller *hose = pe->phb;
  147. struct pnv_phb *phb = hose->private_data;
  148. int ret = -EEXIST;
  149. /*
  150. * What we need do is pass it down for hardware
  151. * implementation to handle it.
  152. */
  153. if (phb->eeh_ops && phb->eeh_ops->set_option)
  154. ret = phb->eeh_ops->set_option(pe, option);
  155. return ret;
  156. }
  157. /**
  158. * powernv_eeh_get_pe_addr - Retrieve PE address
  159. * @pe: EEH PE
  160. *
  161. * Retrieve the PE address according to the given tranditional
  162. * PCI BDF (Bus/Device/Function) address.
  163. */
  164. static int powernv_eeh_get_pe_addr(struct eeh_pe *pe)
  165. {
  166. return pe->addr;
  167. }
  168. /**
  169. * powernv_eeh_get_state - Retrieve PE state
  170. * @pe: EEH PE
  171. * @delay: delay while PE state is temporarily unavailable
  172. *
  173. * Retrieve the state of the specified PE. For IODA-compitable
  174. * platform, it should be retrieved from IODA table. Therefore,
  175. * we prefer passing down to hardware implementation to handle
  176. * it.
  177. */
  178. static int powernv_eeh_get_state(struct eeh_pe *pe, int *delay)
  179. {
  180. struct pci_controller *hose = pe->phb;
  181. struct pnv_phb *phb = hose->private_data;
  182. int ret = EEH_STATE_NOT_SUPPORT;
  183. if (phb->eeh_ops && phb->eeh_ops->get_state) {
  184. ret = phb->eeh_ops->get_state(pe);
  185. /*
  186. * If the PE state is temporarily unavailable,
  187. * to inform the EEH core delay for default
  188. * period (1 second)
  189. */
  190. if (delay) {
  191. *delay = 0;
  192. if (ret & EEH_STATE_UNAVAILABLE)
  193. *delay = 1000;
  194. }
  195. }
  196. return ret;
  197. }
  198. /**
  199. * powernv_eeh_reset - Reset the specified PE
  200. * @pe: EEH PE
  201. * @option: reset option
  202. *
  203. * Reset the specified PE
  204. */
  205. static int powernv_eeh_reset(struct eeh_pe *pe, int option)
  206. {
  207. struct pci_controller *hose = pe->phb;
  208. struct pnv_phb *phb = hose->private_data;
  209. int ret = -EEXIST;
  210. if (phb->eeh_ops && phb->eeh_ops->reset)
  211. ret = phb->eeh_ops->reset(pe, option);
  212. return ret;
  213. }
  214. /**
  215. * powernv_eeh_wait_state - Wait for PE state
  216. * @pe: EEH PE
  217. * @max_wait: maximal period in microsecond
  218. *
  219. * Wait for the state of associated PE. It might take some time
  220. * to retrieve the PE's state.
  221. */
  222. static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait)
  223. {
  224. int ret;
  225. int mwait;
  226. while (1) {
  227. ret = powernv_eeh_get_state(pe, &mwait);
  228. /*
  229. * If the PE's state is temporarily unavailable,
  230. * we have to wait for the specified time. Otherwise,
  231. * the PE's state will be returned immediately.
  232. */
  233. if (ret != EEH_STATE_UNAVAILABLE)
  234. return ret;
  235. max_wait -= mwait;
  236. if (max_wait <= 0) {
  237. pr_warning("%s: Timeout getting PE#%x's state (%d)\n",
  238. __func__, pe->addr, max_wait);
  239. return EEH_STATE_NOT_SUPPORT;
  240. }
  241. msleep(mwait);
  242. }
  243. return EEH_STATE_NOT_SUPPORT;
  244. }
  245. /**
  246. * powernv_eeh_get_log - Retrieve error log
  247. * @pe: EEH PE
  248. * @severity: temporary or permanent error log
  249. * @drv_log: driver log to be combined with retrieved error log
  250. * @len: length of driver log
  251. *
  252. * Retrieve the temporary or permanent error from the PE.
  253. */
  254. static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
  255. char *drv_log, unsigned long len)
  256. {
  257. struct pci_controller *hose = pe->phb;
  258. struct pnv_phb *phb = hose->private_data;
  259. int ret = -EEXIST;
  260. if (phb->eeh_ops && phb->eeh_ops->get_log)
  261. ret = phb->eeh_ops->get_log(pe, severity, drv_log, len);
  262. return ret;
  263. }
  264. /**
  265. * powernv_eeh_configure_bridge - Configure PCI bridges in the indicated PE
  266. * @pe: EEH PE
  267. *
  268. * The function will be called to reconfigure the bridges included
  269. * in the specified PE so that the mulfunctional PE would be recovered
  270. * again.
  271. */
  272. static int powernv_eeh_configure_bridge(struct eeh_pe *pe)
  273. {
  274. struct pci_controller *hose = pe->phb;
  275. struct pnv_phb *phb = hose->private_data;
  276. int ret = 0;
  277. if (phb->eeh_ops && phb->eeh_ops->configure_bridge)
  278. ret = phb->eeh_ops->configure_bridge(pe);
  279. return ret;
  280. }
  281. /**
  282. * powernv_eeh_next_error - Retrieve next EEH error to handle
  283. * @pe: Affected PE
  284. *
  285. * Using OPAL API, to retrieve next EEH error for EEH core to handle
  286. */
  287. static int powernv_eeh_next_error(struct eeh_pe **pe)
  288. {
  289. struct pci_controller *hose;
  290. struct pnv_phb *phb = NULL;
  291. list_for_each_entry(hose, &hose_list, list_node) {
  292. phb = hose->private_data;
  293. break;
  294. }
  295. if (phb && phb->eeh_ops->next_error)
  296. return phb->eeh_ops->next_error(pe);
  297. return -EEXIST;
  298. }
  299. static struct eeh_ops powernv_eeh_ops = {
  300. .name = "powernv",
  301. .init = powernv_eeh_init,
  302. .post_init = powernv_eeh_post_init,
  303. .of_probe = NULL,
  304. .dev_probe = powernv_eeh_dev_probe,
  305. .set_option = powernv_eeh_set_option,
  306. .get_pe_addr = powernv_eeh_get_pe_addr,
  307. .get_state = powernv_eeh_get_state,
  308. .reset = powernv_eeh_reset,
  309. .wait_state = powernv_eeh_wait_state,
  310. .get_log = powernv_eeh_get_log,
  311. .configure_bridge = powernv_eeh_configure_bridge,
  312. .read_config = pnv_pci_cfg_read,
  313. .write_config = pnv_pci_cfg_write,
  314. .next_error = powernv_eeh_next_error
  315. };
  316. /**
  317. * eeh_powernv_init - Register platform dependent EEH operations
  318. *
  319. * EEH initialization on powernv platform. This function should be
  320. * called before any EEH related functions.
  321. */
  322. static int __init eeh_powernv_init(void)
  323. {
  324. int ret = -EINVAL;
  325. if (!machine_is(powernv))
  326. return ret;
  327. ret = eeh_ops_register(&powernv_eeh_ops);
  328. if (!ret)
  329. pr_info("EEH: PowerNV platform initialized\n");
  330. else
  331. pr_info("EEH: Failed to initialize PowerNV platform (%d)\n", ret);
  332. return ret;
  333. }
  334. early_initcall(eeh_powernv_init);