1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2022 Oxide Computer Company 25 */ 26 27 #ifndef _SYS_PCIE_HP_H 28 #define _SYS_PCIE_HP_H 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #ifdef _KERNEL 35 #include <sys/ddi_hp.h> 36 #include <sys/pcie_impl.h> 37 #endif /* _KERNEL */ 38 #include "../../../../../common/pci/pci_strings.h" 39 #include <sys/hotplug/pci/pcihp.h> 40 41 #define PCIEHPC_PROP_HELP "help" 42 #define PCIEHPC_PROP_ALL "all" 43 #define PCIEHPC_PROP_LED_FAULT "fault_led" 44 #define PCIEHPC_PROP_LED_POWER "power_led" 45 #define PCIEHPC_PROP_LED_ATTN "attn_led" 46 #define PCIEHPC_PROP_LED_ACTIVE "active_led" 47 #define PCIEHPC_PROP_CARD_TYPE "card_type" 48 #define PCIEHPC_PROP_BOARD_TYPE "board_type" 49 #define PCIEHPC_PROP_SLOT_CONDITION "slot_condition" 50 51 #define PCIEHPC_PROP_VALUE_UNKNOWN "unknown" 52 #define PCIEHPC_PROP_VALUE_ON "on" 53 #define PCIEHPC_PROP_VALUE_OFF "off" 54 #define PCIEHPC_PROP_VALUE_BLINK "blink" 55 #define PCIEHPC_PROP_VALUE_PCIHOTPLUG "pci hotplug" 56 #define PCIEHPC_PROP_VALUE_OK "ok" 57 #define PCIEHPC_PROP_VALUE_FAILING "failing" 58 #define PCIEHPC_PROP_VALUE_FAILED "failed" 59 #define PCIEHPC_PROP_VALUE_UNUSABLE "unusable" 60 #define PCIEHPC_PROP_VALUE_LED "<on|off|blink>" 61 #define PCIEHPC_PROP_VALUE_TYPE "<type description>" 62 #define PCIEHPC_PROP_VALUE_CONDITION "<unknown|ok|failing|failed|unusable>" 63 64 /* condition */ 65 #define PCIEHPC_PROP_COND_OK "ok" 66 #define PCIEHPC_PROP_COND_FAILING "failing" 67 #define PCIEHPC_PROP_COND_FAILED "failed" 68 #define PCIEHPC_PROP_COND_UNUSABLE "unusable" 69 #define PCIEHPC_PROP_COND_UNKNOWN "unknown" 70 71 #ifdef _KERNEL 72 73 #define PCIE_HP_MAX_SLOTS 31 /* Max # of slots */ 74 #define PCIE_HP_CMD_WAIT_TIME 10000 /* Delay in microseconds */ 75 #define PCIE_HP_CMD_WAIT_RETRY 100 /* Max retry count */ 76 #define PCIE_HP_DLL_STATE_CHANGE_TIMEOUT 1 /* Timeout in seconds */ 77 #define PCIE_HP_POWER_GOOD_WAIT_TIME 220000 /* Wait time after issuing a */ 78 /* cmd to change slot state */ 79 80 /* definations for PCIEHPC/PCISHPC */ 81 #define PCIE_NATIVE_HP_TYPE "PCIe-Native" /* PCIe Native type */ 82 #define PCIE_ACPI_HP_TYPE "PCIe-ACPI" /* PCIe ACPI type */ 83 #define PCIE_PROP_HP_TYPE "PCIe-Proprietary" /* PCIe Prop type */ 84 #define PCIE_PCI_HP_TYPE "PCI-SHPC" /* PCI (SHPC) type */ 85 86 #define PCIE_GET_HP_CTRL(dip) \ 87 (pcie_hp_ctrl_t *)PCIE_DIP2BUS(dip)->bus_hp_ctrl 88 89 #define PCIE_SET_HP_CTRL(dip, ctrl_p) \ 90 (PCIE_DIP2BUS(dip)->bus_hp_ctrl) = (pcie_hp_ctrl_t *)ctrl_p 91 92 #define PCIE_IS_PCIE_HOTPLUG_CAPABLE(bus_p) \ 93 ((bus_p->bus_hp_sup_modes & PCIE_ACPI_HP_MODE) || \ 94 (bus_p->bus_hp_sup_modes & PCIE_NATIVE_HP_MODE)) 95 96 #define PCIE_IS_PCI_HOTPLUG_CAPABLE(bus_p) \ 97 (bus_p->bus_hp_sup_modes & PCIE_PCI_HP_MODE) 98 99 #define PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p) \ 100 ((bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE) || \ 101 (bus_p->bus_hp_curr_mode == PCIE_NATIVE_HP_MODE)) 102 103 #define PCIE_IS_PCI_HOTPLUG_ENABLED(bus_p) \ 104 (bus_p->bus_hp_curr_mode & PCIE_PCI_HP_MODE) 105 106 typedef struct pcie_hp_ctrl pcie_hp_ctrl_t; 107 typedef struct pcie_hp_slot pcie_hp_slot_t; 108 109 /* 110 * Maximum length of the string converted from the digital number of pci device 111 * number and function number, including the string's end mark. For example, 112 * device number 0 and function number 255 (ARI case), then the length is 113 * (1 + 3 + 1). 114 */ 115 #define PCIE_HP_DEV_FUNC_NUM_STRING_LEN 5 116 117 /* 118 * Length of the characters in a PCI port name. 119 * The format of the PCI port name is: pci.d,f where d is device number, f is 120 * function number. The constant string and characters are "pci." and ",". 121 */ 122 #define PCIE_HP_PORT_NAME_STRING_LEN 5 123 124 /* Platform specific ops (Native HP, ACPI, etc.) */ 125 typedef struct pcie_hp_ops { 126 /* initialize/setup hot plug controller hw */ 127 int (*init_hpc_hw)(pcie_hp_ctrl_t *ctrl_p); 128 129 /* uninitialize hot plug controller hw */ 130 int (*uninit_hpc_hw)(pcie_hp_ctrl_t *ctrl_p); 131 132 /* initialize slot information structure */ 133 int (*init_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p); 134 135 /* uninitialize slot information structure */ 136 int (*uninit_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p); 137 138 /* slot poweron */ 139 int (*poweron_hpc_slot)(pcie_hp_slot_t *slot_p, 140 ddi_hp_cn_state_t *result); 141 142 /* slot poweroff */ 143 /* uninitialize hot plug controller hw */ 144 int (*poweroff_hpc_slot)(pcie_hp_slot_t *slot_p, 145 ddi_hp_cn_state_t *result); 146 147 /* enable hot plug interrupts/events */ 148 int (*enable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p); 149 150 /* disable hot plug interrupts/events */ 151 int (*disable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p); 152 } pcie_hp_ops_t; 153 154 /* Slot occupant information structure */ 155 #define PCIE_HP_MAX_OCCUPANTS 128 156 typedef struct pcie_hp_occupant_info { 157 int i; 158 char *id[PCIE_HP_MAX_OCCUPANTS]; 159 } pcie_hp_occupant_info_t; 160 161 /* 162 * pcie_hp_led_t 163 * 164 * Type definitions for LED type 165 */ 166 typedef enum { 167 PCIE_HP_FAULT_LED, 168 PCIE_HP_POWER_LED, 169 PCIE_HP_ATTN_LED, 170 PCIE_HP_ACTIVE_LED 171 } pcie_hp_led_t; 172 173 /* 174 * pcie_hp_led_state_t 175 * 176 * Type definitions for LED state 177 */ 178 typedef enum { 179 PCIE_HP_LED_OFF, 180 PCIE_HP_LED_ON, 181 PCIE_HP_LED_BLINK 182 } pcie_hp_led_state_t; 183 184 /* 185 * PCI and PCI Express Hotplug slot structure 186 */ 187 struct pcie_hp_slot { 188 uint32_t hs_num; /* Logical slot number */ 189 uint32_t hs_phy_slot_num; /* Physical slot number */ 190 uint32_t hs_device_num; /* PCI device num for slot */ 191 uint16_t hs_minor; /* Minor num for this slot */ 192 ddi_hp_cn_info_t hs_info; /* Slot information */ 193 ddi_hp_cn_state_t hs_state; /* Slot state */ 194 195 pcie_hp_led_state_t hs_power_led_state; /* Power LED state */ 196 pcie_hp_led_state_t hs_attn_led_state; /* Attn LED state */ 197 pcie_hp_led_state_t hs_active_led_state; /* Active LED state */ 198 pcie_hp_led_state_t hs_fault_led_state; /* Fault LED state */ 199 200 ap_condition_t hs_condition; /* Condition of the slot. */ 201 /* For cfgadm condition. */ 202 203 /* Synchronization variable(s) for hot plug events */ 204 kcondvar_t hs_attn_btn_cv; /* ATTN button pressed intr */ 205 boolean_t hs_attn_btn_pending; 206 kthread_t *hs_attn_btn_threadp; /* ATTN button event thread */ 207 boolean_t hs_attn_btn_thread_exit; 208 kcondvar_t hs_dll_active_cv; /* DLL State Changed intr */ 209 210 pcie_hp_ctrl_t *hs_ctrl; /* Hotplug ctrl for this slot */ 211 }; 212 213 /* 214 * Register ops for read/write of non-standard HPC (e.g: OPL platform). 215 */ 216 typedef struct pcie_hp_regops { 217 uint_t (*get)(void *cookie, off_t offset); 218 uint_t (*put)(void *cookie, off_t offset, uint_t val); 219 void *cookie; 220 } pcie_hp_regops_t; 221 222 /* 223 * PCI and PCI Express Hotplug controller structure 224 */ 225 struct pcie_hp_ctrl { 226 dev_info_t *hc_dip; /* DIP for HP controller */ 227 kmutex_t hc_mutex; /* Mutex for this ctrl */ 228 uint_t hc_flags; /* Misc flags */ 229 230 /* Slot information */ 231 pcie_hp_slot_t *hc_slots[PCIE_HP_MAX_SLOTS]; /* Slot pointers */ 232 boolean_t hc_has_attn; /* Do we have attn btn? */ 233 boolean_t hc_has_mrl; /* Do we have MRL? */ 234 boolean_t hc_has_pwr; /* Do we have a power ctl? */ 235 kcondvar_t hc_cmd_comp_cv; /* Command Completion intr */ 236 boolean_t hc_cmd_pending; /* Command completion pending */ 237 238 /* PCI Express Hotplug specific fields */ 239 boolean_t hc_has_emi_lock; /* Do we have EMI Lock? */ 240 boolean_t hc_dll_active_rep; /* Report DLL DL_Active state */ 241 pcie_hp_ops_t hc_ops; /* Platform specific ops */ 242 /* (Native, ACPI) */ 243 244 /* PCI Hotplug (SHPC) specific fields */ 245 uint32_t hc_num_slots_impl; /* # of HP Slots Implemented */ 246 uint32_t hc_num_slots_connected; /* # of HP Slots Connected */ 247 int hc_curr_bus_speed; /* Current Bus Speed */ 248 uint32_t hc_device_start; /* 1st PCI Device # */ 249 uint32_t hc_phys_start; /* 1st Phys Device # */ 250 uint32_t hc_device_increases; /* Device # Increases */ 251 boolean_t hc_arbiter_timeout; /* Got a Arb timeout IRQ */ 252 253 /* Register read/write ops for non-standard HPC (e.g: OPL) */ 254 pcie_hp_regops_t hc_regops; 255 256 /* Platform implementation specific data if any: ACPI, CK804,... */ 257 void *hc_misc_data; 258 }; 259 260 /* 261 * Control structure for tree walk during configure/unconfigure operation. 262 */ 263 typedef struct pcie_hp_cn_cfg_t { 264 void *slotp; 265 boolean_t flag; /* Flag to ignore errors */ 266 int rv; /* Return error code */ 267 dev_info_t *dip; /* dip at which the (first) */ 268 /* error occurred */ 269 void *cn_private; /* Connection specific data */ 270 } pcie_hp_cn_cfg_t; 271 272 /* 273 * arg for unregistering port of a pci bridge 274 */ 275 typedef struct pcie_hp_unreg_port { 276 /* pci bridge dip to which the port is associated */ 277 dev_info_t *nexus_dip; 278 /* 279 * Connector number of the physical slot whose dependent ports will be 280 * unregistered. If NULL, then all the ports of the pci bridge dip will 281 * be unregistered. 282 */ 283 int connector_num; 284 int rv; 285 } pcie_hp_unreg_port_t; 286 287 /* 288 * arg for getting a port's state 289 */ 290 typedef struct pcie_hp_port_state { 291 char *cn_name; 292 ddi_hp_cn_state_t cn_state; 293 int rv; 294 } pcie_hp_port_state_t; 295 296 /* hc_flags */ 297 #define PCIE_HP_INITIALIZED_FLAG (1 << 0) /* HPC initialized */ 298 299 /* PCIe hotplug friendly functions */ 300 extern int pcie_hp_init(dev_info_t *dip, caddr_t arg); 301 extern int pcie_hp_uninit(dev_info_t *dip); 302 extern int pcie_hp_intr(dev_info_t *dip); 303 extern int pcie_hp_probe(pcie_hp_slot_t *slot_p); 304 extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p); 305 extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op, 306 void *arg, void *result); 307 extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device, 308 uint_t function); 309 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 310 int pci_dev); 311 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 312 int pci_dev); 313 extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev); 314 extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz, 315 nvlist_t **nvlp); 316 extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf, 317 size_t *packed_sz); 318 extern char *pcie_led_state_text(pcie_hp_led_state_t state); 319 extern char *pcie_slot_condition_text(ap_condition_t condition); 320 extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int); 321 extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int); 322 extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint, 323 dev_info_t *self, int kmflag); 324 325 extern const struct pci_class_strings_s class_pci[]; 326 extern int class_pci_items; 327 328 #endif /* _KERNEL */ 329 330 #ifdef __cplusplus 331 } 332 #endif 333 334 #endif /* _SYS_PCIE_HP_H */ 335