1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform. 4 * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com> 5 * 6 * All rights reserved. 7 * 8 * Send feedback to <lxie@us.ibm.com> 9 * 10 */ 11 #include <linux/of.h> 12 #include <linux/pci.h> 13 #include <linux/string.h> 14 15 #include <asm/pci-bridge.h> 16 #include <asm/rtas.h> 17 #include <asm/machdep.h> 18 19 #include "../pci.h" /* for pci_add_new_bus */ 20 #include "rpaphp.h" 21 22 /* 23 * RTAS call get-sensor-state(DR_ENTITY_SENSE) return values as per PAPR: 24 * -- generic return codes --- 25 * -1: Hardware Error 26 * -2: RTAS_BUSY 27 * -3: Invalid sensor. RTAS Parameter Error. 28 * -- rtas_get_sensor function specific return codes --- 29 * -9000: Need DR entity to be powered up and unisolated before RTAS call 30 * -9001: Need DR entity to be powered up, but not unisolated, before RTAS call 31 * -9002: DR entity unusable 32 * 990x: Extended delay - where x is a number in the range of 0-5 33 */ 34 #define RTAS_SLOT_UNISOLATED -9000 35 #define RTAS_SLOT_NOT_UNISOLATED -9001 36 #define RTAS_SLOT_NOT_USABLE -9002 37 38 static int rtas_get_sensor_errno(int rtas_rc) 39 { 40 switch (rtas_rc) { 41 case 0: 42 /* Success case */ 43 return 0; 44 case RTAS_SLOT_UNISOLATED: 45 case RTAS_SLOT_NOT_UNISOLATED: 46 return -EFAULT; 47 case RTAS_SLOT_NOT_USABLE: 48 return -ENODEV; 49 case RTAS_BUSY: 50 case RTAS_EXTENDED_DELAY_MIN...RTAS_EXTENDED_DELAY_MAX: 51 return -EBUSY; 52 default: 53 return rtas_error_rc(rtas_rc); 54 } 55 } 56 57 /* 58 * get_adapter_status() can be called by the EEH handler during EEH recovery. 59 * On certain PHB failures, the RTAS call rtas_call(get-sensor-state) returns 60 * extended busy error (9902) until PHB is recovered by pHyp. The RTAS call 61 * interface rtas_get_sensor() loops over the RTAS call on extended delay 62 * return code (9902) until the return value is either success (0) or error 63 * (-1). This causes the EEH handler to get stuck for ~6 seconds before it 64 * could notify that the PCI error has been detected and stop any active 65 * operations. This sometimes causes EEH recovery to fail. To avoid this issue, 66 * invoke rtas_call(get-sensor-state) directly if the respective PE is in EEH 67 * recovery state and return -EBUSY error based on RTAS return status. This 68 * will help the EEH handler to notify the driver about the PCI error 69 * immediately and successfully proceed with EEH recovery steps. 70 */ 71 72 static int __rpaphp_get_sensor_state(struct slot *slot, int *state) 73 { 74 int rc; 75 int token = rtas_token("get-sensor-state"); 76 struct pci_dn *pdn; 77 struct eeh_pe *pe; 78 struct pci_controller *phb = PCI_DN(slot->dn)->phb; 79 80 if (token == RTAS_UNKNOWN_SERVICE) 81 return -ENOENT; 82 83 /* 84 * Fallback to existing method for empty slot or PE isn't in EEH 85 * recovery. 86 */ 87 pdn = list_first_entry_or_null(&PCI_DN(phb->dn)->child_list, 88 struct pci_dn, list); 89 if (!pdn) 90 goto fallback; 91 92 pe = eeh_dev_to_pe(pdn->edev); 93 if (pe && (pe->state & EEH_PE_RECOVERING)) { 94 rc = rtas_call(token, 2, 2, state, DR_ENTITY_SENSE, 95 slot->index); 96 return rtas_get_sensor_errno(rc); 97 } 98 fallback: 99 return rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state); 100 } 101 102 int rpaphp_get_sensor_state(struct slot *slot, int *state) 103 { 104 int rc; 105 int setlevel; 106 107 rc = __rpaphp_get_sensor_state(slot, state); 108 109 if (rc < 0) { 110 if (rc == -EFAULT || rc == -EEXIST) { 111 dbg("%s: slot must be power up to get sensor-state\n", 112 __func__); 113 114 /* some slots have to be powered up 115 * before get-sensor will succeed. 116 */ 117 rc = rtas_set_power_level(slot->power_domain, POWER_ON, 118 &setlevel); 119 if (rc < 0) { 120 dbg("%s: power on slot[%s] failed rc=%d.\n", 121 __func__, slot->name, rc); 122 } else { 123 rc = __rpaphp_get_sensor_state(slot, state); 124 } 125 } else if (rc == -ENODEV) 126 info("%s: slot is unusable\n", __func__); 127 else 128 err("%s failed to get sensor state\n", __func__); 129 } 130 return rc; 131 } 132 133 /** 134 * rpaphp_enable_slot - record slot state, config pci device 135 * @slot: target &slot 136 * 137 * Initialize values in the slot structure to indicate if there is a pci card 138 * plugged into the slot. If the slot is not empty, run the pcibios routine 139 * to get pcibios stuff correctly set up. 140 */ 141 int rpaphp_enable_slot(struct slot *slot) 142 { 143 int rc, level, state; 144 struct pci_bus *bus; 145 146 slot->state = EMPTY; 147 148 /* Find out if the power is turned on for the slot */ 149 rc = rtas_get_power_level(slot->power_domain, &level); 150 if (rc) 151 return rc; 152 153 /* Figure out if there is an adapter in the slot */ 154 rc = rpaphp_get_sensor_state(slot, &state); 155 if (rc) 156 return rc; 157 158 bus = pci_find_bus_by_node(slot->dn); 159 if (!bus) { 160 err("%s: no pci_bus for dn %pOF\n", __func__, slot->dn); 161 return -EINVAL; 162 } 163 164 slot->bus = bus; 165 slot->pci_devs = &bus->devices; 166 167 /* if there's an adapter in the slot, go add the pci devices */ 168 if (state == PRESENT) { 169 slot->state = NOT_CONFIGURED; 170 171 /* non-empty slot has to have child */ 172 if (!slot->dn->child) { 173 err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 174 __func__, slot->name); 175 return -EINVAL; 176 } 177 178 if (list_empty(&bus->devices)) { 179 pseries_eeh_init_edev_recursive(PCI_DN(slot->dn)); 180 pci_hp_add_devices(bus); 181 } 182 183 if (!list_empty(&bus->devices)) { 184 slot->state = CONFIGURED; 185 } 186 187 if (rpaphp_debug) { 188 struct pci_dev *dev; 189 dbg("%s: pci_devs of slot[%pOF]\n", __func__, slot->dn); 190 list_for_each_entry(dev, &bus->devices, bus_list) 191 dbg("\t%s\n", pci_name(dev)); 192 } 193 } 194 195 return 0; 196 } 197