129310e5eSGavin Shan /* 229310e5eSGavin Shan * The file intends to implement the platform dependent EEH operations on 329310e5eSGavin Shan * powernv platform. Actually, the powernv was created in order to fully 429310e5eSGavin Shan * hypervisor support. 529310e5eSGavin Shan * 629310e5eSGavin Shan * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2013. 729310e5eSGavin Shan * 829310e5eSGavin Shan * This program is free software; you can redistribute it and/or modify 929310e5eSGavin Shan * it under the terms of the GNU General Public License as published by 1029310e5eSGavin Shan * the Free Software Foundation; either version 2 of the License, or 1129310e5eSGavin Shan * (at your option) any later version. 1229310e5eSGavin Shan */ 1329310e5eSGavin Shan 1429310e5eSGavin Shan #include <linux/atomic.h> 1529310e5eSGavin Shan #include <linux/delay.h> 1629310e5eSGavin Shan #include <linux/export.h> 1729310e5eSGavin Shan #include <linux/init.h> 1829310e5eSGavin Shan #include <linux/list.h> 1929310e5eSGavin Shan #include <linux/msi.h> 2029310e5eSGavin Shan #include <linux/of.h> 2129310e5eSGavin Shan #include <linux/pci.h> 2229310e5eSGavin Shan #include <linux/proc_fs.h> 2329310e5eSGavin Shan #include <linux/rbtree.h> 2429310e5eSGavin Shan #include <linux/sched.h> 2529310e5eSGavin Shan #include <linux/seq_file.h> 2629310e5eSGavin Shan #include <linux/spinlock.h> 2729310e5eSGavin Shan 2829310e5eSGavin Shan #include <asm/eeh.h> 2929310e5eSGavin Shan #include <asm/eeh_event.h> 3029310e5eSGavin Shan #include <asm/firmware.h> 3129310e5eSGavin Shan #include <asm/io.h> 3229310e5eSGavin Shan #include <asm/iommu.h> 3329310e5eSGavin Shan #include <asm/machdep.h> 3429310e5eSGavin Shan #include <asm/msi_bitmap.h> 3529310e5eSGavin Shan #include <asm/opal.h> 3629310e5eSGavin Shan #include <asm/ppc-pci.h> 3729310e5eSGavin Shan 3829310e5eSGavin Shan #include "powernv.h" 3929310e5eSGavin Shan #include "pci.h" 4029310e5eSGavin Shan 4129310e5eSGavin Shan /** 4201f3bfb7SGavin Shan * pnv_eeh_init - EEH platform dependent initialization 4329310e5eSGavin Shan * 4429310e5eSGavin Shan * EEH platform dependent initialization on powernv 4529310e5eSGavin Shan */ 4601f3bfb7SGavin Shan static int pnv_eeh_init(void) 4729310e5eSGavin Shan { 48dc561fb9SGavin Shan struct pci_controller *hose; 49dc561fb9SGavin Shan struct pnv_phb *phb; 50dc561fb9SGavin Shan 5129310e5eSGavin Shan /* We require OPALv3 */ 5229310e5eSGavin Shan if (!firmware_has_feature(FW_FEATURE_OPALv3)) { 530dae2743SGavin Shan pr_warn("%s: OPALv3 is required !\n", 540dae2743SGavin Shan __func__); 5529310e5eSGavin Shan return -EINVAL; 5629310e5eSGavin Shan } 5729310e5eSGavin Shan 5805b1721dSGavin Shan /* Set probe mode */ 5905b1721dSGavin Shan eeh_add_flag(EEH_PROBE_MODE_DEV); 6029310e5eSGavin Shan 61dc561fb9SGavin Shan /* 62dc561fb9SGavin Shan * P7IOC blocks PCI config access to frozen PE, but PHB3 63dc561fb9SGavin Shan * doesn't do that. So we have to selectively enable I/O 64dc561fb9SGavin Shan * prior to collecting error log. 65dc561fb9SGavin Shan */ 66dc561fb9SGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 67dc561fb9SGavin Shan phb = hose->private_data; 68dc561fb9SGavin Shan 69dc561fb9SGavin Shan if (phb->model == PNV_PHB_MODEL_P7IOC) 70dc561fb9SGavin Shan eeh_add_flag(EEH_ENABLE_IO_FOR_LOG); 712aa5cf9eSGavin Shan 722aa5cf9eSGavin Shan /* 732aa5cf9eSGavin Shan * PE#0 should be regarded as valid by EEH core 742aa5cf9eSGavin Shan * if it's not the reserved one. Currently, we 752aa5cf9eSGavin Shan * have the reserved PE#0 and PE#127 for PHB3 762aa5cf9eSGavin Shan * and P7IOC separately. So we should regard 772aa5cf9eSGavin Shan * PE#0 as valid for P7IOC. 782aa5cf9eSGavin Shan */ 792aa5cf9eSGavin Shan if (phb->ioda.reserved_pe != 0) 802aa5cf9eSGavin Shan eeh_add_flag(EEH_VALID_PE_ZERO); 812aa5cf9eSGavin Shan 82dc561fb9SGavin Shan break; 83dc561fb9SGavin Shan } 84dc561fb9SGavin Shan 8529310e5eSGavin Shan return 0; 8629310e5eSGavin Shan } 8729310e5eSGavin Shan 8829310e5eSGavin Shan /** 8901f3bfb7SGavin Shan * pnv_eeh_post_init - EEH platform dependent post initialization 9029310e5eSGavin Shan * 9129310e5eSGavin Shan * EEH platform dependent post initialization on powernv. When 9229310e5eSGavin Shan * the function is called, the EEH PEs and devices should have 9329310e5eSGavin Shan * been built. If the I/O cache staff has been built, EEH is 9429310e5eSGavin Shan * ready to supply service. 9529310e5eSGavin Shan */ 9601f3bfb7SGavin Shan static int pnv_eeh_post_init(void) 9729310e5eSGavin Shan { 9829310e5eSGavin Shan struct pci_controller *hose; 9929310e5eSGavin Shan struct pnv_phb *phb; 10029310e5eSGavin Shan int ret = 0; 10129310e5eSGavin Shan 10229310e5eSGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 10329310e5eSGavin Shan phb = hose->private_data; 10429310e5eSGavin Shan 10529310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->post_init) { 10629310e5eSGavin Shan ret = phb->eeh_ops->post_init(hose); 10729310e5eSGavin Shan if (ret) 10829310e5eSGavin Shan break; 10929310e5eSGavin Shan } 11029310e5eSGavin Shan } 11129310e5eSGavin Shan 11229310e5eSGavin Shan return ret; 11329310e5eSGavin Shan } 11429310e5eSGavin Shan 11529310e5eSGavin Shan /** 11601f3bfb7SGavin Shan * pnv_eeh_dev_probe - Do probe on PCI device 11729310e5eSGavin Shan * @dev: PCI device 11829310e5eSGavin Shan * @flag: unused 11929310e5eSGavin Shan * 12029310e5eSGavin Shan * When EEH module is installed during system boot, all PCI devices 12129310e5eSGavin Shan * are checked one by one to see if it supports EEH. The function 12229310e5eSGavin Shan * is introduced for the purpose. By default, EEH has been enabled 12329310e5eSGavin Shan * on all PCI devices. That's to say, we only need do necessary 12429310e5eSGavin Shan * initialization on the corresponding eeh device and create PE 12529310e5eSGavin Shan * accordingly. 12629310e5eSGavin Shan * 12729310e5eSGavin Shan * It's notable that's unsafe to retrieve the EEH device through 12829310e5eSGavin Shan * the corresponding PCI device. During the PCI device hotplug, which 12929310e5eSGavin Shan * was possiblly triggered by EEH core, the binding between EEH device 13029310e5eSGavin Shan * and the PCI device isn't built yet. 13129310e5eSGavin Shan */ 13201f3bfb7SGavin Shan static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) 13329310e5eSGavin Shan { 13429310e5eSGavin Shan struct pci_controller *hose = pci_bus_to_host(dev->bus); 13529310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 13629310e5eSGavin Shan struct device_node *dn = pci_device_to_OF_node(dev); 13729310e5eSGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 138dadcd6d6SMike Qiu int ret; 13929310e5eSGavin Shan 14029310e5eSGavin Shan /* 14129310e5eSGavin Shan * When probing the root bridge, which doesn't have any 14229310e5eSGavin Shan * subordinate PCI devices. We don't have OF node for 14329310e5eSGavin Shan * the root bridge. So it's not reasonable to continue 14429310e5eSGavin Shan * the probing. 14529310e5eSGavin Shan */ 146f5c57710SGavin Shan if (!dn || !edev || edev->pe) 14729310e5eSGavin Shan return 0; 14829310e5eSGavin Shan 14929310e5eSGavin Shan /* Skip for PCI-ISA bridge */ 15029310e5eSGavin Shan if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA) 15129310e5eSGavin Shan return 0; 15229310e5eSGavin Shan 15329310e5eSGavin Shan /* Initialize eeh device */ 15429310e5eSGavin Shan edev->class_code = dev->class; 155ab55d218SGavin Shan edev->mode &= 0xFFFFFF00; 1564b83bd45SGavin Shan if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) 1574b83bd45SGavin Shan edev->mode |= EEH_DEV_BRIDGE; 1582a18dfc6SGavin Shan edev->pcix_cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 1594b83bd45SGavin Shan if (pci_is_pcie(dev)) { 1604b83bd45SGavin Shan edev->pcie_cap = pci_pcie_cap(dev); 1614b83bd45SGavin Shan 1624b83bd45SGavin Shan if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) 1634b83bd45SGavin Shan edev->mode |= EEH_DEV_ROOT_PORT; 1644b83bd45SGavin Shan else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) 1654b83bd45SGavin Shan edev->mode |= EEH_DEV_DS_PORT; 1662a18dfc6SGavin Shan 1672a18dfc6SGavin Shan edev->aer_cap = pci_find_ext_capability(dev, 1682a18dfc6SGavin Shan PCI_EXT_CAP_ID_ERR); 1694b83bd45SGavin Shan } 1704b83bd45SGavin Shan 17129310e5eSGavin Shan edev->config_addr = ((dev->bus->number << 8) | dev->devfn); 17229310e5eSGavin Shan edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); 17329310e5eSGavin Shan 17429310e5eSGavin Shan /* Create PE */ 175dadcd6d6SMike Qiu ret = eeh_add_to_parent_pe(edev); 176dadcd6d6SMike Qiu if (ret) { 177dadcd6d6SMike Qiu pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", 178dadcd6d6SMike Qiu __func__, pci_name(dev), ret); 179dadcd6d6SMike Qiu return ret; 180dadcd6d6SMike Qiu } 181dadcd6d6SMike Qiu 182dadcd6d6SMike Qiu /* 183b6541db1SGavin Shan * If the PE contains any one of following adapters, the 184b6541db1SGavin Shan * PCI config space can't be accessed when dumping EEH log. 185b6541db1SGavin Shan * Otherwise, we will run into fenced PHB caused by shortage 186b6541db1SGavin Shan * of outbound credits in the adapter. The PCI config access 187b6541db1SGavin Shan * should be blocked until PE reset. MMIO access is dropped 188b6541db1SGavin Shan * by hardware certainly. In order to drop PCI config requests, 189b6541db1SGavin Shan * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which 190b6541db1SGavin Shan * will be checked in the backend for PE state retrival. If 191b6541db1SGavin Shan * the PE becomes frozen for the first time and the flag has 192b6541db1SGavin Shan * been set for the PE, we will set EEH_PE_CFG_BLOCKED for 193b6541db1SGavin Shan * that PE to block its config space. 194b6541db1SGavin Shan * 195b6541db1SGavin Shan * Broadcom Austin 4-ports NICs (14e4:1657) 196179ea48bSGavin Shan * Broadcom Shiner 2-ports 10G NICs (14e4:168e) 197b6541db1SGavin Shan */ 198179ea48bSGavin Shan if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || 199179ea48bSGavin Shan (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) 200b6541db1SGavin Shan edev->pe->state |= EEH_PE_CFG_RESTRICTED; 201b6541db1SGavin Shan 202b6541db1SGavin Shan /* 203dadcd6d6SMike Qiu * Cache the PE primary bus, which can't be fetched when 204dadcd6d6SMike Qiu * full hotplug is in progress. In that case, all child 205dadcd6d6SMike Qiu * PCI devices of the PE are expected to be removed prior 206dadcd6d6SMike Qiu * to PE reset. 207dadcd6d6SMike Qiu */ 208dadcd6d6SMike Qiu if (!edev->pe->bus) 209dadcd6d6SMike Qiu edev->pe->bus = dev->bus; 21029310e5eSGavin Shan 21129310e5eSGavin Shan /* 21229310e5eSGavin Shan * Enable EEH explicitly so that we will do EEH check 21329310e5eSGavin Shan * while accessing I/O stuff 21429310e5eSGavin Shan */ 21505b1721dSGavin Shan eeh_add_flag(EEH_ENABLED); 21629310e5eSGavin Shan 21729310e5eSGavin Shan /* Save memory bars */ 21829310e5eSGavin Shan eeh_save_bars(edev); 21929310e5eSGavin Shan 22029310e5eSGavin Shan return 0; 22129310e5eSGavin Shan } 22229310e5eSGavin Shan 22329310e5eSGavin Shan /** 22401f3bfb7SGavin Shan * pnv_eeh_set_option - Initialize EEH or MMIO/DMA reenable 22529310e5eSGavin Shan * @pe: EEH PE 22629310e5eSGavin Shan * @option: operation to be issued 22729310e5eSGavin Shan * 22829310e5eSGavin Shan * The function is used to control the EEH functionality globally. 22929310e5eSGavin Shan * Currently, following options are support according to PAPR: 23029310e5eSGavin Shan * Enable EEH, Disable EEH, Enable MMIO and Enable DMA 23129310e5eSGavin Shan */ 23201f3bfb7SGavin Shan static int pnv_eeh_set_option(struct eeh_pe *pe, int option) 23329310e5eSGavin Shan { 23429310e5eSGavin Shan struct pci_controller *hose = pe->phb; 23529310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 23629310e5eSGavin Shan int ret = -EEXIST; 23729310e5eSGavin Shan 23829310e5eSGavin Shan /* 23929310e5eSGavin Shan * What we need do is pass it down for hardware 24029310e5eSGavin Shan * implementation to handle it. 24129310e5eSGavin Shan */ 24229310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->set_option) 24329310e5eSGavin Shan ret = phb->eeh_ops->set_option(pe, option); 24429310e5eSGavin Shan 24529310e5eSGavin Shan return ret; 24629310e5eSGavin Shan } 24729310e5eSGavin Shan 24829310e5eSGavin Shan /** 24901f3bfb7SGavin Shan * pnv_eeh_get_pe_addr - Retrieve PE address 25029310e5eSGavin Shan * @pe: EEH PE 25129310e5eSGavin Shan * 25229310e5eSGavin Shan * Retrieve the PE address according to the given tranditional 25329310e5eSGavin Shan * PCI BDF (Bus/Device/Function) address. 25429310e5eSGavin Shan */ 25501f3bfb7SGavin Shan static int pnv_eeh_get_pe_addr(struct eeh_pe *pe) 25629310e5eSGavin Shan { 25729310e5eSGavin Shan return pe->addr; 25829310e5eSGavin Shan } 25929310e5eSGavin Shan 26029310e5eSGavin Shan /** 26101f3bfb7SGavin Shan * pnv_eeh_get_state - Retrieve PE state 26229310e5eSGavin Shan * @pe: EEH PE 26329310e5eSGavin Shan * @delay: delay while PE state is temporarily unavailable 26429310e5eSGavin Shan * 26529310e5eSGavin Shan * Retrieve the state of the specified PE. For IODA-compitable 26629310e5eSGavin Shan * platform, it should be retrieved from IODA table. Therefore, 26729310e5eSGavin Shan * we prefer passing down to hardware implementation to handle 26829310e5eSGavin Shan * it. 26929310e5eSGavin Shan */ 27001f3bfb7SGavin Shan static int pnv_eeh_get_state(struct eeh_pe *pe, int *delay) 27129310e5eSGavin Shan { 27229310e5eSGavin Shan struct pci_controller *hose = pe->phb; 27329310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 27429310e5eSGavin Shan int ret = EEH_STATE_NOT_SUPPORT; 27529310e5eSGavin Shan 27629310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->get_state) { 27729310e5eSGavin Shan ret = phb->eeh_ops->get_state(pe); 27829310e5eSGavin Shan 27929310e5eSGavin Shan /* 28029310e5eSGavin Shan * If the PE state is temporarily unavailable, 28129310e5eSGavin Shan * to inform the EEH core delay for default 28229310e5eSGavin Shan * period (1 second) 28329310e5eSGavin Shan */ 28429310e5eSGavin Shan if (delay) { 28529310e5eSGavin Shan *delay = 0; 28629310e5eSGavin Shan if (ret & EEH_STATE_UNAVAILABLE) 28729310e5eSGavin Shan *delay = 1000; 28829310e5eSGavin Shan } 28929310e5eSGavin Shan } 29029310e5eSGavin Shan 29129310e5eSGavin Shan return ret; 29229310e5eSGavin Shan } 29329310e5eSGavin Shan 29429310e5eSGavin Shan /** 29501f3bfb7SGavin Shan * pnv_eeh_reset - Reset the specified PE 29629310e5eSGavin Shan * @pe: EEH PE 29729310e5eSGavin Shan * @option: reset option 29829310e5eSGavin Shan * 29929310e5eSGavin Shan * Reset the specified PE 30029310e5eSGavin Shan */ 30101f3bfb7SGavin Shan static int pnv_eeh_reset(struct eeh_pe *pe, int option) 30229310e5eSGavin Shan { 30329310e5eSGavin Shan struct pci_controller *hose = pe->phb; 30429310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 30529310e5eSGavin Shan int ret = -EEXIST; 30629310e5eSGavin Shan 30729310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->reset) 30829310e5eSGavin Shan ret = phb->eeh_ops->reset(pe, option); 30929310e5eSGavin Shan 31029310e5eSGavin Shan return ret; 31129310e5eSGavin Shan } 31229310e5eSGavin Shan 31329310e5eSGavin Shan /** 31401f3bfb7SGavin Shan * pnv_eeh_wait_state - Wait for PE state 31529310e5eSGavin Shan * @pe: EEH PE 31629310e5eSGavin Shan * @max_wait: maximal period in microsecond 31729310e5eSGavin Shan * 31829310e5eSGavin Shan * Wait for the state of associated PE. It might take some time 31929310e5eSGavin Shan * to retrieve the PE's state. 32029310e5eSGavin Shan */ 32101f3bfb7SGavin Shan static int pnv_eeh_wait_state(struct eeh_pe *pe, int max_wait) 32229310e5eSGavin Shan { 32329310e5eSGavin Shan int ret; 32429310e5eSGavin Shan int mwait; 32529310e5eSGavin Shan 32629310e5eSGavin Shan while (1) { 32701f3bfb7SGavin Shan ret = pnv_eeh_get_state(pe, &mwait); 32829310e5eSGavin Shan 32929310e5eSGavin Shan /* 33029310e5eSGavin Shan * If the PE's state is temporarily unavailable, 33129310e5eSGavin Shan * we have to wait for the specified time. Otherwise, 33229310e5eSGavin Shan * the PE's state will be returned immediately. 33329310e5eSGavin Shan */ 33429310e5eSGavin Shan if (ret != EEH_STATE_UNAVAILABLE) 33529310e5eSGavin Shan return ret; 33629310e5eSGavin Shan 33729310e5eSGavin Shan max_wait -= mwait; 33829310e5eSGavin Shan if (max_wait <= 0) { 3390dae2743SGavin Shan pr_warn("%s: Timeout getting PE#%x's state (%d)\n", 34029310e5eSGavin Shan __func__, pe->addr, max_wait); 34129310e5eSGavin Shan return EEH_STATE_NOT_SUPPORT; 34229310e5eSGavin Shan } 34329310e5eSGavin Shan 34429310e5eSGavin Shan msleep(mwait); 34529310e5eSGavin Shan } 34629310e5eSGavin Shan 34729310e5eSGavin Shan return EEH_STATE_NOT_SUPPORT; 34829310e5eSGavin Shan } 34929310e5eSGavin Shan 35029310e5eSGavin Shan /** 35101f3bfb7SGavin Shan * pnv_eeh_get_log - Retrieve error log 35229310e5eSGavin Shan * @pe: EEH PE 35329310e5eSGavin Shan * @severity: temporary or permanent error log 35429310e5eSGavin Shan * @drv_log: driver log to be combined with retrieved error log 35529310e5eSGavin Shan * @len: length of driver log 35629310e5eSGavin Shan * 35729310e5eSGavin Shan * Retrieve the temporary or permanent error from the PE. 35829310e5eSGavin Shan */ 35901f3bfb7SGavin Shan static int pnv_eeh_get_log(struct eeh_pe *pe, int severity, 36029310e5eSGavin Shan char *drv_log, unsigned long len) 36129310e5eSGavin Shan { 36229310e5eSGavin Shan struct pci_controller *hose = pe->phb; 36329310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 36429310e5eSGavin Shan int ret = -EEXIST; 36529310e5eSGavin Shan 36629310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->get_log) 36729310e5eSGavin Shan ret = phb->eeh_ops->get_log(pe, severity, drv_log, len); 36829310e5eSGavin Shan 36929310e5eSGavin Shan return ret; 37029310e5eSGavin Shan } 37129310e5eSGavin Shan 37229310e5eSGavin Shan /** 37301f3bfb7SGavin Shan * pnv_eeh_configure_bridge - Configure PCI bridges in the indicated PE 37429310e5eSGavin Shan * @pe: EEH PE 37529310e5eSGavin Shan * 37629310e5eSGavin Shan * The function will be called to reconfigure the bridges included 37729310e5eSGavin Shan * in the specified PE so that the mulfunctional PE would be recovered 37829310e5eSGavin Shan * again. 37929310e5eSGavin Shan */ 38001f3bfb7SGavin Shan static int pnv_eeh_configure_bridge(struct eeh_pe *pe) 38129310e5eSGavin Shan { 38229310e5eSGavin Shan struct pci_controller *hose = pe->phb; 38329310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 38429310e5eSGavin Shan int ret = 0; 38529310e5eSGavin Shan 38629310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->configure_bridge) 38729310e5eSGavin Shan ret = phb->eeh_ops->configure_bridge(pe); 38829310e5eSGavin Shan 38929310e5eSGavin Shan return ret; 39029310e5eSGavin Shan } 39129310e5eSGavin Shan 39229310e5eSGavin Shan /** 39301f3bfb7SGavin Shan * pnv_pe_err_inject - Inject specified error to the indicated PE 394131c123aSGavin Shan * @pe: the indicated PE 395131c123aSGavin Shan * @type: error type 396131c123aSGavin Shan * @func: specific error type 397131c123aSGavin Shan * @addr: address 398131c123aSGavin Shan * @mask: address mask 399131c123aSGavin Shan * 400131c123aSGavin Shan * The routine is called to inject specified error, which is 401131c123aSGavin Shan * determined by @type and @func, to the indicated PE for 402131c123aSGavin Shan * testing purpose. 403131c123aSGavin Shan */ 40401f3bfb7SGavin Shan static int pnv_eeh_err_inject(struct eeh_pe *pe, int type, int func, 405131c123aSGavin Shan unsigned long addr, unsigned long mask) 406131c123aSGavin Shan { 407131c123aSGavin Shan struct pci_controller *hose = pe->phb; 408131c123aSGavin Shan struct pnv_phb *phb = hose->private_data; 409fa646c3cSGavin Shan s64 rc; 410131c123aSGavin Shan 411fa646c3cSGavin Shan /* Sanity check on error type */ 412fa646c3cSGavin Shan if (type != OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR && 413fa646c3cSGavin Shan type != OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) { 414fa646c3cSGavin Shan pr_warn("%s: Invalid error type %d\n", 415fa646c3cSGavin Shan __func__, type); 416fa646c3cSGavin Shan return -ERANGE; 417fa646c3cSGavin Shan } 418131c123aSGavin Shan 419fa646c3cSGavin Shan if (func < OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR || 420fa646c3cSGavin Shan func > OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET) { 421fa646c3cSGavin Shan pr_warn("%s: Invalid error function %d\n", 422fa646c3cSGavin Shan __func__, func); 423fa646c3cSGavin Shan return -ERANGE; 424fa646c3cSGavin Shan } 425fa646c3cSGavin Shan 426fa646c3cSGavin Shan /* Firmware supports error injection ? */ 427fa646c3cSGavin Shan if (!opal_check_token(OPAL_PCI_ERR_INJECT)) { 428fa646c3cSGavin Shan pr_warn("%s: Firmware doesn't support error injection\n", 429fa646c3cSGavin Shan __func__); 430fa646c3cSGavin Shan return -ENXIO; 431fa646c3cSGavin Shan } 432fa646c3cSGavin Shan 433fa646c3cSGavin Shan /* Do error injection */ 434fa646c3cSGavin Shan rc = opal_pci_err_inject(phb->opal_id, pe->addr, 435fa646c3cSGavin Shan type, func, addr, mask); 436fa646c3cSGavin Shan if (rc != OPAL_SUCCESS) { 437fa646c3cSGavin Shan pr_warn("%s: Failure %lld injecting error " 438fa646c3cSGavin Shan "%d-%d to PHB#%x-PE#%x\n", 439fa646c3cSGavin Shan __func__, rc, type, func, 440fa646c3cSGavin Shan hose->global_number, pe->addr); 441fa646c3cSGavin Shan return -EIO; 442fa646c3cSGavin Shan } 443fa646c3cSGavin Shan 444fa646c3cSGavin Shan return 0; 445131c123aSGavin Shan } 446131c123aSGavin Shan 44701f3bfb7SGavin Shan static inline bool pnv_eeh_cfg_blocked(struct device_node *dn) 448d2cfbcd7SGavin Shan { 449d2cfbcd7SGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 450d2cfbcd7SGavin Shan 451d2cfbcd7SGavin Shan if (!edev || !edev->pe) 452d2cfbcd7SGavin Shan return false; 453d2cfbcd7SGavin Shan 454d2cfbcd7SGavin Shan if (edev->pe->state & EEH_PE_CFG_BLOCKED) 455d2cfbcd7SGavin Shan return true; 456d2cfbcd7SGavin Shan 457d2cfbcd7SGavin Shan return false; 458d2cfbcd7SGavin Shan } 459d2cfbcd7SGavin Shan 46001f3bfb7SGavin Shan static int pnv_eeh_read_config(struct device_node *dn, 461d2cfbcd7SGavin Shan int where, int size, u32 *val) 462d2cfbcd7SGavin Shan { 46301f3bfb7SGavin Shan if (pnv_eeh_cfg_blocked(dn)) { 464d2cfbcd7SGavin Shan *val = 0xFFFFFFFF; 465d2cfbcd7SGavin Shan return PCIBIOS_SET_FAILED; 466d2cfbcd7SGavin Shan } 467d2cfbcd7SGavin Shan 468d2cfbcd7SGavin Shan return pnv_pci_cfg_read(dn, where, size, val); 469d2cfbcd7SGavin Shan } 470d2cfbcd7SGavin Shan 47101f3bfb7SGavin Shan static int pnv_eeh_write_config(struct device_node *dn, 472d2cfbcd7SGavin Shan int where, int size, u32 val) 473d2cfbcd7SGavin Shan { 47401f3bfb7SGavin Shan if (pnv_eeh_cfg_blocked(dn)) 475d2cfbcd7SGavin Shan return PCIBIOS_SET_FAILED; 476d2cfbcd7SGavin Shan 477d2cfbcd7SGavin Shan return pnv_pci_cfg_write(dn, where, size, val); 478d2cfbcd7SGavin Shan } 479d2cfbcd7SGavin Shan 480131c123aSGavin Shan /** 48101f3bfb7SGavin Shan * pnv_eeh_next_error - Retrieve next EEH error to handle 48229310e5eSGavin Shan * @pe: Affected PE 48329310e5eSGavin Shan * 48429310e5eSGavin Shan * Using OPAL API, to retrieve next EEH error for EEH core to handle 48529310e5eSGavin Shan */ 48601f3bfb7SGavin Shan static int pnv_eeh_next_error(struct eeh_pe **pe) 48729310e5eSGavin Shan { 48829310e5eSGavin Shan struct pci_controller *hose; 48929310e5eSGavin Shan struct pnv_phb *phb = NULL; 49029310e5eSGavin Shan 49129310e5eSGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 49229310e5eSGavin Shan phb = hose->private_data; 49329310e5eSGavin Shan break; 49429310e5eSGavin Shan } 49529310e5eSGavin Shan 49629310e5eSGavin Shan if (phb && phb->eeh_ops->next_error) 49729310e5eSGavin Shan return phb->eeh_ops->next_error(pe); 49829310e5eSGavin Shan 49929310e5eSGavin Shan return -EEXIST; 50029310e5eSGavin Shan } 50129310e5eSGavin Shan 50201f3bfb7SGavin Shan static int pnv_eeh_restore_config(struct device_node *dn) 5039be3beccSGavin Shan { 5049be3beccSGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 5059be3beccSGavin Shan struct pnv_phb *phb; 5069be3beccSGavin Shan s64 ret; 5079be3beccSGavin Shan 5089be3beccSGavin Shan if (!edev) 5099be3beccSGavin Shan return -EEXIST; 5109be3beccSGavin Shan 5119be3beccSGavin Shan phb = edev->phb->private_data; 5129be3beccSGavin Shan ret = opal_pci_reinit(phb->opal_id, 5139be3beccSGavin Shan OPAL_REINIT_PCI_DEV, edev->config_addr); 5149be3beccSGavin Shan if (ret) { 5159be3beccSGavin Shan pr_warn("%s: Can't reinit PCI dev 0x%x (%lld)\n", 5169be3beccSGavin Shan __func__, edev->config_addr, ret); 5179be3beccSGavin Shan return -EIO; 5189be3beccSGavin Shan } 5199be3beccSGavin Shan 5209be3beccSGavin Shan return 0; 5219be3beccSGavin Shan } 5229be3beccSGavin Shan 52301f3bfb7SGavin Shan static struct eeh_ops pnv_eeh_ops = { 52429310e5eSGavin Shan .name = "powernv", 52501f3bfb7SGavin Shan .init = pnv_eeh_init, 52601f3bfb7SGavin Shan .post_init = pnv_eeh_post_init, 52729310e5eSGavin Shan .of_probe = NULL, 52801f3bfb7SGavin Shan .dev_probe = pnv_eeh_dev_probe, 52901f3bfb7SGavin Shan .set_option = pnv_eeh_set_option, 53001f3bfb7SGavin Shan .get_pe_addr = pnv_eeh_get_pe_addr, 53101f3bfb7SGavin Shan .get_state = pnv_eeh_get_state, 53201f3bfb7SGavin Shan .reset = pnv_eeh_reset, 53301f3bfb7SGavin Shan .wait_state = pnv_eeh_wait_state, 53401f3bfb7SGavin Shan .get_log = pnv_eeh_get_log, 53501f3bfb7SGavin Shan .configure_bridge = pnv_eeh_configure_bridge, 53601f3bfb7SGavin Shan .err_inject = pnv_eeh_err_inject, 53701f3bfb7SGavin Shan .read_config = pnv_eeh_read_config, 53801f3bfb7SGavin Shan .write_config = pnv_eeh_write_config, 53901f3bfb7SGavin Shan .next_error = pnv_eeh_next_error, 54001f3bfb7SGavin Shan .restore_config = pnv_eeh_restore_config 54129310e5eSGavin Shan }; 54229310e5eSGavin Shan 54329310e5eSGavin Shan /** 54429310e5eSGavin Shan * eeh_powernv_init - Register platform dependent EEH operations 54529310e5eSGavin Shan * 54629310e5eSGavin Shan * EEH initialization on powernv platform. This function should be 54729310e5eSGavin Shan * called before any EEH related functions. 54829310e5eSGavin Shan */ 54929310e5eSGavin Shan static int __init eeh_powernv_init(void) 55029310e5eSGavin Shan { 55129310e5eSGavin Shan int ret = -EINVAL; 55229310e5eSGavin Shan 553bb593c00SGavin Shan eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE); 55401f3bfb7SGavin Shan ret = eeh_ops_register(&pnv_eeh_ops); 55529310e5eSGavin Shan if (!ret) 55629310e5eSGavin Shan pr_info("EEH: PowerNV platform initialized\n"); 55729310e5eSGavin Shan else 55829310e5eSGavin Shan pr_info("EEH: Failed to initialize PowerNV platform (%d)\n", ret); 55929310e5eSGavin Shan 56029310e5eSGavin Shan return ret; 56129310e5eSGavin Shan } 562b14726c5SMichael Ellerman machine_early_initcall(powernv, eeh_powernv_init); 563