eeh-powernv.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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. * FIXME: Enable that for PHB3 later
  131. */
  132. if (phb->type == PNV_PHB_IODA1)
  133. eeh_subsystem_enabled = 1;
  134. /* Save memory bars */
  135. eeh_save_bars(edev);
  136. return 0;
  137. }
  138. /**
  139. * powernv_eeh_set_option - Initialize EEH or MMIO/DMA reenable
  140. * @pe: EEH PE
  141. * @option: operation to be issued
  142. *
  143. * The function is used to control the EEH functionality globally.
  144. * Currently, following options are support according to PAPR:
  145. * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
  146. */
  147. static int powernv_eeh_set_option(struct eeh_pe *pe, int option)
  148. {
  149. struct pci_controller *hose = pe->phb;
  150. struct pnv_phb *phb = hose->private_data;
  151. int ret = -EEXIST;
  152. /*
  153. * What we need do is pass it down for hardware
  154. * implementation to handle it.
  155. */
  156. if (phb->eeh_ops && phb->eeh_ops->set_option)
  157. ret = phb->eeh_ops->set_option(pe, option);
  158. return ret;
  159. }
  160. /**
  161. * powernv_eeh_get_pe_addr - Retrieve PE address
  162. * @pe: EEH PE
  163. *
  164. * Retrieve the PE address according to the given tranditional
  165. * PCI BDF (Bus/Device/Function) address.
  166. */
  167. static int powernv_eeh_get_pe_addr(struct eeh_pe *pe)
  168. {
  169. return pe->addr;
  170. }
  171. /**
  172. * powernv_eeh_get_state - Retrieve PE state
  173. * @pe: EEH PE
  174. * @delay: delay while PE state is temporarily unavailable
  175. *
  176. * Retrieve the state of the specified PE. For IODA-compitable
  177. * platform, it should be retrieved from IODA table. Therefore,
  178. * we prefer passing down to hardware implementation to handle
  179. * it.
  180. */
  181. static int powernv_eeh_get_state(struct eeh_pe *pe, int *delay)
  182. {
  183. struct pci_controller *hose = pe->phb;
  184. struct pnv_phb *phb = hose->private_data;
  185. int ret = EEH_STATE_NOT_SUPPORT;
  186. if (phb->eeh_ops && phb->eeh_ops->get_state) {
  187. ret = phb->eeh_ops->get_state(pe);
  188. /*
  189. * If the PE state is temporarily unavailable,
  190. * to inform the EEH core delay for default
  191. * period (1 second)
  192. */
  193. if (delay) {
  194. *delay = 0;
  195. if (ret & EEH_STATE_UNAVAILABLE)
  196. *delay = 1000;
  197. }
  198. }
  199. return ret;
  200. }
  201. /**
  202. * powernv_eeh_reset - Reset the specified PE
  203. * @pe: EEH PE
  204. * @option: reset option
  205. *
  206. * Reset the specified PE
  207. */
  208. static int powernv_eeh_reset(struct eeh_pe *pe, int option)
  209. {
  210. struct pci_controller *hose = pe->phb;
  211. struct pnv_phb *phb = hose->private_data;
  212. int ret = -EEXIST;
  213. if (phb->eeh_ops && phb->eeh_ops->reset)
  214. ret = phb->eeh_ops->reset(pe, option);
  215. return ret;
  216. }
  217. /**
  218. * powernv_eeh_wait_state - Wait for PE state
  219. * @pe: EEH PE
  220. * @max_wait: maximal period in microsecond
  221. *
  222. * Wait for the state of associated PE. It might take some time
  223. * to retrieve the PE's state.
  224. */
  225. static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait)
  226. {
  227. int ret;
  228. int mwait;
  229. while (1) {
  230. ret = powernv_eeh_get_state(pe, &mwait);
  231. /*
  232. * If the PE's state is temporarily unavailable,
  233. * we have to wait for the specified time. Otherwise,
  234. * the PE's state will be returned immediately.
  235. */
  236. if (ret != EEH_STATE_UNAVAILABLE)
  237. return ret;
  238. max_wait -= mwait;
  239. if (max_wait <= 0) {
  240. pr_warning("%s: Timeout getting PE#%x's state (%d)\n",
  241. __func__, pe->addr, max_wait);
  242. return EEH_STATE_NOT_SUPPORT;
  243. }
  244. msleep(mwait);
  245. }
  246. return EEH_STATE_NOT_SUPPORT;
  247. }
  248. /**
  249. * powernv_eeh_get_log - Retrieve error log
  250. * @pe: EEH PE
  251. * @severity: temporary or permanent error log
  252. * @drv_log: driver log to be combined with retrieved error log
  253. * @len: length of driver log
  254. *
  255. * Retrieve the temporary or permanent error from the PE.
  256. */
  257. static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
  258. char *drv_log, unsigned long len)
  259. {
  260. struct pci_controller *hose = pe->phb;
  261. struct pnv_phb *phb = hose->private_data;
  262. int ret = -EEXIST;
  263. if (phb->eeh_ops && phb->eeh_ops->get_log)
  264. ret = phb->eeh_ops->get_log(pe, severity, drv_log, len);
  265. return ret;
  266. }
  267. /**
  268. * powernv_eeh_configure_bridge - Configure PCI bridges in the indicated PE
  269. * @pe: EEH PE
  270. *
  271. * The function will be called to reconfigure the bridges included
  272. * in the specified PE so that the mulfunctional PE would be recovered
  273. * again.
  274. */
  275. static int powernv_eeh_configure_bridge(struct eeh_pe *pe)
  276. {
  277. struct pci_controller *hose = pe->phb;
  278. struct pnv_phb *phb = hose->private_data;
  279. int ret = 0;
  280. if (phb->eeh_ops && phb->eeh_ops->configure_bridge)
  281. ret = phb->eeh_ops->configure_bridge(pe);
  282. return ret;
  283. }
  284. /**
  285. * powernv_eeh_next_error - Retrieve next EEH error to handle
  286. * @pe: Affected PE
  287. *
  288. * Using OPAL API, to retrieve next EEH error for EEH core to handle
  289. */
  290. static int powernv_eeh_next_error(struct eeh_pe **pe)
  291. {
  292. struct pci_controller *hose;
  293. struct pnv_phb *phb = NULL;
  294. list_for_each_entry(hose, &hose_list, list_node) {
  295. phb = hose->private_data;
  296. break;
  297. }
  298. if (phb && phb->eeh_ops->next_error)
  299. return phb->eeh_ops->next_error(pe);
  300. return -EEXIST;
  301. }
  302. static struct eeh_ops powernv_eeh_ops = {
  303. .name = "powernv",
  304. .init = powernv_eeh_init,
  305. .post_init = powernv_eeh_post_init,
  306. .of_probe = NULL,
  307. .dev_probe = powernv_eeh_dev_probe,
  308. .set_option = powernv_eeh_set_option,
  309. .get_pe_addr = powernv_eeh_get_pe_addr,
  310. .get_state = powernv_eeh_get_state,
  311. .reset = powernv_eeh_reset,
  312. .wait_state = powernv_eeh_wait_state,
  313. .get_log = powernv_eeh_get_log,
  314. .configure_bridge = powernv_eeh_configure_bridge,
  315. .read_config = pnv_pci_cfg_read,
  316. .write_config = pnv_pci_cfg_write,
  317. .next_error = powernv_eeh_next_error
  318. };
  319. /**
  320. * eeh_powernv_init - Register platform dependent EEH operations
  321. *
  322. * EEH initialization on powernv platform. This function should be
  323. * called before any EEH related functions.
  324. */
  325. static int __init eeh_powernv_init(void)
  326. {
  327. int ret = -EINVAL;
  328. if (!machine_is(powernv))
  329. return ret;
  330. ret = eeh_ops_register(&powernv_eeh_ops);
  331. if (!ret)
  332. pr_info("EEH: PowerNV platform initialized\n");
  333. else
  334. pr_info("EEH: Failed to initialize PowerNV platform (%d)\n", ret);
  335. return ret;
  336. }
  337. early_initcall(eeh_powernv_init);