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> 154cf17445SGavin Shan #include <linux/debugfs.h> 1629310e5eSGavin Shan #include <linux/delay.h> 1729310e5eSGavin Shan #include <linux/export.h> 1829310e5eSGavin Shan #include <linux/init.h> 1929310e5eSGavin Shan #include <linux/list.h> 2029310e5eSGavin Shan #include <linux/msi.h> 2129310e5eSGavin Shan #include <linux/of.h> 2229310e5eSGavin Shan #include <linux/pci.h> 2329310e5eSGavin Shan #include <linux/proc_fs.h> 2429310e5eSGavin Shan #include <linux/rbtree.h> 2529310e5eSGavin Shan #include <linux/sched.h> 2629310e5eSGavin Shan #include <linux/seq_file.h> 2729310e5eSGavin Shan #include <linux/spinlock.h> 2829310e5eSGavin Shan 2929310e5eSGavin Shan #include <asm/eeh.h> 3029310e5eSGavin Shan #include <asm/eeh_event.h> 3129310e5eSGavin Shan #include <asm/firmware.h> 3229310e5eSGavin Shan #include <asm/io.h> 3329310e5eSGavin Shan #include <asm/iommu.h> 3429310e5eSGavin Shan #include <asm/machdep.h> 3529310e5eSGavin Shan #include <asm/msi_bitmap.h> 3629310e5eSGavin Shan #include <asm/opal.h> 3729310e5eSGavin Shan #include <asm/ppc-pci.h> 3829310e5eSGavin Shan 3929310e5eSGavin Shan #include "powernv.h" 4029310e5eSGavin Shan #include "pci.h" 4129310e5eSGavin Shan 424cf17445SGavin Shan static bool pnv_eeh_nb_init = false; 434cf17445SGavin Shan 4429310e5eSGavin Shan /** 4501f3bfb7SGavin Shan * pnv_eeh_init - EEH platform dependent initialization 4629310e5eSGavin Shan * 4729310e5eSGavin Shan * EEH platform dependent initialization on powernv 4829310e5eSGavin Shan */ 4901f3bfb7SGavin Shan static int pnv_eeh_init(void) 5029310e5eSGavin Shan { 51dc561fb9SGavin Shan struct pci_controller *hose; 52dc561fb9SGavin Shan struct pnv_phb *phb; 53dc561fb9SGavin Shan 5429310e5eSGavin Shan /* We require OPALv3 */ 5529310e5eSGavin Shan if (!firmware_has_feature(FW_FEATURE_OPALv3)) { 560dae2743SGavin Shan pr_warn("%s: OPALv3 is required !\n", 570dae2743SGavin Shan __func__); 5829310e5eSGavin Shan return -EINVAL; 5929310e5eSGavin Shan } 6029310e5eSGavin Shan 6105b1721dSGavin Shan /* Set probe mode */ 6205b1721dSGavin Shan eeh_add_flag(EEH_PROBE_MODE_DEV); 6329310e5eSGavin Shan 64dc561fb9SGavin Shan /* 65dc561fb9SGavin Shan * P7IOC blocks PCI config access to frozen PE, but PHB3 66dc561fb9SGavin Shan * doesn't do that. So we have to selectively enable I/O 67dc561fb9SGavin Shan * prior to collecting error log. 68dc561fb9SGavin Shan */ 69dc561fb9SGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 70dc561fb9SGavin Shan phb = hose->private_data; 71dc561fb9SGavin Shan 72dc561fb9SGavin Shan if (phb->model == PNV_PHB_MODEL_P7IOC) 73dc561fb9SGavin Shan eeh_add_flag(EEH_ENABLE_IO_FOR_LOG); 742aa5cf9eSGavin Shan 752aa5cf9eSGavin Shan /* 762aa5cf9eSGavin Shan * PE#0 should be regarded as valid by EEH core 772aa5cf9eSGavin Shan * if it's not the reserved one. Currently, we 782aa5cf9eSGavin Shan * have the reserved PE#0 and PE#127 for PHB3 792aa5cf9eSGavin Shan * and P7IOC separately. So we should regard 802aa5cf9eSGavin Shan * PE#0 as valid for P7IOC. 812aa5cf9eSGavin Shan */ 822aa5cf9eSGavin Shan if (phb->ioda.reserved_pe != 0) 832aa5cf9eSGavin Shan eeh_add_flag(EEH_VALID_PE_ZERO); 842aa5cf9eSGavin Shan 85dc561fb9SGavin Shan break; 86dc561fb9SGavin Shan } 87dc561fb9SGavin Shan 8829310e5eSGavin Shan return 0; 8929310e5eSGavin Shan } 9029310e5eSGavin Shan 914cf17445SGavin Shan static int pnv_eeh_event(struct notifier_block *nb, 924cf17445SGavin Shan unsigned long events, void *change) 934cf17445SGavin Shan { 944cf17445SGavin Shan uint64_t changed_evts = (uint64_t)change; 954cf17445SGavin Shan 964cf17445SGavin Shan /* 974cf17445SGavin Shan * We simply send special EEH event if EEH has 984cf17445SGavin Shan * been enabled, or clear pending events in 994cf17445SGavin Shan * case that we enable EEH soon 1004cf17445SGavin Shan */ 1014cf17445SGavin Shan if (!(changed_evts & OPAL_EVENT_PCI_ERROR) || 1024cf17445SGavin Shan !(events & OPAL_EVENT_PCI_ERROR)) 1034cf17445SGavin Shan return 0; 1044cf17445SGavin Shan 1054cf17445SGavin Shan if (eeh_enabled()) 1064cf17445SGavin Shan eeh_send_failure_event(NULL); 1074cf17445SGavin Shan else 1084cf17445SGavin Shan opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul); 1094cf17445SGavin Shan 1104cf17445SGavin Shan return 0; 1114cf17445SGavin Shan } 1124cf17445SGavin Shan 1134cf17445SGavin Shan static struct notifier_block pnv_eeh_nb = { 1144cf17445SGavin Shan .notifier_call = pnv_eeh_event, 1154cf17445SGavin Shan .next = NULL, 1164cf17445SGavin Shan .priority = 0 1174cf17445SGavin Shan }; 1184cf17445SGavin Shan 1194cf17445SGavin Shan #ifdef CONFIG_DEBUG_FS 1204cf17445SGavin Shan static ssize_t pnv_eeh_ei_write(struct file *filp, 1214cf17445SGavin Shan const char __user *user_buf, 1224cf17445SGavin Shan size_t count, loff_t *ppos) 1234cf17445SGavin Shan { 1244cf17445SGavin Shan struct pci_controller *hose = filp->private_data; 1254cf17445SGavin Shan struct eeh_dev *edev; 1264cf17445SGavin Shan struct eeh_pe *pe; 1274cf17445SGavin Shan int pe_no, type, func; 1284cf17445SGavin Shan unsigned long addr, mask; 1294cf17445SGavin Shan char buf[50]; 1304cf17445SGavin Shan int ret; 1314cf17445SGavin Shan 1324cf17445SGavin Shan if (!eeh_ops || !eeh_ops->err_inject) 1334cf17445SGavin Shan return -ENXIO; 1344cf17445SGavin Shan 1354cf17445SGavin Shan /* Copy over argument buffer */ 1364cf17445SGavin Shan ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count); 1374cf17445SGavin Shan if (!ret) 1384cf17445SGavin Shan return -EFAULT; 1394cf17445SGavin Shan 1404cf17445SGavin Shan /* Retrieve parameters */ 1414cf17445SGavin Shan ret = sscanf(buf, "%x:%x:%x:%lx:%lx", 1424cf17445SGavin Shan &pe_no, &type, &func, &addr, &mask); 1434cf17445SGavin Shan if (ret != 5) 1444cf17445SGavin Shan return -EINVAL; 1454cf17445SGavin Shan 1464cf17445SGavin Shan /* Retrieve PE */ 1474cf17445SGavin Shan edev = kzalloc(sizeof(*edev), GFP_KERNEL); 1484cf17445SGavin Shan if (!edev) 1494cf17445SGavin Shan return -ENOMEM; 1504cf17445SGavin Shan edev->phb = hose; 1514cf17445SGavin Shan edev->pe_config_addr = pe_no; 1524cf17445SGavin Shan pe = eeh_pe_get(edev); 1534cf17445SGavin Shan kfree(edev); 1544cf17445SGavin Shan if (!pe) 1554cf17445SGavin Shan return -ENODEV; 1564cf17445SGavin Shan 1574cf17445SGavin Shan /* Do error injection */ 1584cf17445SGavin Shan ret = eeh_ops->err_inject(pe, type, func, addr, mask); 1594cf17445SGavin Shan return ret < 0 ? ret : count; 1604cf17445SGavin Shan } 1614cf17445SGavin Shan 1624cf17445SGavin Shan static const struct file_operations pnv_eeh_ei_fops = { 1634cf17445SGavin Shan .open = simple_open, 1644cf17445SGavin Shan .llseek = no_llseek, 1654cf17445SGavin Shan .write = pnv_eeh_ei_write, 1664cf17445SGavin Shan }; 1674cf17445SGavin Shan 1684cf17445SGavin Shan static int pnv_eeh_dbgfs_set(void *data, int offset, u64 val) 1694cf17445SGavin Shan { 1704cf17445SGavin Shan struct pci_controller *hose = data; 1714cf17445SGavin Shan struct pnv_phb *phb = hose->private_data; 1724cf17445SGavin Shan 1734cf17445SGavin Shan out_be64(phb->regs + offset, val); 1744cf17445SGavin Shan return 0; 1754cf17445SGavin Shan } 1764cf17445SGavin Shan 1774cf17445SGavin Shan static int pnv_eeh_dbgfs_get(void *data, int offset, u64 *val) 1784cf17445SGavin Shan { 1794cf17445SGavin Shan struct pci_controller *hose = data; 1804cf17445SGavin Shan struct pnv_phb *phb = hose->private_data; 1814cf17445SGavin Shan 1824cf17445SGavin Shan *val = in_be64(phb->regs + offset); 1834cf17445SGavin Shan return 0; 1844cf17445SGavin Shan } 1854cf17445SGavin Shan 1864cf17445SGavin Shan static int pnv_eeh_outb_dbgfs_set(void *data, u64 val) 1874cf17445SGavin Shan { 1884cf17445SGavin Shan return pnv_eeh_dbgfs_set(data, 0xD10, val); 1894cf17445SGavin Shan } 1904cf17445SGavin Shan 1914cf17445SGavin Shan static int pnv_eeh_outb_dbgfs_get(void *data, u64 *val) 1924cf17445SGavin Shan { 1934cf17445SGavin Shan return pnv_eeh_dbgfs_get(data, 0xD10, val); 1944cf17445SGavin Shan } 1954cf17445SGavin Shan 1964cf17445SGavin Shan static int pnv_eeh_inbA_dbgfs_set(void *data, u64 val) 1974cf17445SGavin Shan { 1984cf17445SGavin Shan return pnv_eeh_dbgfs_set(data, 0xD90, val); 1994cf17445SGavin Shan } 2004cf17445SGavin Shan 2014cf17445SGavin Shan static int pnv_eeh_inbA_dbgfs_get(void *data, u64 *val) 2024cf17445SGavin Shan { 2034cf17445SGavin Shan return pnv_eeh_dbgfs_get(data, 0xD90, val); 2044cf17445SGavin Shan } 2054cf17445SGavin Shan 2064cf17445SGavin Shan static int pnv_eeh_inbB_dbgfs_set(void *data, u64 val) 2074cf17445SGavin Shan { 2084cf17445SGavin Shan return pnv_eeh_dbgfs_set(data, 0xE10, val); 2094cf17445SGavin Shan } 2104cf17445SGavin Shan 2114cf17445SGavin Shan static int pnv_eeh_inbB_dbgfs_get(void *data, u64 *val) 2124cf17445SGavin Shan { 2134cf17445SGavin Shan return pnv_eeh_dbgfs_get(data, 0xE10, val); 2144cf17445SGavin Shan } 2154cf17445SGavin Shan 2164cf17445SGavin Shan DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_outb_dbgfs_ops, pnv_eeh_outb_dbgfs_get, 2174cf17445SGavin Shan pnv_eeh_outb_dbgfs_set, "0x%llx\n"); 2184cf17445SGavin Shan DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbA_dbgfs_ops, pnv_eeh_inbA_dbgfs_get, 2194cf17445SGavin Shan pnv_eeh_inbA_dbgfs_set, "0x%llx\n"); 2204cf17445SGavin Shan DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbB_dbgfs_ops, pnv_eeh_inbB_dbgfs_get, 2214cf17445SGavin Shan pnv_eeh_inbB_dbgfs_set, "0x%llx\n"); 2224cf17445SGavin Shan #endif /* CONFIG_DEBUG_FS */ 2234cf17445SGavin Shan 22429310e5eSGavin Shan /** 22501f3bfb7SGavin Shan * pnv_eeh_post_init - EEH platform dependent post initialization 22629310e5eSGavin Shan * 22729310e5eSGavin Shan * EEH platform dependent post initialization on powernv. When 22829310e5eSGavin Shan * the function is called, the EEH PEs and devices should have 22929310e5eSGavin Shan * been built. If the I/O cache staff has been built, EEH is 23029310e5eSGavin Shan * ready to supply service. 23129310e5eSGavin Shan */ 23201f3bfb7SGavin Shan static int pnv_eeh_post_init(void) 23329310e5eSGavin Shan { 23429310e5eSGavin Shan struct pci_controller *hose; 23529310e5eSGavin Shan struct pnv_phb *phb; 23629310e5eSGavin Shan int ret = 0; 23729310e5eSGavin Shan 2384cf17445SGavin Shan /* Register OPAL event notifier */ 2394cf17445SGavin Shan if (!pnv_eeh_nb_init) { 2404cf17445SGavin Shan ret = opal_notifier_register(&pnv_eeh_nb); 2414cf17445SGavin Shan if (ret) { 2424cf17445SGavin Shan pr_warn("%s: Can't register OPAL event notifier (%d)\n", 2434cf17445SGavin Shan __func__, ret); 2444cf17445SGavin Shan return ret; 2454cf17445SGavin Shan } 2464cf17445SGavin Shan 2474cf17445SGavin Shan pnv_eeh_nb_init = true; 2484cf17445SGavin Shan } 2494cf17445SGavin Shan 25029310e5eSGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 25129310e5eSGavin Shan phb = hose->private_data; 25229310e5eSGavin Shan 2534cf17445SGavin Shan /* 2544cf17445SGavin Shan * If EEH is enabled, we're going to rely on that. 2554cf17445SGavin Shan * Otherwise, we restore to conventional mechanism 2564cf17445SGavin Shan * to clear frozen PE during PCI config access. 2574cf17445SGavin Shan */ 2584cf17445SGavin Shan if (eeh_enabled()) 2594cf17445SGavin Shan phb->flags |= PNV_PHB_FLAG_EEH; 2604cf17445SGavin Shan else 2614cf17445SGavin Shan phb->flags &= ~PNV_PHB_FLAG_EEH; 2624cf17445SGavin Shan 2634cf17445SGavin Shan /* Create debugfs entries */ 2644cf17445SGavin Shan #ifdef CONFIG_DEBUG_FS 2654cf17445SGavin Shan if (phb->has_dbgfs || !phb->dbgfs) 2664cf17445SGavin Shan continue; 2674cf17445SGavin Shan 2684cf17445SGavin Shan phb->has_dbgfs = 1; 2694cf17445SGavin Shan debugfs_create_file("err_injct", 0200, 2704cf17445SGavin Shan phb->dbgfs, hose, 2714cf17445SGavin Shan &pnv_eeh_ei_fops); 2724cf17445SGavin Shan 2734cf17445SGavin Shan debugfs_create_file("err_injct_outbound", 0600, 2744cf17445SGavin Shan phb->dbgfs, hose, 2754cf17445SGavin Shan &pnv_eeh_outb_dbgfs_ops); 2764cf17445SGavin Shan debugfs_create_file("err_injct_inboundA", 0600, 2774cf17445SGavin Shan phb->dbgfs, hose, 2784cf17445SGavin Shan &pnv_eeh_inbA_dbgfs_ops); 2794cf17445SGavin Shan debugfs_create_file("err_injct_inboundB", 0600, 2804cf17445SGavin Shan phb->dbgfs, hose, 2814cf17445SGavin Shan &pnv_eeh_inbB_dbgfs_ops); 2824cf17445SGavin Shan #endif /* CONFIG_DEBUG_FS */ 28329310e5eSGavin Shan } 2844cf17445SGavin Shan 28529310e5eSGavin Shan 28629310e5eSGavin Shan return ret; 28729310e5eSGavin Shan } 28829310e5eSGavin Shan 28929310e5eSGavin Shan /** 29001f3bfb7SGavin Shan * pnv_eeh_dev_probe - Do probe on PCI device 29129310e5eSGavin Shan * @dev: PCI device 29229310e5eSGavin Shan * @flag: unused 29329310e5eSGavin Shan * 29429310e5eSGavin Shan * When EEH module is installed during system boot, all PCI devices 29529310e5eSGavin Shan * are checked one by one to see if it supports EEH. The function 29629310e5eSGavin Shan * is introduced for the purpose. By default, EEH has been enabled 29729310e5eSGavin Shan * on all PCI devices. That's to say, we only need do necessary 29829310e5eSGavin Shan * initialization on the corresponding eeh device and create PE 29929310e5eSGavin Shan * accordingly. 30029310e5eSGavin Shan * 30129310e5eSGavin Shan * It's notable that's unsafe to retrieve the EEH device through 30229310e5eSGavin Shan * the corresponding PCI device. During the PCI device hotplug, which 30329310e5eSGavin Shan * was possiblly triggered by EEH core, the binding between EEH device 30429310e5eSGavin Shan * and the PCI device isn't built yet. 30529310e5eSGavin Shan */ 30601f3bfb7SGavin Shan static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) 30729310e5eSGavin Shan { 30829310e5eSGavin Shan struct pci_controller *hose = pci_bus_to_host(dev->bus); 30929310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 31029310e5eSGavin Shan struct device_node *dn = pci_device_to_OF_node(dev); 31129310e5eSGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 312dadcd6d6SMike Qiu int ret; 31329310e5eSGavin Shan 31429310e5eSGavin Shan /* 31529310e5eSGavin Shan * When probing the root bridge, which doesn't have any 31629310e5eSGavin Shan * subordinate PCI devices. We don't have OF node for 31729310e5eSGavin Shan * the root bridge. So it's not reasonable to continue 31829310e5eSGavin Shan * the probing. 31929310e5eSGavin Shan */ 320f5c57710SGavin Shan if (!dn || !edev || edev->pe) 32129310e5eSGavin Shan return 0; 32229310e5eSGavin Shan 32329310e5eSGavin Shan /* Skip for PCI-ISA bridge */ 32429310e5eSGavin Shan if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA) 32529310e5eSGavin Shan return 0; 32629310e5eSGavin Shan 32729310e5eSGavin Shan /* Initialize eeh device */ 32829310e5eSGavin Shan edev->class_code = dev->class; 329ab55d218SGavin Shan edev->mode &= 0xFFFFFF00; 3304b83bd45SGavin Shan if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) 3314b83bd45SGavin Shan edev->mode |= EEH_DEV_BRIDGE; 3322a18dfc6SGavin Shan edev->pcix_cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 3334b83bd45SGavin Shan if (pci_is_pcie(dev)) { 3344b83bd45SGavin Shan edev->pcie_cap = pci_pcie_cap(dev); 3354b83bd45SGavin Shan 3364b83bd45SGavin Shan if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) 3374b83bd45SGavin Shan edev->mode |= EEH_DEV_ROOT_PORT; 3384b83bd45SGavin Shan else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) 3394b83bd45SGavin Shan edev->mode |= EEH_DEV_DS_PORT; 3402a18dfc6SGavin Shan 3412a18dfc6SGavin Shan edev->aer_cap = pci_find_ext_capability(dev, 3422a18dfc6SGavin Shan PCI_EXT_CAP_ID_ERR); 3434b83bd45SGavin Shan } 3444b83bd45SGavin Shan 34529310e5eSGavin Shan edev->config_addr = ((dev->bus->number << 8) | dev->devfn); 34629310e5eSGavin Shan edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); 34729310e5eSGavin Shan 34829310e5eSGavin Shan /* Create PE */ 349dadcd6d6SMike Qiu ret = eeh_add_to_parent_pe(edev); 350dadcd6d6SMike Qiu if (ret) { 351dadcd6d6SMike Qiu pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", 352dadcd6d6SMike Qiu __func__, pci_name(dev), ret); 353dadcd6d6SMike Qiu return ret; 354dadcd6d6SMike Qiu } 355dadcd6d6SMike Qiu 356dadcd6d6SMike Qiu /* 357b6541db1SGavin Shan * If the PE contains any one of following adapters, the 358b6541db1SGavin Shan * PCI config space can't be accessed when dumping EEH log. 359b6541db1SGavin Shan * Otherwise, we will run into fenced PHB caused by shortage 360b6541db1SGavin Shan * of outbound credits in the adapter. The PCI config access 361b6541db1SGavin Shan * should be blocked until PE reset. MMIO access is dropped 362b6541db1SGavin Shan * by hardware certainly. In order to drop PCI config requests, 363b6541db1SGavin Shan * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which 364b6541db1SGavin Shan * will be checked in the backend for PE state retrival. If 365b6541db1SGavin Shan * the PE becomes frozen for the first time and the flag has 366b6541db1SGavin Shan * been set for the PE, we will set EEH_PE_CFG_BLOCKED for 367b6541db1SGavin Shan * that PE to block its config space. 368b6541db1SGavin Shan * 369b6541db1SGavin Shan * Broadcom Austin 4-ports NICs (14e4:1657) 370179ea48bSGavin Shan * Broadcom Shiner 2-ports 10G NICs (14e4:168e) 371b6541db1SGavin Shan */ 372179ea48bSGavin Shan if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || 373179ea48bSGavin Shan (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) 374b6541db1SGavin Shan edev->pe->state |= EEH_PE_CFG_RESTRICTED; 375b6541db1SGavin Shan 376b6541db1SGavin Shan /* 377dadcd6d6SMike Qiu * Cache the PE primary bus, which can't be fetched when 378dadcd6d6SMike Qiu * full hotplug is in progress. In that case, all child 379dadcd6d6SMike Qiu * PCI devices of the PE are expected to be removed prior 380dadcd6d6SMike Qiu * to PE reset. 381dadcd6d6SMike Qiu */ 382dadcd6d6SMike Qiu if (!edev->pe->bus) 383dadcd6d6SMike Qiu edev->pe->bus = dev->bus; 38429310e5eSGavin Shan 38529310e5eSGavin Shan /* 38629310e5eSGavin Shan * Enable EEH explicitly so that we will do EEH check 38729310e5eSGavin Shan * while accessing I/O stuff 38829310e5eSGavin Shan */ 38905b1721dSGavin Shan eeh_add_flag(EEH_ENABLED); 39029310e5eSGavin Shan 39129310e5eSGavin Shan /* Save memory bars */ 39229310e5eSGavin Shan eeh_save_bars(edev); 39329310e5eSGavin Shan 39429310e5eSGavin Shan return 0; 39529310e5eSGavin Shan } 39629310e5eSGavin Shan 39729310e5eSGavin Shan /** 39801f3bfb7SGavin Shan * pnv_eeh_set_option - Initialize EEH or MMIO/DMA reenable 39929310e5eSGavin Shan * @pe: EEH PE 40029310e5eSGavin Shan * @option: operation to be issued 40129310e5eSGavin Shan * 40229310e5eSGavin Shan * The function is used to control the EEH functionality globally. 40329310e5eSGavin Shan * Currently, following options are support according to PAPR: 40429310e5eSGavin Shan * Enable EEH, Disable EEH, Enable MMIO and Enable DMA 40529310e5eSGavin Shan */ 40601f3bfb7SGavin Shan static int pnv_eeh_set_option(struct eeh_pe *pe, int option) 40729310e5eSGavin Shan { 40829310e5eSGavin Shan struct pci_controller *hose = pe->phb; 40929310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 41029310e5eSGavin Shan int ret = -EEXIST; 41129310e5eSGavin Shan 41229310e5eSGavin Shan /* 41329310e5eSGavin Shan * What we need do is pass it down for hardware 41429310e5eSGavin Shan * implementation to handle it. 41529310e5eSGavin Shan */ 41629310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->set_option) 41729310e5eSGavin Shan ret = phb->eeh_ops->set_option(pe, option); 41829310e5eSGavin Shan 41929310e5eSGavin Shan return ret; 42029310e5eSGavin Shan } 42129310e5eSGavin Shan 42229310e5eSGavin Shan /** 42301f3bfb7SGavin Shan * pnv_eeh_get_pe_addr - Retrieve PE address 42429310e5eSGavin Shan * @pe: EEH PE 42529310e5eSGavin Shan * 42629310e5eSGavin Shan * Retrieve the PE address according to the given tranditional 42729310e5eSGavin Shan * PCI BDF (Bus/Device/Function) address. 42829310e5eSGavin Shan */ 42901f3bfb7SGavin Shan static int pnv_eeh_get_pe_addr(struct eeh_pe *pe) 43029310e5eSGavin Shan { 43129310e5eSGavin Shan return pe->addr; 43229310e5eSGavin Shan } 43329310e5eSGavin Shan 43429310e5eSGavin Shan /** 43501f3bfb7SGavin Shan * pnv_eeh_get_state - Retrieve PE state 43629310e5eSGavin Shan * @pe: EEH PE 43729310e5eSGavin Shan * @delay: delay while PE state is temporarily unavailable 43829310e5eSGavin Shan * 43929310e5eSGavin Shan * Retrieve the state of the specified PE. For IODA-compitable 44029310e5eSGavin Shan * platform, it should be retrieved from IODA table. Therefore, 44129310e5eSGavin Shan * we prefer passing down to hardware implementation to handle 44229310e5eSGavin Shan * it. 44329310e5eSGavin Shan */ 44401f3bfb7SGavin Shan static int pnv_eeh_get_state(struct eeh_pe *pe, int *delay) 44529310e5eSGavin Shan { 44629310e5eSGavin Shan struct pci_controller *hose = pe->phb; 44729310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 44829310e5eSGavin Shan int ret = EEH_STATE_NOT_SUPPORT; 44929310e5eSGavin Shan 45029310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->get_state) { 45129310e5eSGavin Shan ret = phb->eeh_ops->get_state(pe); 45229310e5eSGavin Shan 45329310e5eSGavin Shan /* 45429310e5eSGavin Shan * If the PE state is temporarily unavailable, 45529310e5eSGavin Shan * to inform the EEH core delay for default 45629310e5eSGavin Shan * period (1 second) 45729310e5eSGavin Shan */ 45829310e5eSGavin Shan if (delay) { 45929310e5eSGavin Shan *delay = 0; 46029310e5eSGavin Shan if (ret & EEH_STATE_UNAVAILABLE) 46129310e5eSGavin Shan *delay = 1000; 46229310e5eSGavin Shan } 46329310e5eSGavin Shan } 46429310e5eSGavin Shan 46529310e5eSGavin Shan return ret; 46629310e5eSGavin Shan } 46729310e5eSGavin Shan 46829310e5eSGavin Shan /** 46901f3bfb7SGavin Shan * pnv_eeh_reset - Reset the specified PE 47029310e5eSGavin Shan * @pe: EEH PE 47129310e5eSGavin Shan * @option: reset option 47229310e5eSGavin Shan * 47329310e5eSGavin Shan * Reset the specified PE 47429310e5eSGavin Shan */ 47501f3bfb7SGavin Shan static int pnv_eeh_reset(struct eeh_pe *pe, int option) 47629310e5eSGavin Shan { 47729310e5eSGavin Shan struct pci_controller *hose = pe->phb; 47829310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 47929310e5eSGavin Shan int ret = -EEXIST; 48029310e5eSGavin Shan 48129310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->reset) 48229310e5eSGavin Shan ret = phb->eeh_ops->reset(pe, option); 48329310e5eSGavin Shan 48429310e5eSGavin Shan return ret; 48529310e5eSGavin Shan } 48629310e5eSGavin Shan 48729310e5eSGavin Shan /** 48801f3bfb7SGavin Shan * pnv_eeh_wait_state - Wait for PE state 48929310e5eSGavin Shan * @pe: EEH PE 49029310e5eSGavin Shan * @max_wait: maximal period in microsecond 49129310e5eSGavin Shan * 49229310e5eSGavin Shan * Wait for the state of associated PE. It might take some time 49329310e5eSGavin Shan * to retrieve the PE's state. 49429310e5eSGavin Shan */ 49501f3bfb7SGavin Shan static int pnv_eeh_wait_state(struct eeh_pe *pe, int max_wait) 49629310e5eSGavin Shan { 49729310e5eSGavin Shan int ret; 49829310e5eSGavin Shan int mwait; 49929310e5eSGavin Shan 50029310e5eSGavin Shan while (1) { 50101f3bfb7SGavin Shan ret = pnv_eeh_get_state(pe, &mwait); 50229310e5eSGavin Shan 50329310e5eSGavin Shan /* 50429310e5eSGavin Shan * If the PE's state is temporarily unavailable, 50529310e5eSGavin Shan * we have to wait for the specified time. Otherwise, 50629310e5eSGavin Shan * the PE's state will be returned immediately. 50729310e5eSGavin Shan */ 50829310e5eSGavin Shan if (ret != EEH_STATE_UNAVAILABLE) 50929310e5eSGavin Shan return ret; 51029310e5eSGavin Shan 51129310e5eSGavin Shan max_wait -= mwait; 51229310e5eSGavin Shan if (max_wait <= 0) { 5130dae2743SGavin Shan pr_warn("%s: Timeout getting PE#%x's state (%d)\n", 51429310e5eSGavin Shan __func__, pe->addr, max_wait); 51529310e5eSGavin Shan return EEH_STATE_NOT_SUPPORT; 51629310e5eSGavin Shan } 51729310e5eSGavin Shan 51829310e5eSGavin Shan msleep(mwait); 51929310e5eSGavin Shan } 52029310e5eSGavin Shan 52129310e5eSGavin Shan return EEH_STATE_NOT_SUPPORT; 52229310e5eSGavin Shan } 52329310e5eSGavin Shan 52429310e5eSGavin Shan /** 52501f3bfb7SGavin Shan * pnv_eeh_get_log - Retrieve error log 52629310e5eSGavin Shan * @pe: EEH PE 52729310e5eSGavin Shan * @severity: temporary or permanent error log 52829310e5eSGavin Shan * @drv_log: driver log to be combined with retrieved error log 52929310e5eSGavin Shan * @len: length of driver log 53029310e5eSGavin Shan * 53129310e5eSGavin Shan * Retrieve the temporary or permanent error from the PE. 53229310e5eSGavin Shan */ 53301f3bfb7SGavin Shan static int pnv_eeh_get_log(struct eeh_pe *pe, int severity, 53429310e5eSGavin Shan char *drv_log, unsigned long len) 53529310e5eSGavin Shan { 53695edcdeaSGavin Shan if (!eeh_has_flag(EEH_EARLY_DUMP_LOG)) 53795edcdeaSGavin Shan pnv_pci_dump_phb_diag_data(pe->phb, pe->data); 53829310e5eSGavin Shan 53995edcdeaSGavin Shan return 0; 54029310e5eSGavin Shan } 54129310e5eSGavin Shan 54229310e5eSGavin Shan /** 54301f3bfb7SGavin Shan * pnv_eeh_configure_bridge - Configure PCI bridges in the indicated PE 54429310e5eSGavin Shan * @pe: EEH PE 54529310e5eSGavin Shan * 54629310e5eSGavin Shan * The function will be called to reconfigure the bridges included 54729310e5eSGavin Shan * in the specified PE so that the mulfunctional PE would be recovered 54829310e5eSGavin Shan * again. 54929310e5eSGavin Shan */ 55001f3bfb7SGavin Shan static int pnv_eeh_configure_bridge(struct eeh_pe *pe) 55129310e5eSGavin Shan { 55229310e5eSGavin Shan struct pci_controller *hose = pe->phb; 55329310e5eSGavin Shan struct pnv_phb *phb = hose->private_data; 55429310e5eSGavin Shan int ret = 0; 55529310e5eSGavin Shan 55629310e5eSGavin Shan if (phb->eeh_ops && phb->eeh_ops->configure_bridge) 55729310e5eSGavin Shan ret = phb->eeh_ops->configure_bridge(pe); 55829310e5eSGavin Shan 55929310e5eSGavin Shan return ret; 56029310e5eSGavin Shan } 56129310e5eSGavin Shan 56229310e5eSGavin Shan /** 56301f3bfb7SGavin Shan * pnv_pe_err_inject - Inject specified error to the indicated PE 564131c123aSGavin Shan * @pe: the indicated PE 565131c123aSGavin Shan * @type: error type 566131c123aSGavin Shan * @func: specific error type 567131c123aSGavin Shan * @addr: address 568131c123aSGavin Shan * @mask: address mask 569131c123aSGavin Shan * 570131c123aSGavin Shan * The routine is called to inject specified error, which is 571131c123aSGavin Shan * determined by @type and @func, to the indicated PE for 572131c123aSGavin Shan * testing purpose. 573131c123aSGavin Shan */ 57401f3bfb7SGavin Shan static int pnv_eeh_err_inject(struct eeh_pe *pe, int type, int func, 575131c123aSGavin Shan unsigned long addr, unsigned long mask) 576131c123aSGavin Shan { 577131c123aSGavin Shan struct pci_controller *hose = pe->phb; 578131c123aSGavin Shan struct pnv_phb *phb = hose->private_data; 579fa646c3cSGavin Shan s64 rc; 580131c123aSGavin Shan 581fa646c3cSGavin Shan /* Sanity check on error type */ 582fa646c3cSGavin Shan if (type != OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR && 583fa646c3cSGavin Shan type != OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) { 584fa646c3cSGavin Shan pr_warn("%s: Invalid error type %d\n", 585fa646c3cSGavin Shan __func__, type); 586fa646c3cSGavin Shan return -ERANGE; 587fa646c3cSGavin Shan } 588131c123aSGavin Shan 589fa646c3cSGavin Shan if (func < OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR || 590fa646c3cSGavin Shan func > OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET) { 591fa646c3cSGavin Shan pr_warn("%s: Invalid error function %d\n", 592fa646c3cSGavin Shan __func__, func); 593fa646c3cSGavin Shan return -ERANGE; 594fa646c3cSGavin Shan } 595fa646c3cSGavin Shan 596fa646c3cSGavin Shan /* Firmware supports error injection ? */ 597fa646c3cSGavin Shan if (!opal_check_token(OPAL_PCI_ERR_INJECT)) { 598fa646c3cSGavin Shan pr_warn("%s: Firmware doesn't support error injection\n", 599fa646c3cSGavin Shan __func__); 600fa646c3cSGavin Shan return -ENXIO; 601fa646c3cSGavin Shan } 602fa646c3cSGavin Shan 603fa646c3cSGavin Shan /* Do error injection */ 604fa646c3cSGavin Shan rc = opal_pci_err_inject(phb->opal_id, pe->addr, 605fa646c3cSGavin Shan type, func, addr, mask); 606fa646c3cSGavin Shan if (rc != OPAL_SUCCESS) { 607fa646c3cSGavin Shan pr_warn("%s: Failure %lld injecting error " 608fa646c3cSGavin Shan "%d-%d to PHB#%x-PE#%x\n", 609fa646c3cSGavin Shan __func__, rc, type, func, 610fa646c3cSGavin Shan hose->global_number, pe->addr); 611fa646c3cSGavin Shan return -EIO; 612fa646c3cSGavin Shan } 613fa646c3cSGavin Shan 614fa646c3cSGavin Shan return 0; 615131c123aSGavin Shan } 616131c123aSGavin Shan 61701f3bfb7SGavin Shan static inline bool pnv_eeh_cfg_blocked(struct device_node *dn) 618d2cfbcd7SGavin Shan { 619d2cfbcd7SGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 620d2cfbcd7SGavin Shan 621d2cfbcd7SGavin Shan if (!edev || !edev->pe) 622d2cfbcd7SGavin Shan return false; 623d2cfbcd7SGavin Shan 624d2cfbcd7SGavin Shan if (edev->pe->state & EEH_PE_CFG_BLOCKED) 625d2cfbcd7SGavin Shan return true; 626d2cfbcd7SGavin Shan 627d2cfbcd7SGavin Shan return false; 628d2cfbcd7SGavin Shan } 629d2cfbcd7SGavin Shan 63001f3bfb7SGavin Shan static int pnv_eeh_read_config(struct device_node *dn, 631d2cfbcd7SGavin Shan int where, int size, u32 *val) 632d2cfbcd7SGavin Shan { 63301f3bfb7SGavin Shan if (pnv_eeh_cfg_blocked(dn)) { 634d2cfbcd7SGavin Shan *val = 0xFFFFFFFF; 635d2cfbcd7SGavin Shan return PCIBIOS_SET_FAILED; 636d2cfbcd7SGavin Shan } 637d2cfbcd7SGavin Shan 638d2cfbcd7SGavin Shan return pnv_pci_cfg_read(dn, where, size, val); 639d2cfbcd7SGavin Shan } 640d2cfbcd7SGavin Shan 64101f3bfb7SGavin Shan static int pnv_eeh_write_config(struct device_node *dn, 642d2cfbcd7SGavin Shan int where, int size, u32 val) 643d2cfbcd7SGavin Shan { 64401f3bfb7SGavin Shan if (pnv_eeh_cfg_blocked(dn)) 645d2cfbcd7SGavin Shan return PCIBIOS_SET_FAILED; 646d2cfbcd7SGavin Shan 647d2cfbcd7SGavin Shan return pnv_pci_cfg_write(dn, where, size, val); 648d2cfbcd7SGavin Shan } 649d2cfbcd7SGavin Shan 650131c123aSGavin Shan /** 65101f3bfb7SGavin Shan * pnv_eeh_next_error - Retrieve next EEH error to handle 65229310e5eSGavin Shan * @pe: Affected PE 65329310e5eSGavin Shan * 65429310e5eSGavin Shan * Using OPAL API, to retrieve next EEH error for EEH core to handle 65529310e5eSGavin Shan */ 65601f3bfb7SGavin Shan static int pnv_eeh_next_error(struct eeh_pe **pe) 65729310e5eSGavin Shan { 65829310e5eSGavin Shan struct pci_controller *hose; 65929310e5eSGavin Shan struct pnv_phb *phb = NULL; 66029310e5eSGavin Shan 66129310e5eSGavin Shan list_for_each_entry(hose, &hose_list, list_node) { 66229310e5eSGavin Shan phb = hose->private_data; 66329310e5eSGavin Shan break; 66429310e5eSGavin Shan } 66529310e5eSGavin Shan 66629310e5eSGavin Shan if (phb && phb->eeh_ops->next_error) 66729310e5eSGavin Shan return phb->eeh_ops->next_error(pe); 66829310e5eSGavin Shan 66929310e5eSGavin Shan return -EEXIST; 67029310e5eSGavin Shan } 67129310e5eSGavin Shan 67201f3bfb7SGavin Shan static int pnv_eeh_restore_config(struct device_node *dn) 6739be3beccSGavin Shan { 6749be3beccSGavin Shan struct eeh_dev *edev = of_node_to_eeh_dev(dn); 6759be3beccSGavin Shan struct pnv_phb *phb; 6769be3beccSGavin Shan s64 ret; 6779be3beccSGavin Shan 6789be3beccSGavin Shan if (!edev) 6799be3beccSGavin Shan return -EEXIST; 6809be3beccSGavin Shan 6819be3beccSGavin Shan phb = edev->phb->private_data; 6829be3beccSGavin Shan ret = opal_pci_reinit(phb->opal_id, 6839be3beccSGavin Shan OPAL_REINIT_PCI_DEV, edev->config_addr); 6849be3beccSGavin Shan if (ret) { 6859be3beccSGavin Shan pr_warn("%s: Can't reinit PCI dev 0x%x (%lld)\n", 6869be3beccSGavin Shan __func__, edev->config_addr, ret); 6879be3beccSGavin Shan return -EIO; 6889be3beccSGavin Shan } 6899be3beccSGavin Shan 6909be3beccSGavin Shan return 0; 6919be3beccSGavin Shan } 6929be3beccSGavin Shan 69301f3bfb7SGavin Shan static struct eeh_ops pnv_eeh_ops = { 69429310e5eSGavin Shan .name = "powernv", 69501f3bfb7SGavin Shan .init = pnv_eeh_init, 69601f3bfb7SGavin Shan .post_init = pnv_eeh_post_init, 69729310e5eSGavin Shan .of_probe = NULL, 69801f3bfb7SGavin Shan .dev_probe = pnv_eeh_dev_probe, 69901f3bfb7SGavin Shan .set_option = pnv_eeh_set_option, 70001f3bfb7SGavin Shan .get_pe_addr = pnv_eeh_get_pe_addr, 70101f3bfb7SGavin Shan .get_state = pnv_eeh_get_state, 70201f3bfb7SGavin Shan .reset = pnv_eeh_reset, 70301f3bfb7SGavin Shan .wait_state = pnv_eeh_wait_state, 70401f3bfb7SGavin Shan .get_log = pnv_eeh_get_log, 70501f3bfb7SGavin Shan .configure_bridge = pnv_eeh_configure_bridge, 70601f3bfb7SGavin Shan .err_inject = pnv_eeh_err_inject, 70701f3bfb7SGavin Shan .read_config = pnv_eeh_read_config, 70801f3bfb7SGavin Shan .write_config = pnv_eeh_write_config, 70901f3bfb7SGavin Shan .next_error = pnv_eeh_next_error, 71001f3bfb7SGavin Shan .restore_config = pnv_eeh_restore_config 71129310e5eSGavin Shan }; 71229310e5eSGavin Shan 71329310e5eSGavin Shan /** 71429310e5eSGavin Shan * eeh_powernv_init - Register platform dependent EEH operations 71529310e5eSGavin Shan * 71629310e5eSGavin Shan * EEH initialization on powernv platform. This function should be 71729310e5eSGavin Shan * called before any EEH related functions. 71829310e5eSGavin Shan */ 71929310e5eSGavin Shan static int __init eeh_powernv_init(void) 72029310e5eSGavin Shan { 72129310e5eSGavin Shan int ret = -EINVAL; 72229310e5eSGavin Shan 723bb593c00SGavin Shan eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE); 72401f3bfb7SGavin Shan ret = eeh_ops_register(&pnv_eeh_ops); 72529310e5eSGavin Shan if (!ret) 72629310e5eSGavin Shan pr_info("EEH: PowerNV platform initialized\n"); 72729310e5eSGavin Shan else 72829310e5eSGavin Shan pr_info("EEH: Failed to initialize PowerNV platform (%d)\n", ret); 72929310e5eSGavin Shan 73029310e5eSGavin Shan return ret; 73129310e5eSGavin Shan } 732b14726c5SMichael Ellerman machine_early_initcall(powernv, eeh_powernv_init); 733