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 2023 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 /* Definitions 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 taskqid_t hc_startup_sync; /* Startup synched? */ 242 pcie_hp_ops_t hc_ops; /* Platform specific ops */ 243 /* (Native, ACPI) */ 244 245 /* PCI Hotplug (SHPC) specific fields */ 246 uint32_t hc_num_slots_impl; /* # of HP Slots Implemented */ 247 uint32_t hc_num_slots_connected; /* # of HP Slots Connected */ 248 int hc_curr_bus_speed; /* Current Bus Speed */ 249 uint32_t hc_device_start; /* 1st PCI Device # */ 250 uint32_t hc_phys_start; /* 1st Phys Device # */ 251 uint32_t hc_device_increases; /* Device # Increases */ 252 boolean_t hc_arbiter_timeout; /* Got a Arb timeout IRQ */ 253 254 /* Register read/write ops for non-standard HPC (e.g: OPL) */ 255 pcie_hp_regops_t hc_regops; 256 257 /* Platform implementation specific data if any: ACPI, CK804,... */ 258 void *hc_misc_data; 259 }; 260 261 /* 262 * Control structure for tree walk during configure/unconfigure operation. 263 */ 264 typedef struct pcie_hp_cn_cfg_t { 265 void *slotp; 266 boolean_t flag; /* Flag to ignore errors */ 267 int rv; /* Return error code */ 268 dev_info_t *dip; /* dip at which the (first) */ 269 /* error occurred */ 270 void *cn_private; /* Connection specific data */ 271 } pcie_hp_cn_cfg_t; 272 273 /* 274 * arg for unregistering port of a pci bridge 275 */ 276 typedef struct pcie_hp_unreg_port { 277 /* pci bridge dip to which the port is associated */ 278 dev_info_t *nexus_dip; 279 /* 280 * Connector number of the physical slot whose dependent ports will be 281 * unregistered. If NULL, then all the ports of the pci bridge dip will 282 * be unregistered. 283 */ 284 int connector_num; 285 int rv; 286 } pcie_hp_unreg_port_t; 287 288 /* 289 * arg for getting a port's state 290 */ 291 typedef struct pcie_hp_port_state { 292 char *cn_name; 293 ddi_hp_cn_state_t cn_state; 294 int rv; 295 } pcie_hp_port_state_t; 296 297 /* hc_flags */ 298 #define PCIE_HP_INITIALIZED_FLAG (1 << 0) /* HPC initialized */ 299 /* 300 * These two flags are all related to initial synchronization. See 301 * uts/common/io/pciex/hotplug/pciehpc.c for more information. The first is used 302 * to track that this is required while the second indicates that it's actively 303 * occurring. 304 */ 305 #define PCIE_HP_SYNC_PENDING (1 << 1) 306 #define PCIE_HP_SYNC_RUNNING (1 << 2) 307 308 /* PCIe hotplug friendly functions */ 309 extern int pcie_hp_init(dev_info_t *dip, caddr_t arg); 310 extern int pcie_hp_uninit(dev_info_t *dip); 311 extern int pcie_hp_intr(dev_info_t *dip); 312 extern int pcie_hp_probe(pcie_hp_slot_t *slot_p); 313 extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p); 314 extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op, 315 void *arg, void *result); 316 extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device, 317 uint_t function); 318 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 319 int pci_dev); 320 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 321 int pci_dev); 322 extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev); 323 extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz, 324 nvlist_t **nvlp); 325 extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf, 326 size_t *packed_sz); 327 extern char *pcie_led_state_text(pcie_hp_led_state_t state); 328 extern char *pcie_slot_condition_text(ap_condition_t condition); 329 extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int); 330 extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int); 331 extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint, 332 dev_info_t *self, int kmflag); 333 334 #endif /* _KERNEL */ 335 336 #ifdef __cplusplus 337 } 338 #endif 339 340 #endif /* _SYS_PCIE_HP_H */ 341