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 2024 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 #include <sys/stdbool.h> 38 #endif /* _KERNEL */ 39 #include "../../../../../common/pci/pci_strings.h" 40 #include <sys/hotplug/pci/pcihp.h> 41 42 #define PCIEHPC_PROP_HELP "help" 43 #define PCIEHPC_PROP_ALL "all" 44 #define PCIEHPC_PROP_LED_FAULT "fault_led" 45 #define PCIEHPC_PROP_LED_POWER "power_led" 46 #define PCIEHPC_PROP_LED_ATTN "attn_led" 47 #define PCIEHPC_PROP_LED_ACTIVE "active_led" 48 #define PCIEHPC_PROP_CARD_TYPE "card_type" 49 #define PCIEHPC_PROP_BOARD_TYPE "board_type" 50 #define PCIEHPC_PROP_SLOT_CONDITION "slot_condition" 51 52 #define PCIEHPC_PROP_VALUE_UNKNOWN "unknown" 53 #define PCIEHPC_PROP_VALUE_ON "on" 54 #define PCIEHPC_PROP_VALUE_OFF "off" 55 #define PCIEHPC_PROP_VALUE_BLINK "blink" 56 #define PCIEHPC_PROP_VALUE_DEFAULT "default" 57 #define PCIEHPC_PROP_VALUE_PCIHOTPLUG "pci hotplug" 58 #define PCIEHPC_PROP_VALUE_OK "ok" 59 #define PCIEHPC_PROP_VALUE_FAILING "failing" 60 #define PCIEHPC_PROP_VALUE_FAILED "failed" 61 #define PCIEHPC_PROP_VALUE_UNUSABLE "unusable" 62 #define PCIEHPC_PROP_VALUE_LED "<on|off|blink>" 63 #define PCIEHPC_PROP_VALUE_LED_DEF "<on|off|blink|default>" 64 #define PCIEHPC_PROP_VALUE_TYPE "<type description>" 65 #define PCIEHPC_PROP_VALUE_CONDITION "<unknown|ok|failing|failed|unusable>" 66 67 /* condition */ 68 #define PCIEHPC_PROP_COND_OK "ok" 69 #define PCIEHPC_PROP_COND_FAILING "failing" 70 #define PCIEHPC_PROP_COND_FAILED "failed" 71 #define PCIEHPC_PROP_COND_UNUSABLE "unusable" 72 #define PCIEHPC_PROP_COND_UNKNOWN "unknown" 73 74 #ifdef _KERNEL 75 76 #define PCIE_HP_MAX_SLOTS 31 /* Max # of slots */ 77 #define PCIE_HP_CMD_WAIT_TIME 10000 /* Delay in microseconds */ 78 #define PCIE_HP_CMD_WAIT_RETRY 100 /* Max retry count */ 79 #define PCIE_HP_DLL_STATE_CHANGE_TIMEOUT 1 /* Timeout in seconds */ 80 #define PCIE_HP_POWER_GOOD_WAIT_TIME 220000 /* Wait time after issuing a */ 81 /* cmd to change slot state */ 82 83 /* Definitions for PCIEHPC/PCISHPC */ 84 #define PCIE_NATIVE_HP_TYPE "PCIe-Native" /* PCIe Native type */ 85 #define PCIE_ACPI_HP_TYPE "PCIe-ACPI" /* PCIe ACPI type */ 86 #define PCIE_PROP_HP_TYPE "PCIe-Proprietary" /* PCIe Prop type */ 87 #define PCIE_PCI_HP_TYPE "PCI-SHPC" /* PCI (SHPC) type */ 88 89 #define PCIE_GET_HP_CTRL(dip) \ 90 (pcie_hp_ctrl_t *)PCIE_DIP2BUS(dip)->bus_hp_ctrl 91 92 #define PCIE_SET_HP_CTRL(dip, ctrl_p) \ 93 (PCIE_DIP2BUS(dip)->bus_hp_ctrl) = (pcie_hp_ctrl_t *)ctrl_p 94 95 #define PCIE_IS_PCIE_HOTPLUG_CAPABLE(bus_p) \ 96 ((bus_p->bus_hp_sup_modes & PCIE_ACPI_HP_MODE) || \ 97 (bus_p->bus_hp_sup_modes & PCIE_NATIVE_HP_MODE)) 98 99 #define PCIE_IS_PCI_HOTPLUG_CAPABLE(bus_p) \ 100 (bus_p->bus_hp_sup_modes & PCIE_PCI_HP_MODE) 101 102 #define PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p) \ 103 ((bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE) || \ 104 (bus_p->bus_hp_curr_mode == PCIE_NATIVE_HP_MODE)) 105 106 #define PCIE_IS_PCI_HOTPLUG_ENABLED(bus_p) \ 107 (bus_p->bus_hp_curr_mode & PCIE_PCI_HP_MODE) 108 109 typedef struct pcie_hp_ctrl pcie_hp_ctrl_t; 110 typedef struct pcie_hp_slot pcie_hp_slot_t; 111 112 /* 113 * Maximum length of the string converted from the digital number of pci device 114 * number and function number, including the string's end mark. For example, 115 * device number 0 and function number 255 (ARI case), then the length is 116 * (1 + 3 + 1). 117 */ 118 #define PCIE_HP_DEV_FUNC_NUM_STRING_LEN 5 119 120 /* 121 * Length of the characters in a PCI port name. 122 * The format of the PCI port name is: pci.d,f where d is device number, f is 123 * function number. The constant string and characters are "pci." and ",". 124 */ 125 #define PCIE_HP_PORT_NAME_STRING_LEN 5 126 127 /* Platform specific ops (Native HP, ACPI, etc.) */ 128 typedef struct pcie_hp_ops { 129 /* initialize/setup hot plug controller hw */ 130 int (*init_hpc_hw)(pcie_hp_ctrl_t *ctrl_p); 131 132 /* uninitialize hot plug controller hw */ 133 int (*uninit_hpc_hw)(pcie_hp_ctrl_t *ctrl_p); 134 135 /* initialize slot information structure */ 136 int (*init_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p); 137 138 /* uninitialize slot information structure */ 139 int (*uninit_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p); 140 141 /* slot poweron */ 142 int (*poweron_hpc_slot)(pcie_hp_slot_t *slot_p, 143 ddi_hp_cn_state_t *result); 144 145 /* slot poweroff */ 146 /* uninitialize hot plug controller hw */ 147 int (*poweroff_hpc_slot)(pcie_hp_slot_t *slot_p, 148 ddi_hp_cn_state_t *result); 149 150 /* enable hot plug interrupts/events */ 151 int (*enable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p); 152 153 /* disable hot plug interrupts/events */ 154 int (*disable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p); 155 } pcie_hp_ops_t; 156 157 /* Slot occupant information structure */ 158 #define PCIE_HP_MAX_OCCUPANTS 128 159 typedef struct pcie_hp_occupant_info { 160 int i; 161 char *id[PCIE_HP_MAX_OCCUPANTS]; 162 } pcie_hp_occupant_info_t; 163 164 /* 165 * pcie_hp_led_t 166 * 167 * Type definitions for LED type. These are all the types of LEDs that the 168 * subsystem knows about; however, both PCIe and SHPC only implement the Power 169 * and Attention LEDs. 170 */ 171 typedef enum { 172 PCIE_HP_FAULT_LED, 173 PCIE_HP_POWER_LED, 174 PCIE_HP_ATTN_LED, 175 PCIE_HP_ACTIVE_LED 176 } pcie_hp_led_t; 177 178 /* 179 * pcie_hp_led_state_t 180 * 181 * Type definitions for LED state. This structure represents the underlying 182 * hardware state and not what we are using for tracking the meta state 183 * ourselves. 184 */ 185 typedef enum { 186 PCIE_HP_LED_OFF = 0, 187 PCIE_HP_LED_ON, 188 PCIE_HP_LED_BLINK 189 } pcie_hp_led_state_t; 190 191 /* 192 * The following enumerations and structures are used to track the way that we 193 * manage LEDs for the native PCIe hotplug subsystem. See the 'LED Management' 194 * section of the theory statement of uts/common/io/pciex/hotplug/pciehpc.c for 195 * more information. While this is all specific to the native PCIe 196 * implementation there and not used for the SHPC bits, because everything uses 197 * a shared structure for slots, we must track that here. 198 * 199 * Roughly the pcie_hp_led_act_t is used to describe what we can do to an LED in 200 * our table. The pciehpc_logical_led_t describes the different LED states that 201 * we can be in. Finally, the pciehpc_led_plat_id_t is yet another LED 202 * definition. This would be much simpler if the pcie_hp_led_t reflected 203 * reality. 204 */ 205 typedef enum pcie_hp_led_act { 206 PCIE_HLA_PASS, 207 PCIE_HLA_OFF, 208 PCIE_HLA_ON, 209 PCIE_HLA_BLINK 210 } pcie_hp_led_act_t; 211 212 typedef enum pciehpc_logical_led { 213 /* 214 * The base case here indicates what should happen when we have a slot 215 * without power and no device present. 216 */ 217 PCIE_LL_BASE = 0, 218 /* 219 * This is the state that the system should be in when a device is 220 * powered. 221 */ 222 PCIE_LL_POWERED, 223 /* 224 * This indicates what should happen when an explicit power transition 225 * has been requested. The standard PCIe activity is to blink the power 226 * LED. 227 */ 228 PCIE_LL_POWER_TRANSITION, 229 /* 230 * This is the activity to take when a device driver probe has failed. 231 * This lasts until another state transition or acknowledgement. 232 */ 233 PCIE_LL_PROBE_FAILED, 234 /* 235 * This is the activity to take when a power fault occurs. This will 236 * remain until a device is removed or an active state transition 237 * occurs. 238 */ 239 PCIE_LL_POWER_FAULT, 240 /* 241 * This is the activity to take when the attention button has been 242 * pushed during the 5 second window that is used to confirm behavior. 243 */ 244 PCIE_LL_ATTENTION_BUTTON 245 } pciehpc_logical_led_t; 246 247 #define PCIEHPC_LED_NSTATES 6 248 CTASSERT(PCIEHPC_LED_NSTATES == PCIE_LL_ATTENTION_BUTTON + 1); 249 250 typedef enum { 251 PCIEHPC_PLAT_ID_POWER, 252 PCIEHPC_PLAT_ID_ATTN 253 } pciehpc_led_plat_id_t; 254 255 #define PCIEHPC_LED_NLEDS 2 256 CTASSERT(PCIEHPC_LED_NLEDS == PCIEHPC_PLAT_ID_ATTN + 1); 257 258 typedef struct pciehpc_led_plat_state { 259 pcie_hp_led_act_t plps_acts[PCIEHPC_LED_NLEDS]; 260 } pciehpc_led_plat_state_t; 261 262 struct pciehpc_stat_data; 263 264 /* 265 * PCI and PCI Express Hotplug slot structure 266 */ 267 struct pcie_hp_slot { 268 uint32_t hs_num; /* Logical slot number */ 269 uint32_t hs_phy_slot_num; /* Physical slot number */ 270 uint32_t hs_device_num; /* PCI device num for slot */ 271 uint16_t hs_minor; /* Minor num for this slot */ 272 ddi_hp_cn_info_t hs_info; /* Slot information */ 273 ddi_hp_cn_state_t hs_state; /* Slot state */ 274 275 /* 276 * LED states are split into three groups. The first group is the state 277 * that we believe we should have set into hardware. This state is the 278 * only state the SHPC form of the hotplug controller uses. While there 279 * are four LEDs here, only two are actually supported by the SHPC and 280 * PCIe controllers: the attention and power LEDs. 281 * 282 * The subsequent two groups are only used by the PCIe backend. In the 283 * future we should consider whether or not these structures really 284 * should be shared by all hotplug backends (especially when we add the 285 * ACPI/PCI hotplug scheme that virtual machines use). 286 */ 287 pcie_hp_led_state_t hs_power_led_state; /* Power LED state */ 288 pcie_hp_led_state_t hs_attn_led_state; /* Attn LED state */ 289 pcie_hp_led_state_t hs_active_led_state; /* Active LED state */ 290 pcie_hp_led_state_t hs_fault_led_state; /* Fault LED state */ 291 292 /* 293 * The second of three LED groups. This is used to track when a user 294 * overrides an LED. This is separate from the third group so we can 295 * always return to the expected LED behavior when the override is 296 * disabled again. Currently only used by the PCIe backend. 297 */ 298 pcie_hp_led_state_t hs_power_usr_ovr_state; 299 pcie_hp_led_state_t hs_attn_usr_ovr_state; 300 bool hs_power_usr_ovr; 301 bool hs_attn_usr_ovr; 302 303 /* 304 * The final group of LED state. This array tracks logical events that 305 * have occurred in the hotplug controller. Higher indexed events that 306 * are true take priority over lower indexed ones. The actual mapping of 307 * states to LEDs is in hs_led_plat_conf. For more information see the 308 * pciehpc.c theory statement. 309 */ 310 bool hs_led_plat_en[PCIEHPC_LED_NSTATES]; 311 const pciehpc_led_plat_state_t *hs_led_plat_conf; 312 313 ap_condition_t hs_condition; /* Condition of the slot. */ 314 /* For cfgadm condition. */ 315 316 /* Synchronization variable(s) for hot plug events */ 317 kcondvar_t hs_attn_btn_cv; /* ATTN button pressed intr */ 318 boolean_t hs_attn_btn_pending; 319 kthread_t *hs_attn_btn_threadp; /* ATTN button event thread */ 320 boolean_t hs_attn_btn_thread_exit; 321 kcondvar_t hs_dll_active_cv; /* DLL State Changed intr */ 322 323 /* Event counters and timestamps */ 324 kstat_t *hs_kstat; 325 struct pciehpc_stat_data *hs_stat_data; 326 327 pcie_hp_ctrl_t *hs_ctrl; /* Hotplug ctrl for this slot */ 328 }; 329 330 /* 331 * Register ops for read/write of non-standard HPC (e.g: OPL platform). 332 */ 333 typedef struct pcie_hp_regops { 334 uint_t (*get)(void *cookie, off_t offset); 335 uint_t (*put)(void *cookie, off_t offset, uint_t val); 336 void *cookie; 337 } pcie_hp_regops_t; 338 339 /* 340 * PCI and PCI Express Hotplug controller structure 341 */ 342 struct pcie_hp_ctrl { 343 dev_info_t *hc_dip; /* DIP for HP controller */ 344 kmutex_t hc_mutex; /* Mutex for this ctrl */ 345 uint_t hc_flags; /* Misc flags */ 346 347 /* Slot information */ 348 pcie_hp_slot_t *hc_slots[PCIE_HP_MAX_SLOTS]; /* Slot pointers */ 349 boolean_t hc_has_attn; /* Do we have attn btn? */ 350 boolean_t hc_has_mrl; /* Do we have MRL? */ 351 boolean_t hc_has_pwr; /* Do we have a power ctl? */ 352 kcondvar_t hc_cmd_comp_cv; /* Command Completion intr */ 353 boolean_t hc_cmd_pending; /* Command completion pending */ 354 355 /* PCI Express Hotplug specific fields */ 356 boolean_t hc_has_emi_lock; /* Do we have EMI Lock? */ 357 boolean_t hc_dll_active_rep; /* Report DLL DL_Active state */ 358 taskqid_t hc_startup_sync; /* Startup synched? */ 359 pcie_hp_ops_t hc_ops; /* Platform specific ops */ 360 /* (Native, ACPI) */ 361 362 /* PCI Hotplug (SHPC) specific fields */ 363 uint32_t hc_num_slots_impl; /* # of HP Slots Implemented */ 364 uint32_t hc_num_slots_connected; /* # of HP Slots Connected */ 365 int hc_curr_bus_speed; /* Current Bus Speed */ 366 uint32_t hc_device_start; /* 1st PCI Device # */ 367 uint32_t hc_phys_start; /* 1st Phys Device # */ 368 uint32_t hc_device_increases; /* Device # Increases */ 369 boolean_t hc_arbiter_timeout; /* Got a Arb timeout IRQ */ 370 371 /* Register read/write ops for non-standard HPC (e.g: OPL) */ 372 pcie_hp_regops_t hc_regops; 373 374 /* Platform implementation specific data if any: ACPI, CK804,... */ 375 void *hc_misc_data; 376 }; 377 378 /* 379 * Control structure for tree walk during configure/unconfigure operation. 380 */ 381 typedef struct pcie_hp_cn_cfg_t { 382 void *slotp; 383 boolean_t flag; /* Flag to ignore errors */ 384 int rv; /* Return error code */ 385 dev_info_t *dip; /* dip at which the (first) */ 386 /* error occurred */ 387 void *cn_private; /* Connection specific data */ 388 } pcie_hp_cn_cfg_t; 389 390 /* 391 * arg for unregistering port of a pci bridge 392 */ 393 typedef struct pcie_hp_unreg_port { 394 /* pci bridge dip to which the port is associated */ 395 dev_info_t *nexus_dip; 396 /* 397 * Connector number of the physical slot whose dependent ports will be 398 * unregistered. If NULL, then all the ports of the pci bridge dip will 399 * be unregistered. 400 */ 401 int connector_num; 402 int rv; 403 } pcie_hp_unreg_port_t; 404 405 /* 406 * arg for getting a port's state 407 */ 408 typedef struct pcie_hp_port_state { 409 char *cn_name; 410 ddi_hp_cn_state_t cn_state; 411 int rv; 412 } pcie_hp_port_state_t; 413 414 /* hc_flags */ 415 #define PCIE_HP_INITIALIZED_FLAG (1 << 0) /* HPC initialized */ 416 /* 417 * These two flags are all related to initial synchronization. See 418 * uts/common/io/pciex/hotplug/pciehpc.c for more information. The first is used 419 * to track that this is required while the second indicates that it's actively 420 * occurring. 421 */ 422 #define PCIE_HP_SYNC_PENDING (1 << 1) 423 #define PCIE_HP_SYNC_RUNNING (1 << 2) 424 425 /* PCIe hotplug friendly functions */ 426 extern int pcie_hp_init(dev_info_t *dip, caddr_t arg); 427 extern int pcie_hp_uninit(dev_info_t *dip); 428 extern int pcie_hp_intr(dev_info_t *dip); 429 extern int pcie_hp_probe(pcie_hp_slot_t *slot_p); 430 extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p); 431 extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op, 432 void *arg, void *result); 433 extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device, 434 uint_t function); 435 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 436 int pci_dev); 437 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev, 438 int pci_dev); 439 extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev); 440 extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz, 441 nvlist_t **nvlp); 442 extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf, 443 size_t *packed_sz); 444 extern char *pcie_led_state_text(pcie_hp_led_state_t state); 445 extern char *pcie_slot_condition_text(ap_condition_t condition); 446 extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int); 447 extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int); 448 extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint, 449 dev_info_t *self, int kmflag); 450 451 #endif /* _KERNEL */ 452 453 #ifdef __cplusplus 454 } 455 #endif 456 457 #endif /* _SYS_PCIE_HP_H */ 458