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 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2019 Joyent, Inc. 25 * Copyright 2024 Oxide Computer Company 26 */ 27 28 /* 29 * This file contains Standard PCI Express HotPlug functionality that is 30 * compatible with the PCI Express ver 1.1 specification. 31 * 32 * NOTE: This file is compiled and delivered through misc/pcie module. 33 * 34 * The main purpose of this is to take the PCIe slot logic, which is found on a 35 * PCIe bridge that indicates it is hotplug capable, and map the DDI hotplug 36 * controller states to this. This is an imperfect mapping as the definition of 37 * the pciehpc_slot_power_t shows. This file assumes that a device can be 38 * removed at any time without notice. This is what the spec calls 'surprise 39 * removal'. 40 * 41 * Not all PCIe slots are the same. In particular this can handle the following 42 * features which may or may not exist on the slot: 43 * 44 * o Power Controllers: With the rise of NVMe based hotplug and the Enterprise 45 * SSD specification, you can have hotplug, but not specific power control 46 * over the device. 47 * o MRL sensor: Manually-operated Retention latches are an optional item and 48 * less common with U.2, E.1, and E.3 based form factors, but there is the 49 * ability to see their state. 50 * o EMI: Electromechanical Interlock. This is used to lock the device in place 51 * and is often paired with an MRL. This similarly isn't as common. 52 * o Attention Button: A button which can be pressed to say please do 53 * something. This is more of a holdover from the world of coordinated 54 * removal from the PCI Standard Hot-Plug Controller (SHPC). 55 * o Power Fault: The ability to tell whether or not a power fault has 56 * occurred. 57 * o Power and Attention Indicators: These are LEDs that are supposed to be 58 * enabled in response to specific actions in the spec, but some of that is 59 * ultimately policy. It's worth noting that not all controllers support both 60 * LEDs and so platforms may want to munge the logical states here a bit 61 * more. 62 * 63 * There are four primary states that a slot is considered to exist in that 64 * roughly have the following state transition diagram: 65 * 66 * +-------+ 67 * | Empty |<---------------<------------+ 68 * +-------+ | 69 * | | 70 * Device | | 71 * Inserted . ^ 72 * | | 73 * | | 74 * v | 75 * +---------+ . . . Device 76 * | Present |<------+ | Removed 77 * +---------+ | | 78 * | | | 79 * Slot | | | 80 * Power . . . . Slot Power | 81 * Enabled | | Disabled, | 82 * | | Power Fault, | 83 * v | or specific | 84 * +---------+ | request | 85 * | Powered |-->----+ | 86 * +---------+ | | 87 * | | | 88 * | | | 89 * Request | ^ ^ 90 * or auto- | | | 91 * online . * | | 92 * | | | 93 * v | | 94 * +---------+ | | 95 * | Enabled |-->----+--------->----------+ 96 * +---------+ 97 * 98 * These four states are all related to the DDI_HP_CN_STATE_* values. For 99 * example, the empty state above is DDI_HP_CN_STATE_EMPTY and enabled is 100 * DDI_HP_CN_STATE_ENABLED. These changes can happen initially because of 101 * outside action that is taken or because an explicit state change has been 102 * requested via cfgadm/libhotplug. Note that one cannot enter or leave empty 103 * without removing or inserting a device. 104 * 105 * A device node is created in the devinfo tree as a side effect of 106 * transitioning to the enabled state and removed when transitioning away from 107 * enabled. This is initiated by the DDI hotplug framework making a probe 108 * (DDI_HPOP_CN_PROBE) and unprobe (DDI_HPOP_CN_UNPROBE) request which will 109 * ultimately get us to pcicfg_configure() which dynamically sets up child 110 * nodes. 111 * 112 * State Initialization 113 * -------------------- 114 * 115 * Initializing the state of the world is a bit tricky here. In particular, 116 * there are a few things that we need to understand and deal with: 117 * 118 * 1. A PCIe slot may or may not have been powered prior to us initializing this 119 * module. In particular, the PCIe firmware specification generally expects 120 * occupied slots to have both their MRL and power indicator match the slot 121 * occupancy state (3.5 Device State at Firmware/Operating System Handoff). Of 122 * course, we must not assume that firmware has done this or not. 123 * 124 * This is further complicated by the fact that while the PCIe default is that 125 * power is enabled at reset, some controllers require an explicit first write 126 * to enact the reset behavior. You cannot do things like enable or disable 127 * interrupts without doing a write to the PCIe Slot Control register and 128 * turning power on. Those are just the breaks from the spec. The spec also 129 * doesn't have a way to tell us if power is actually on or not, we just have to 130 * hope. All we can see is if we've commanded power on and if a power fault was 131 * detected at some point. 132 * 133 * 2. Because of (1), the normal platform-specific startup logic for PCIe may or 134 * may not have found any devices and initialized them depending on at what 135 * state in the initialization point it was at. 136 * 137 * 3. To actually enumerate a hotplug device, our DDI_HPOP_CN_PROBE entry point 138 * needs to be called, which is pciehpc_slot_probe(). This will ultimately call 139 * pcicfg_configure(). There is a wrinkle here. If we have done (2), we don't 140 * want to call the probe entry point. However, if we haven't, then at start up, 141 * the broader hotplug unfortunately, won't assume that there is anything to do 142 * here to make this happen. The kernel framework won't call this unless it sees 143 * a transition from a lesser state to DDI_HP_CN_STATE_ENABLED. 144 * 145 * The cases described above are not our only problem. In particular, there are 146 * some other complications that happen here. In particular, it's worth 147 * understanding how we actually keep all of our state in sync. The core idea is 148 * that changes are coming from one of two places: either a user has explicitly 149 * requested a state change or we have had external activity that has injected a 150 * hotplug interrupt. This is due to something such as a surprise insertion, 151 * removal, power fault, or similar activity. 152 * 153 * The general construction and assumption is that we know the valid state at 154 * the moment before an interrupt occurs, so then the slot status register will 155 * indicate to us what has changed. Once we know what we should transition to, 156 * then we will go ahead and ask the system to make a state change request to 157 * change our state to a given target. While this is similar in spirit to what a 158 * user could request, they could not imitate a state transition to EMPTY. The 159 * transition to EMPTY or to ENABLED is what kicks off the probe and unprobe 160 * operations. 161 * 162 * This system is all well and good, but it is dependent on the fact that we 163 * have an interrupt enabled for changes and that the various interrupt cause 164 * bits in the slot status register have been cleared as they are generally RW1C 165 * (read, write 1 to clear). This means that in addition to the issues with case 166 * (1) and what firmware has or hasn't done, it is also possible that additional 167 * changes may occur without us recording them or noticing them in an interrupt. 168 * 169 * This steady state is a great place to be, but because of the races we 170 * discussed above, we need to do a bit of additional work here to ensure that 171 * we can reliably enter it. As such, we're going to address the three 172 * complications above in reverse order. If we start with (3), while in the 173 * steady state, we basically treat the DDI states as the main states we can 174 * transition to and from (again see the pciehpc_slot_power_t comment for the 175 * fact that this is somewhat factious). This means that if we are ENABLED, a 176 * probe must have happened (or the semi-equivalent in (2)). 177 * 178 * Normally, we assume that if we got all the way up and have a powered device 179 * that the state we should return to the system is ENABLED. However, that only 180 * works if we can ensure that the state transition from less than ENABLED to 181 * ENABLED occurs so a probe can occur. 182 * 183 * This window is made larger because of (1) and (2). However, this is not 184 * unique to the ENABLED state and these cases can happen by having a device 185 * that was probed at initial time be removed prior to the interrupt being 186 * enabled. While this is honestly a very tight window and something that may 187 * not happen in practice, it highlights many of the things that can occur and 188 * that we need to handle. 189 * 190 * To deal with this we are a little more careful with our startup state. When 191 * we reach our module's main initialization entry point for a given controller, 192 * pciehpc_init(), we know that at that point (2) has completed. We also know 193 * that the interrupt shouldn't be initiated at that point, but that isn't 194 * guaranteed until we finish calling the pciehpc_hpc_init() entry point. We 195 * subsequently will enable the interrupt via the enable_phc_intr() function 196 * pointer, which is called from pcie_hpintr_enable(). This gap is to allow the 197 * overall driver (say pcieb) to ensure that it has allocated and attached 198 * interrupts prior to us enabling it. 199 * 200 * At the point that we are initialized, we can look and see if we have any 201 * children. If we do, then we know that (2) performed initialization and it's 202 * safe for us to set our initial state to ENABLED and allow that to be the 203 * first thing the kernel hotplug framework sees, assuming our state would 204 * otherwise suggest we'd be here. If we do not see a child device and we have 205 * enabled power, then we basically need to mimic the normal act of having 206 * transitioned to an ENABLED state. This needs to happen ahead of us first 207 * communicating our state to the DDI. 208 * 209 * The next set of things we need to do happen when we go to enable interrupts. 210 * It's worth keeping in mind that at this point the rest of the system is fully 211 * operational. One of three events can be injected at this point, a removal, 212 * insertion, or a power fault. We also need to consider that a removal or 213 * insertion happened in an intervening point. To make this all happen, let's 214 * discuss the different pieces that are involved in tracking what's going on: 215 * 216 * 1) During pciehpc_slotinfo_init() we check to see if we have a child devinfo 217 * node or not. We only mark a node as ENABLED if we have a child and it is 218 * already POWERED. This ensures that we aren't ahead of ourselves. The normal 219 * state determination logic will not put us at enabled prior to being there. 220 * 221 * 2) We have added a pair of flags to the pcie_hp_ctrl_t called 222 * PCIE_HP_SYNC_PENDING and PCIE_HP_SYNC_RUNNING. The former indicates that we 223 * have identified that we need to perform a state correction and have 224 * dispatched a task to the system taskq to deal with it. The 225 * PCIE_HP_SYNC_RUNNING flag is used to indicate that a state transition request 226 * is actually being made due to this right now. This is used to tweak a bit of 227 * the slot upgrade path, discussed below. 228 * 229 * 3) Immediately after enabling interrupts, while still holding the hotplug 230 * controller mutex, we investigate what our current state is and what we have 231 * previously set it to. Depending on the transition that needs to occur and if 232 * it has a side effect of needing to probe or unprobe a connection, then we'll 233 * end up scheduling a task in the system taskq to perform that transition. 234 * Otherwise, we will simply fix up the LED state as we have no reason to 235 * believe that it is currently correct for our state. 236 * 237 * Using the taskq has a major benefit for us in that it allows us to leverage 238 * the existing code paths for state transitions. This means that if things are 239 * already powered on and the data link layer is active, there won't be any 240 * extra delay and if not, it will honor the same 1s timeout, take advantage of 241 * the datalink layer active bit if supported, and on failure it will turn off 242 * the controller. 243 * 244 * 4) We are reliant on an important property of pciehpc_get_slot_state(): if it 245 * finds itself in the POWERED state, it will not change from that. This is half 246 * of the reason that we opt to go to the POWERED state when this occurs. The 247 * other half is that it is factually accurate and doing otherwise would get in 248 * the way of our logic which attempts to correct the state in 249 * pciehpc_change_slot_state() which corrects for the state being incorrect. 250 * While it is tempting to use the PRESENT state and try to avoid a special case 251 * in pciehpc_upgrade_slot_state(), that ends up breaking more invariants than 252 * the logic described below. 253 * 254 * 5) Finally, when the PCIE_HP_SYNC_RUNNING bit is set, that tells us when 255 * we're doing a power on exercise that we need to do so again regardless of 256 * what we think we've done. Because of our attempts to try to have things be 257 * idempotent, this ends up being a relatively safe operation to perform again 258 * and being able to reuse this helps a lot. 259 * 260 * It is our hope that after this point everything will be in line such that we 261 * can enter the steady state. If devices have come or gone, the use of the 262 * normal state machine transitions should allow us to get them to be attached 263 * or not. 264 * 265 * LED Management 266 * -------------- 267 * 268 * The PCIe specifications define two LEDs that may optionally exist on a slot: 269 * a power LED and an attention LED. In the earliest version of the PCIe 270 * specification, these were maintained as device capabilities, but by PCIe 1.1 271 * they are solely on the slot. The PCIe specification provides very specific 272 * meanings for what these LEDs indicate. However, different systems implement a 273 * subset of these LEDs and may not want to use them for the same purposes. The 274 * PCIe Native HotPlug defined in S6.7 describes the following roles for each 275 * LED (and also defines the colors): 276 * 277 * POWER Off: Device not powered 278 * On: Device powered 279 * Blink: Power transition occurring 280 * 281 * ATTENTION Off: Everything's fine, how are you? 282 * On: There's a problem here. 283 * Blink: Attention 284 * 285 * While this is the standard, it's not always the case that everything actually 286 * has implemented these, that all platforms want to use the same definitions, 287 * or even have both LEDs. The above definitions are strictly meant for hotplug, 288 * but one could have LEDs without hotplug (though it's rare). In addition, 289 * there are cases that the operating system adds additional semantics as to 290 * what the LEDs should mean. For example, while holding the attention button, 291 * the power LED blinks, or if probe fails, then we assume that attention should 292 * be asserted. Finally, there is the unfortunate reality that many systems 293 * which implement a more limited form of Enterprise SSD take away LED 294 * management from the OS entirely and it is left entirely up to firmware's 295 * druthers (possibly allowing for interaction via IPMI or something similar). 296 * 297 * The next consideration for LED management is that there is an ability for 298 * this to be overridden by userland. For example, there is no first class blink 299 * or locate ioctl and instead that is something that is created by an operator 300 * using libhotplug or say an FMA topology. This means that the state that we 301 * have displayed can be overridden at any time. As such, while libhotplug and 302 * other consumers may chance the LED state, we instead think of this as an 303 * override. When they are done, they can restore the default behavior and we 304 * will figure out what that means. 305 * 306 * For the most part our LED state can be determined based upon the slot's 307 * state. However, there are a few specific transitions that can occur that need 308 * to be captured like while we are powering, attention button activity, or 309 * probe failures. A particular part of this is what are the lifetimes of these 310 * and when should they be cleared out. There is a bunch of complexity here that 311 * suggests this subsystem should perhaps be driven more by userland (where it's 312 * a bit easier to inject what someone wants). For now, here is how we scope 313 * those special cases: 314 * 315 * POWER FAULT When a power fault occurs, this normally automatically 316 * causes us to power off the device (if there is a power 317 * controller). As such the only things that clear out a 318 * power fault is another attempt to power on the device 319 * (because we have no way of knowing whether or not it's 320 * still faulted, thanks specs) or until the device is 321 * removed. 322 * 323 * ATTENTION BUTTON Pushing the attention button is supposed to cause a five 324 * second timer to begin. This state persists across its 325 * entire lifetime. Once that is done, then it will be 326 * turned off. Unlike other things it is not bound to a 327 * power transition. 328 * 329 * PROBE FAILURE This is not a PCIe concept, but something that we do. 330 * This is meant to last until a subsequent attempt to 331 * probe the device occurs, the device is powered off, or 332 * the device is removed. This is different from a power 333 * fault in so far as we honor power off as a transition 334 * point here. This was chosen because powering off 335 * represents an active action to try to and change the 336 * state away from probing, so it no longer serves to blink 337 * the LED because of a probe failure. 338 * 339 * To deal with this, we have a series of logical LED states that can be enabled 340 * which are then evaluated in a preferential ordering that describe what to do 341 * for each logical item we want to do. These include things like power 342 * transitions, the device being powered, or things like the power fault or 343 * probe failing. This is tracked in the slot's hs_led_plat_en[] data structure. 344 * Higher states are preferential which is why we work through the states 345 * backwards. Each state can opt to take an explicit state or punt to the next. 346 * 347 * We map the logical state to LED actions through a platform-specific set of 348 * definitions. Pretty much everything will use the standard PCIe LED behavior 349 * (pciehpc_pcie_std_leds[]), but this can be overridden for particular 350 * platforms. 351 * 352 * Because of our startup races, we defer actually setting the external LED 353 * state until we first get through pciehpc_enable_state_sync() or a 354 * corresponding state transition that it forces to happen. 355 */ 356 357 #include <sys/types.h> 358 #include <sys/note.h> 359 #include <sys/conf.h> 360 #include <sys/kmem.h> 361 #include <sys/debug.h> 362 #include <sys/vtrace.h> 363 #include <sys/autoconf.h> 364 #include <sys/varargs.h> 365 #include <sys/ddi_impldefs.h> 366 #include <sys/time.h> 367 #include <sys/callb.h> 368 #include <sys/ddi.h> 369 #include <sys/sunddi.h> 370 #include <sys/sunndi.h> 371 #include <sys/sysmacros.h> 372 #include <sys/sysevent/dr.h> 373 #include <sys/pci_impl.h> 374 #include <sys/kstat.h> 375 #include <sys/zone.h> 376 #include <sys/hotplug/pci/pcie_hp.h> 377 #include <sys/hotplug/pci/pciehpc.h> 378 379 /* XXX /etc/system is NOT a policy interface */ 380 int pcie_auto_online = 1; 381 382 /* 383 * Ideally, it would be possible to represent the state of a slot with a single 384 * ddi_hp_cn_state_t; after all, that's the purpose of that data type. 385 * Unfortunately it wasn't designed very well and cannot even represent the 386 * range of possible power states of a PCIe slot. It is possible for a slot to 387 * be powered on or off with or without a device present, and it is possible for 388 * a slot not to have a power controller at all. Finally, it's possible for a 389 * power fault to be detected regardless of whether power is on or off or a 390 * device is present or not. This state attempts to represent all possible 391 * power states that a slot can have, which is important for implementing our 392 * state machine that has to expose only the very limited DDI states. 393 * 394 * These are bits that may be ORed together. Not all combinations comply with 395 * the standards, but these definitions were chosen to make it harder to 396 * construct invalid combinations. In particular, if there is no controller, 397 * there is also no possibility of the slot being turned off, nor is it possible 398 * for there to be a fault. 399 */ 400 typedef enum pciehpc_slot_power { 401 PSP_NO_CONTROLLER = 0, 402 PSP_HAS_CONTROLLER = (1U << 0), 403 PSP_OFF = (1U << 1), 404 PSP_FAULT = (1U << 2) 405 } pciehpc_slot_power_t; 406 407 typedef struct { 408 pcie_hp_ctrl_t *pst_ctrl; 409 ddi_hp_cn_state_t pst_targ; 410 ddi_hp_cn_state_t pst_cur; 411 } pciehpc_sync_task_t; 412 413 static const pciehpc_led_plat_state_t pciehpc_std_leds[PCIEHPC_LED_NSTATES] = { 414 [PCIE_LL_BASE] = { PCIE_HLA_OFF, PCIE_HLA_OFF }, 415 [PCIE_LL_POWER_TRANSITION] = { PCIE_HLA_BLINK, PCIE_HLA_PASS }, 416 [PCIE_LL_POWERED] = { PCIE_HLA_ON, PCIE_HLA_OFF }, 417 [PCIE_LL_PROBE_FAILED] = { PCIE_HLA_PASS, PCIE_HLA_ON }, 418 [PCIE_LL_POWER_FAULT] = { PCIE_HLA_BLINK, PCIE_HLA_PASS }, 419 [PCIE_LL_ATTENTION_BUTTON] = { PCIE_HLA_BLINK, PCIE_HLA_PASS } 420 }; 421 422 /* 423 * The Gimlet hardware platform only has a single attention LED that is used for 424 * multiple purposes. 425 */ 426 static const pciehpc_led_plat_state_t pciehpc_gimlet_leds[PCIEHPC_LED_NSTATES] = 427 { 428 [PCIE_LL_BASE] = { PCIE_HLA_OFF, PCIE_HLA_OFF }, 429 [PCIE_LL_POWER_TRANSITION] = { PCIE_HLA_PASS, PCIE_HLA_PASS }, 430 [PCIE_LL_POWERED] = { PCIE_HLA_PASS, PCIE_HLA_ON }, 431 [PCIE_LL_PROBE_FAILED] = { PCIE_HLA_PASS, PCIE_HLA_BLINK }, 432 [PCIE_LL_POWER_FAULT] = { PCIE_HLA_PASS, PCIE_HLA_BLINK }, 433 [PCIE_LL_ATTENTION_BUTTON] = { PCIE_HLA_PASS, PCIE_HLA_PASS } 434 }; 435 436 typedef struct pciehpc_led_plat_map { 437 uint16_t plpm_vid; 438 uint16_t plpm_did; 439 uint16_t plpm_svid; 440 uint16_t plpm_ssys; 441 const pciehpc_led_plat_state_t *plpm_map; 442 } pciehpc_led_plat_map_t; 443 444 /* 445 * This table represents platforms that have different values than the default 446 * PCIe LED usage that should be applied. 447 */ 448 static const pciehpc_led_plat_map_t pciehpc_led_plat_map[] = { 449 { .plpm_vid = 0x1022, .plpm_did = 0x1483, .plpm_svid = 0x1de, 450 .plpm_ssys = 0xfff9, .plpm_map = pciehpc_gimlet_leds } 451 }; 452 453 /* Local functions prototype */ 454 static int pciehpc_hpc_init(pcie_hp_ctrl_t *ctrl_p); 455 static int pciehpc_hpc_uninit(pcie_hp_ctrl_t *ctrl_p); 456 static int pciehpc_slotinfo_init(pcie_hp_ctrl_t *ctrl_p); 457 static int pciehpc_slotinfo_uninit(pcie_hp_ctrl_t *ctrl_p); 458 static int pciehpc_enable_intr(pcie_hp_ctrl_t *ctrl_p); 459 static int pciehpc_disable_intr(pcie_hp_ctrl_t *ctrl_p); 460 static pcie_hp_ctrl_t *pciehpc_create_controller(dev_info_t *dip); 461 static void pciehpc_destroy_controller(dev_info_t *dip); 462 static int pciehpc_register_slot(pcie_hp_ctrl_t *ctrl_p); 463 static int pciehpc_unregister_slot(pcie_hp_ctrl_t *ctrl_p); 464 static int pciehpc_slot_get_property(pcie_hp_slot_t *slot_p, 465 uintptr_t arg, uintptr_t rval); 466 static int pciehpc_slot_set_property(pcie_hp_slot_t *slot_p, 467 uintptr_t arg, uintptr_t rval); 468 static void pciehpc_issue_hpc_command(pcie_hp_ctrl_t *ctrl_p, uint16_t control); 469 static void pciehpc_attn_btn_handler(pcie_hp_ctrl_t *ctrl_p); 470 static pcie_hp_led_state_t pciehpc_led_state_to_hpc(uint16_t state); 471 472 static int pciehpc_upgrade_slot_state(pcie_hp_slot_t *slot_p, 473 ddi_hp_cn_state_t target_state); 474 static int pciehpc_downgrade_slot_state(pcie_hp_slot_t *slot_p, 475 ddi_hp_cn_state_t target_state); 476 static int pciehpc_change_slot_state(pcie_hp_slot_t *slot_p, 477 ddi_hp_cn_state_t target_state); 478 static int 479 pciehpc_slot_poweron(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result); 480 static int 481 pciehpc_slot_poweroff(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result); 482 static int pciehpc_slot_probe(pcie_hp_slot_t *slot_p); 483 static int pciehpc_slot_unprobe(pcie_hp_slot_t *slot_p); 484 static void pciehpc_handle_power_fault(dev_info_t *dip); 485 static void pciehpc_power_fault_handler(void *arg); 486 487 #ifdef DEBUG 488 static void pciehpc_dump_hpregs(pcie_hp_ctrl_t *ctrl_p); 489 #endif /* DEBUG */ 490 491 typedef struct pciehpc_stat_data { 492 kstat_named_t psd_attnsw_count; 493 kstat_named_t psd_attnsw_ts; 494 kstat_named_t psd_pwrflt_count; 495 kstat_named_t psd_pwrflt_ts; 496 kstat_named_t psd_mrl_chg_count; 497 kstat_named_t psd_mrl_chg_ts; 498 kstat_named_t psd_pres_chg_count; 499 kstat_named_t psd_pres_chg_ts; 500 kstat_named_t psd_cmd_cpl_count; 501 kstat_named_t psd_cmd_cpl_ts; 502 kstat_named_t psd_dll_chg_count; 503 kstat_named_t psd_dll_chg_ts; 504 kstat_named_t psd_intr_count; 505 kstat_named_t psd_intr_ts; 506 } pciehpc_stat_data_t; 507 508 static inline void 509 pciehpc_kstat_event(kstat_named_t *countp, kstat_named_t *tsp, hrtime_t now) 510 { 511 atomic_inc_64(&countp->value.ui64); 512 tsp->value.ui64 = now; 513 } 514 515 #define KSTAT_EVENT(_slotp, _evname, _now) \ 516 pciehpc_kstat_event((&(_slotp)->hs_stat_data->psd_ ## _evname ## _count), \ 517 (&(_slotp)->hs_stat_data->psd_ ## _evname ## _ts), (_now)) 518 519 /* 520 * Global functions (called by other drivers/modules) 521 */ 522 523 /* 524 * Initialize Hot Plug Controller if present. The arguments are: 525 * dip - devinfo node pointer to the hot plug bus node 526 * regops - register ops to access HPC registers for non-standard 527 * HPC hw implementations (e.g: HPC in host PCI-E bridges) 528 * This is NULL for standard HPC in PCIe bridges. 529 * Returns: 530 * DDI_SUCCESS for successful HPC initialization 531 * DDI_FAILURE for errors or if HPC hw not found 532 */ 533 int 534 pciehpc_init(dev_info_t *dip, caddr_t arg) 535 { 536 pcie_hp_regops_t *regops = (pcie_hp_regops_t *)(void *)arg; 537 pcie_hp_ctrl_t *ctrl_p; 538 539 PCIE_DBG("pciehpc_init() called (dip=%p)\n", (void *)dip); 540 541 /* Make sure that it is not already initialized */ 542 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) != NULL) { 543 PCIE_DBG("%s%d: pciehpc instance already initialized!\n", 544 ddi_driver_name(dip), ddi_get_instance(dip)); 545 return (DDI_SUCCESS); 546 } 547 548 /* Allocate a new hotplug controller and slot structures */ 549 ctrl_p = pciehpc_create_controller(dip); 550 551 /* setup access handle for HPC regs */ 552 if (regops != NULL) { 553 /* HPC access is non-standard; use the supplied reg ops */ 554 ctrl_p->hc_regops = *regops; 555 } 556 557 /* 558 * Setup resource maps for this bus node. 559 */ 560 (void) pci_resource_setup(dip); 561 562 PCIE_DISABLE_ERRORS(dip); 563 564 /* 565 * Set the platform specific hot plug mode. 566 */ 567 ctrl_p->hc_ops.init_hpc_hw = pciehpc_hpc_init; 568 ctrl_p->hc_ops.uninit_hpc_hw = pciehpc_hpc_uninit; 569 ctrl_p->hc_ops.init_hpc_slotinfo = pciehpc_slotinfo_init; 570 ctrl_p->hc_ops.uninit_hpc_slotinfo = pciehpc_slotinfo_uninit; 571 ctrl_p->hc_ops.poweron_hpc_slot = pciehpc_slot_poweron; 572 ctrl_p->hc_ops.poweroff_hpc_slot = pciehpc_slot_poweroff; 573 574 ctrl_p->hc_ops.enable_hpc_intr = pciehpc_enable_intr; 575 ctrl_p->hc_ops.disable_hpc_intr = pciehpc_disable_intr; 576 577 #if defined(__x86) 578 pciehpc_update_ops(ctrl_p); 579 #endif 580 581 /* initialize hot plug controller hw */ 582 if ((ctrl_p->hc_ops.init_hpc_hw)(ctrl_p) != DDI_SUCCESS) 583 goto cleanup1; 584 585 /* initialize slot information soft state structure */ 586 if ((ctrl_p->hc_ops.init_hpc_slotinfo)(ctrl_p) != DDI_SUCCESS) 587 goto cleanup2; 588 589 /* register the hot plug slot with DDI HP framework */ 590 if (pciehpc_register_slot(ctrl_p) != DDI_SUCCESS) 591 goto cleanup3; 592 593 /* create minor node for this slot */ 594 if (pcie_create_minor_node(ctrl_p, 0) != DDI_SUCCESS) 595 goto cleanup4; 596 597 /* 598 * While we disabled errors upon entry, if we were initialized and 599 * entered the ENABLED state that indicates we have children and 600 * therefore we should go back and enable errors. 601 */ 602 if (ctrl_p->hc_slots[0]->hs_info.cn_state == DDI_HP_CN_STATE_ENABLED) { 603 PCIE_ENABLE_ERRORS(dip); 604 } 605 606 /* HPC initialization is complete now */ 607 ctrl_p->hc_flags |= PCIE_HP_INITIALIZED_FLAG; 608 609 #ifdef DEBUG 610 /* For debug, dump the HPC registers */ 611 pciehpc_dump_hpregs(ctrl_p); 612 #endif /* DEBUG */ 613 614 return (DDI_SUCCESS); 615 cleanup4: 616 (void) pciehpc_unregister_slot(ctrl_p); 617 cleanup3: 618 (void) (ctrl_p->hc_ops.uninit_hpc_slotinfo)(ctrl_p); 619 620 cleanup2: 621 (void) (ctrl_p->hc_ops.uninit_hpc_hw)(ctrl_p); 622 623 cleanup1: 624 PCIE_ENABLE_ERRORS(dip); 625 (void) pci_resource_destroy(dip); 626 627 pciehpc_destroy_controller(dip); 628 return (DDI_FAILURE); 629 } 630 631 /* 632 * Uninitialize HPC soft state structure and free up any resources 633 * used for the HPC instance. 634 */ 635 int 636 pciehpc_uninit(dev_info_t *dip) 637 { 638 pcie_hp_ctrl_t *ctrl_p; 639 taskqid_t id; 640 641 PCIE_DBG("pciehpc_uninit() called (dip=%p)\n", (void *)dip); 642 643 /* get the soft state structure for this dip */ 644 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) == NULL) { 645 return (DDI_FAILURE); 646 } 647 648 /* 649 * Prior to taking any action, we want to remove the initialized flag. 650 * Any interrupts should have already been quiesced prior to this. There 651 * may be an outstanding startup synchronization timeout(9F) call. 652 */ 653 mutex_enter(&ctrl_p->hc_mutex); 654 ctrl_p->hc_flags &= ~PCIE_HP_INITIALIZED_FLAG; 655 id = ctrl_p->hc_startup_sync; 656 ctrl_p->hc_startup_sync = TASKQID_INVALID; 657 mutex_exit(&ctrl_p->hc_mutex); 658 659 if (id != TASKQID_INVALID) 660 taskq_wait_id(system_taskq, id); 661 662 pcie_remove_minor_node(ctrl_p, 0); 663 664 /* unregister the slot */ 665 (void) pciehpc_unregister_slot(ctrl_p); 666 667 /* uninit any slot info data structures */ 668 (void) (ctrl_p->hc_ops.uninit_hpc_slotinfo)(ctrl_p); 669 670 /* uninitialize hpc, remove interrupt handler, etc. */ 671 (void) (ctrl_p->hc_ops.uninit_hpc_hw)(ctrl_p); 672 673 PCIE_ENABLE_ERRORS(dip); 674 675 /* 676 * Destroy resource maps for this bus node. 677 */ 678 (void) pci_resource_destroy(dip); 679 680 /* destroy the soft state structure */ 681 pciehpc_destroy_controller(dip); 682 683 return (DDI_SUCCESS); 684 } 685 686 /* 687 * pciehpc_intr() 688 * 689 * Interrupt handler for PCI-E Hot plug controller interrupts. 690 * 691 * Note: This is only for native mode hot plug. This is called 692 * by the nexus driver at interrupt context. Interrupt Service Routine 693 * registration is done by the nexus driver for both hot plug and 694 * non-hot plug interrupts. This function is called from the ISR 695 * of the nexus driver to handle hot-plug interrupts. 696 * 697 * We must check whether or not we have a pending synchronization event and if 698 * so, cancel it. In particular, there are several cases that may cause us to 699 * request an asynchronous state transition (e.g. a drive was removed or 700 * inserted). When that occurs, we effectively cancel the pending 701 * synchronization taskq activity. It will still execute, but do nothing. If it 702 * has already started executing, then its state change request will already 703 * have been dispatched and we let things shake out with the additional logic we 704 * have present in pciehpc_change_slot_state(). 705 */ 706 int 707 pciehpc_intr(dev_info_t *dip) 708 { 709 pcie_hp_ctrl_t *ctrl_p; 710 pcie_hp_slot_t *slot_p; 711 pcie_bus_t *bus_p = PCIE_DIP2BUS(dip); 712 uint16_t status, control; 713 boolean_t clear_pend = B_FALSE; 714 hrtime_t now; 715 716 /* get the soft state structure for this dip */ 717 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) == NULL) 718 return (DDI_INTR_UNCLAIMED); 719 720 now = gethrtime(); 721 722 mutex_enter(&ctrl_p->hc_mutex); 723 724 /* make sure the controller soft state is initialized */ 725 if (!(ctrl_p->hc_flags & PCIE_HP_INITIALIZED_FLAG)) { 726 mutex_exit(&ctrl_p->hc_mutex); 727 return (DDI_INTR_UNCLAIMED); 728 } 729 730 /* if it is not NATIVE hot plug mode then return */ 731 if (bus_p->bus_hp_curr_mode != PCIE_NATIVE_HP_MODE) { 732 mutex_exit(&ctrl_p->hc_mutex); 733 return (DDI_INTR_UNCLAIMED); 734 } 735 736 slot_p = ctrl_p->hc_slots[0]; 737 738 /* read the current slot status register */ 739 status = pciehpc_reg_get16(ctrl_p, 740 bus_p->bus_pcie_off + PCIE_SLOTSTS); 741 742 /* check if there are any hot plug interrupts occurred */ 743 if (!(status & PCIE_SLOTSTS_STATUS_EVENTS)) { 744 /* no hot plug events occurred */ 745 mutex_exit(&ctrl_p->hc_mutex); 746 return (DDI_INTR_UNCLAIMED); 747 } 748 749 /* We are now committed to claiming the interrupt; record it. */ 750 KSTAT_EVENT(slot_p, intr, now); 751 752 /* clear the interrupt status bits */ 753 pciehpc_reg_put16(ctrl_p, 754 bus_p->bus_pcie_off + PCIE_SLOTSTS, status); 755 756 /* check for CMD COMPLETE interrupt */ 757 if (status & PCIE_SLOTSTS_COMMAND_COMPLETED) { 758 KSTAT_EVENT(slot_p, cmd_cpl, now); 759 PCIE_DBG("pciehpc_intr(): CMD COMPLETED interrupt received\n"); 760 /* wake up any one waiting for Command Completion event */ 761 cv_signal(&ctrl_p->hc_cmd_comp_cv); 762 } 763 764 /* check for ATTN button interrupt */ 765 if (status & PCIE_SLOTSTS_ATTN_BTN_PRESSED) { 766 KSTAT_EVENT(slot_p, attnsw, now); 767 PCIE_DBG("pciehpc_intr(): ATTN BUTTON interrupt received\n"); 768 769 /* if ATTN button event is still pending then cancel it */ 770 if (slot_p->hs_attn_btn_pending == B_TRUE) 771 slot_p->hs_attn_btn_pending = B_FALSE; 772 else 773 slot_p->hs_attn_btn_pending = B_TRUE; 774 775 /* wake up the ATTN event handler */ 776 cv_signal(&slot_p->hs_attn_btn_cv); 777 } 778 779 /* check for power fault interrupt */ 780 if (status & PCIE_SLOTSTS_PWR_FAULT_DETECTED) { 781 KSTAT_EVENT(slot_p, pwrflt, now); 782 PCIE_DBG("pciehpc_intr(): POWER FAULT interrupt received" 783 " on slot %d\n", slot_p->hs_phy_slot_num); 784 control = pciehpc_reg_get16(ctrl_p, 785 bus_p->bus_pcie_off + PCIE_SLOTCTL); 786 787 if (control & PCIE_SLOTCTL_PWR_FAULT_EN) { 788 slot_p->hs_condition = AP_COND_FAILED; 789 790 /* disable power fault detection interrupt */ 791 pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off + 792 PCIE_SLOTCTL, control & ~PCIE_SLOTCTL_PWR_FAULT_EN); 793 794 pciehpc_handle_power_fault(dip); 795 clear_pend = B_TRUE; 796 } 797 } 798 799 /* check for MRL SENSOR CHANGED interrupt */ 800 if (status & PCIE_SLOTSTS_MRL_SENSOR_CHANGED) { 801 KSTAT_EVENT(slot_p, mrl_chg, now); 802 /* For now (phase-I), no action is taken on this event */ 803 PCIE_DBG("pciehpc_intr(): MRL SENSOR CHANGED interrupt received" 804 " on slot %d\n", slot_p->hs_phy_slot_num); 805 } 806 807 /* check for PRESENCE CHANGED interrupt */ 808 if (status & PCIE_SLOTSTS_PRESENCE_CHANGED) { 809 KSTAT_EVENT(slot_p, pres_chg, now); 810 PCIE_DBG("pciehpc_intr(): PRESENCE CHANGED interrupt received" 811 " on slot %d\n", slot_p->hs_phy_slot_num); 812 813 if (status & PCIE_SLOTSTS_PRESENCE_DETECTED) { 814 ddi_hp_cn_state_t tgt_state = (pcie_auto_online != 0) ? 815 DDI_HP_CN_STATE_ENABLED : DDI_HP_CN_STATE_PRESENT; 816 /* 817 * card is inserted into the slot, ask DDI Hotplug 818 * framework to change state to Present. 819 */ 820 cmn_err(CE_NOTE, "pciehpc (%s%d): card is inserted" 821 " in the slot %s", 822 ddi_driver_name(dip), 823 ddi_get_instance(dip), 824 slot_p->hs_info.cn_name); 825 826 (void) ndi_hp_state_change_req(dip, 827 slot_p->hs_info.cn_name, 828 tgt_state, DDI_HP_REQ_ASYNC); 829 } else { /* card is removed from the slot */ 830 cmn_err(CE_NOTE, "pciehpc (%s%d): card is removed" 831 " from the slot %s", 832 ddi_driver_name(dip), 833 ddi_get_instance(dip), 834 slot_p->hs_info.cn_name); 835 836 if (slot_p->hs_info.cn_state == 837 DDI_HP_CN_STATE_ENABLED) { 838 /* Card is removed when slot is enabled */ 839 slot_p->hs_condition = AP_COND_FAILED; 840 } else { 841 slot_p->hs_condition = AP_COND_UNKNOWN; 842 } 843 /* make sure to disable power fault detction intr */ 844 control = pciehpc_reg_get16(ctrl_p, 845 bus_p->bus_pcie_off + PCIE_SLOTCTL); 846 847 if (control & PCIE_SLOTCTL_PWR_FAULT_EN) 848 pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off + 849 PCIE_SLOTCTL, 850 control & ~PCIE_SLOTCTL_PWR_FAULT_EN); 851 852 /* 853 * If supported, notify the child device driver that the 854 * device is being removed. 855 */ 856 dev_info_t *cdip = ddi_get_child(dip); 857 if (cdip != NULL) { 858 ddi_eventcookie_t rm_cookie; 859 if (ddi_get_eventcookie(cdip, 860 DDI_DEVI_REMOVE_EVENT, 861 &rm_cookie) == DDI_SUCCESS) { 862 ndi_post_event(dip, cdip, rm_cookie, 863 NULL); 864 } 865 } 866 867 /* 868 * Ask DDI Hotplug framework to change state to Empty 869 */ 870 (void) ndi_hp_state_change_req(dip, 871 slot_p->hs_info.cn_name, 872 DDI_HP_CN_STATE_EMPTY, 873 DDI_HP_REQ_ASYNC); 874 } 875 876 clear_pend = B_TRUE; 877 } 878 879 /* check for DLL state changed interrupt */ 880 if (ctrl_p->hc_dll_active_rep && 881 (status & PCIE_SLOTSTS_DLL_STATE_CHANGED)) { 882 KSTAT_EVENT(slot_p, dll_chg, now); 883 PCIE_DBG("pciehpc_intr(): DLL STATE CHANGED interrupt received" 884 " on slot %d\n", slot_p->hs_phy_slot_num); 885 886 cv_signal(&slot_p->hs_dll_active_cv); 887 } 888 889 if (clear_pend) { 890 ctrl_p->hc_flags &= ~PCIE_HP_SYNC_PENDING; 891 } 892 mutex_exit(&ctrl_p->hc_mutex); 893 894 return (DDI_INTR_CLAIMED); 895 } 896 897 /* 898 * Handle hotplug commands 899 * 900 * Note: This function is called by DDI HP framework at kernel context only 901 */ 902 int 903 pciehpc_hp_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op, 904 void *arg, void *result) 905 { 906 pcie_hp_ctrl_t *ctrl_p; 907 pcie_hp_slot_t *slot_p; 908 int ret = DDI_SUCCESS; 909 910 PCIE_DBG("pciehpc_hp_ops: dip=%p cn_name=%s op=%x arg=%p\n", 911 dip, cn_name, op, arg); 912 913 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) == NULL) 914 return (DDI_FAILURE); 915 916 slot_p = ctrl_p->hc_slots[0]; 917 918 if (strcmp(cn_name, slot_p->hs_info.cn_name) != 0) 919 return (DDI_EINVAL); 920 921 switch (op) { 922 case DDI_HPOP_CN_GET_STATE: 923 { 924 mutex_enter(&slot_p->hs_ctrl->hc_mutex); 925 926 /* get the current slot state */ 927 pciehpc_get_slot_state(slot_p); 928 929 *((ddi_hp_cn_state_t *)result) = slot_p->hs_info.cn_state; 930 931 mutex_exit(&slot_p->hs_ctrl->hc_mutex); 932 break; 933 } 934 case DDI_HPOP_CN_CHANGE_STATE: 935 { 936 ddi_hp_cn_state_t target_state = *(ddi_hp_cn_state_t *)arg; 937 938 mutex_enter(&slot_p->hs_ctrl->hc_mutex); 939 940 ret = pciehpc_change_slot_state(slot_p, target_state); 941 *(ddi_hp_cn_state_t *)result = slot_p->hs_info.cn_state; 942 943 mutex_exit(&slot_p->hs_ctrl->hc_mutex); 944 break; 945 } 946 case DDI_HPOP_CN_PROBE: 947 948 ret = pciehpc_slot_probe(slot_p); 949 950 break; 951 case DDI_HPOP_CN_UNPROBE: 952 ret = pciehpc_slot_unprobe(slot_p); 953 954 break; 955 case DDI_HPOP_CN_GET_PROPERTY: 956 ret = pciehpc_slot_get_property(slot_p, (uintptr_t)arg, 957 (uintptr_t)result); 958 break; 959 case DDI_HPOP_CN_SET_PROPERTY: 960 ret = pciehpc_slot_set_property(slot_p, (uintptr_t)arg, 961 (uintptr_t)result); 962 break; 963 default: 964 ret = DDI_ENOTSUP; 965 break; 966 } 967 968 return (ret); 969 } 970 971 /* 972 * Get the current state of the slot from the hw. 973 * 974 * The slot state should have been initialized before this function gets called. 975 */ 976 void 977 pciehpc_get_slot_state(pcie_hp_slot_t *slot_p) 978 { 979 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 980 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 981 uint16_t control, status; 982 ddi_hp_cn_state_t curr_state = slot_p->hs_info.cn_state; 983 984 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 985 986 /* read the Slot Control Register */ 987 control = pciehpc_reg_get16(ctrl_p, 988 bus_p->bus_pcie_off + PCIE_SLOTCTL); 989 990 /* 991 * These LEDs are always set to off because they don't exist. They are 992 * only here because the data structure is shared with the PCI SHPC 993 * logic. We do not pretend to implement it. 994 */ 995 slot_p->hs_fault_led_state = PCIE_HP_LED_OFF; 996 slot_p->hs_active_led_state = PCIE_HP_LED_OFF; 997 998 /* read the current Slot Status Register */ 999 status = pciehpc_reg_get16(ctrl_p, 1000 bus_p->bus_pcie_off + PCIE_SLOTSTS); 1001 1002 /* get POWER led state */ 1003 slot_p->hs_power_led_state = 1004 pciehpc_led_state_to_hpc(pcie_slotctl_pwr_indicator_get(control)); 1005 1006 /* get ATTN led state */ 1007 slot_p->hs_attn_led_state = 1008 pciehpc_led_state_to_hpc(pcie_slotctl_attn_indicator_get(control)); 1009 1010 if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) { 1011 /* no device present; slot is empty */ 1012 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_EMPTY; 1013 return; 1014 } 1015 1016 /* device is present */ 1017 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_PRESENT; 1018 1019 /* 1020 * If we have power control and power control is disabled, then we are 1021 * merely present. We cannot be POWERED or ENABLED without this being 1022 * active. 1023 */ 1024 if (ctrl_p->hc_has_pwr && (control & PCIE_SLOTCTL_PWR_CONTROL) != 0) { 1025 return; 1026 } 1027 1028 /* 1029 * To be in the ENABLED state that means that we have verified that the 1030 * device is ready to be used. This happens at different points in time 1031 * right now depending on whether or not we have a power controller and 1032 * should be consolidated in the future. Our main constraint is that the 1033 * kernel expects that when something is in the ENABLED state that probe 1034 * should succeed. 1035 * 1036 * For devices with a power controller, this is guaranteed as part of 1037 * the PRESENT->POWERED transition. For devices without a power 1038 * controller, we must assume that power is always applied (the slot 1039 * control register bit for power status is undefined). This means that 1040 * the POWERED->ENABLED transition point is where this occurs. 1041 * 1042 * This is all a long way of justifying the logic below. If our current 1043 * state is enabled then we will stay in enabled; however, if it is 1044 * anything else we will go to powered and allow the normal state 1045 * transition to take effect. 1046 */ 1047 if (curr_state == DDI_HP_CN_STATE_ENABLED) { 1048 slot_p->hs_info.cn_state = curr_state; 1049 } else { 1050 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_POWERED; 1051 } 1052 } 1053 1054 /* 1055 * setup slot name/slot-number info. 1056 */ 1057 void 1058 pciehpc_set_slot_name(pcie_hp_ctrl_t *ctrl_p) 1059 { 1060 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1061 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1062 uchar_t *slotname_data; 1063 int *slotnum; 1064 uint_t count; 1065 int len; 1066 int invalid_slotnum = 0; 1067 uint32_t slot_capabilities; 1068 1069 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, ctrl_p->hc_dip, 1070 DDI_PROP_DONTPASS, "physical-slot#", &slotnum, &count) == 1071 DDI_PROP_SUCCESS) { 1072 slot_p->hs_phy_slot_num = slotnum[0]; 1073 ddi_prop_free(slotnum); 1074 } else { 1075 slot_capabilities = pciehpc_reg_get32(ctrl_p, 1076 bus_p->bus_pcie_off + PCIE_SLOTCAP); 1077 slot_p->hs_phy_slot_num = 1078 PCIE_SLOTCAP_PHY_SLOT_NUM(slot_capabilities); 1079 } 1080 1081 /* platform may not have initialized it */ 1082 if (!slot_p->hs_phy_slot_num) { 1083 PCIE_DBG("%s#%d: Invalid slot number!\n", 1084 ddi_driver_name(ctrl_p->hc_dip), 1085 ddi_get_instance(ctrl_p->hc_dip)); 1086 slot_p->hs_phy_slot_num = pciehpc_reg_get8(ctrl_p, 1087 PCI_BCNF_SECBUS); 1088 invalid_slotnum = 1; 1089 } 1090 slot_p->hs_info.cn_num = slot_p->hs_phy_slot_num; 1091 slot_p->hs_info.cn_num_dpd_on = DDI_HP_CN_NUM_NONE; 1092 1093 /* 1094 * construct the slot_name: 1095 * if "slot-names" property exists then use that name 1096 * else if valid slot number exists then it is "pcie<slot-num>". 1097 * else it will be "pcie<sec-bus-number>dev0" 1098 */ 1099 if (ddi_getlongprop(DDI_DEV_T_ANY, ctrl_p->hc_dip, DDI_PROP_DONTPASS, 1100 "slot-names", (caddr_t)&slotname_data, &len) == DDI_PROP_SUCCESS) { 1101 char tmp_name[256]; 1102 1103 /* 1104 * Note: for PCI-E slots, the device number is always 0 so the 1105 * first (and only) string is the slot name for this slot. 1106 */ 1107 (void) snprintf(tmp_name, sizeof (tmp_name), 1108 (char *)slotname_data + 4); 1109 slot_p->hs_info.cn_name = ddi_strdup(tmp_name, KM_SLEEP); 1110 kmem_free(slotname_data, len); 1111 } else { 1112 if (invalid_slotnum) { 1113 /* use device number ie. 0 */ 1114 slot_p->hs_info.cn_name = ddi_strdup("pcie0", 1115 KM_SLEEP); 1116 } else { 1117 char tmp_name[256]; 1118 1119 (void) snprintf(tmp_name, sizeof (tmp_name), "pcie%d", 1120 slot_p->hs_phy_slot_num); 1121 slot_p->hs_info.cn_name = ddi_strdup(tmp_name, 1122 KM_SLEEP); 1123 } 1124 } 1125 } 1126 1127 /* 1128 * Read/Write access to HPC registers. If platform nexus has non-standard 1129 * HPC access mechanism then regops functions are used to do reads/writes. 1130 */ 1131 uint8_t 1132 pciehpc_reg_get8(pcie_hp_ctrl_t *ctrl_p, uint_t off) 1133 { 1134 if (ctrl_p->hc_regops.get != NULL) { 1135 return ((uint8_t)ctrl_p->hc_regops.get( 1136 ctrl_p->hc_regops.cookie, (off_t)off)); 1137 } else { 1138 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1139 1140 return (pci_config_get8(bus_p->bus_cfg_hdl, off)); 1141 } 1142 } 1143 1144 uint16_t 1145 pciehpc_reg_get16(pcie_hp_ctrl_t *ctrl_p, uint_t off) 1146 { 1147 if (ctrl_p->hc_regops.get != NULL) { 1148 return ((uint16_t)ctrl_p->hc_regops.get( 1149 ctrl_p->hc_regops.cookie, (off_t)off)); 1150 } else { 1151 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1152 1153 return (pci_config_get16(bus_p->bus_cfg_hdl, off)); 1154 } 1155 } 1156 1157 uint32_t 1158 pciehpc_reg_get32(pcie_hp_ctrl_t *ctrl_p, uint_t off) 1159 { 1160 if (ctrl_p->hc_regops.get != NULL) { 1161 return ((uint32_t)ctrl_p->hc_regops.get( 1162 ctrl_p->hc_regops.cookie, (off_t)off)); 1163 } else { 1164 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1165 1166 return (pci_config_get32(bus_p->bus_cfg_hdl, off)); 1167 } 1168 } 1169 1170 void 1171 pciehpc_reg_put8(pcie_hp_ctrl_t *ctrl_p, uint_t off, uint8_t val) 1172 { 1173 if (ctrl_p->hc_regops.put != NULL) { 1174 ctrl_p->hc_regops.put(ctrl_p->hc_regops.cookie, 1175 (off_t)off, (uint_t)val); 1176 } else { 1177 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1178 1179 pci_config_put8(bus_p->bus_cfg_hdl, off, val); 1180 } 1181 } 1182 1183 void 1184 pciehpc_reg_put16(pcie_hp_ctrl_t *ctrl_p, uint_t off, uint16_t val) 1185 { 1186 if (ctrl_p->hc_regops.put != NULL) { 1187 ctrl_p->hc_regops.put(ctrl_p->hc_regops.cookie, 1188 (off_t)off, (uint_t)val); 1189 } else { 1190 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1191 1192 pci_config_put16(bus_p->bus_cfg_hdl, off, val); 1193 } 1194 } 1195 1196 void 1197 pciehpc_reg_put32(pcie_hp_ctrl_t *ctrl_p, uint_t off, uint32_t val) 1198 { 1199 if (ctrl_p->hc_regops.put != NULL) { 1200 ctrl_p->hc_regops.put(ctrl_p->hc_regops.cookie, 1201 (off_t)off, (uint_t)val); 1202 } else { 1203 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1204 1205 pci_config_put32(bus_p->bus_cfg_hdl, off, val); 1206 } 1207 } 1208 1209 /* 1210 * ************************************************************************ 1211 * *** Local functions (called within this file) 1212 * *** PCIe Native Hotplug mode specific functions 1213 * ************************************************************************ 1214 */ 1215 1216 static uint8_t 1217 pciehpc_led_state_to_pcie(pcie_hp_led_state_t state) 1218 { 1219 switch (state) { 1220 case PCIE_HP_LED_ON: 1221 return (PCIE_SLOTCTL_INDICATOR_STATE_ON); 1222 case PCIE_HP_LED_BLINK: 1223 return (PCIE_SLOTCTL_INDICATOR_STATE_BLINK); 1224 case PCIE_HP_LED_OFF: 1225 default: 1226 return (PCIE_SLOTCTL_INDICATOR_STATE_OFF); 1227 } 1228 } 1229 1230 /* 1231 * This iterates over the logical led states that we have (in descending order) 1232 * and computes the resulting state that a given LED should have. User overrides 1233 * are applied elsewhere. 1234 */ 1235 static pcie_hp_led_state_t 1236 pciehpc_calc_logical_led(pcie_hp_slot_t *slot_p, pciehpc_led_plat_id_t led) 1237 { 1238 pcie_hp_led_state_t ret = PCIE_HP_LED_OFF; 1239 1240 for (uint_t i = PCIEHPC_LED_NSTATES; i > 0; i--) { 1241 const uint_t idx = i - 1; 1242 if (!slot_p->hs_led_plat_en[idx]) 1243 continue; 1244 1245 switch (slot_p->hs_led_plat_conf[idx].plps_acts[led]) { 1246 case PCIE_HLA_PASS: 1247 continue; 1248 case PCIE_HLA_OFF: 1249 return (PCIE_HP_LED_OFF); 1250 case PCIE_HLA_ON: 1251 return (PCIE_HP_LED_ON); 1252 case PCIE_HLA_BLINK: 1253 return (PCIE_HP_LED_BLINK); 1254 } 1255 } 1256 1257 return (ret); 1258 } 1259 1260 static void 1261 pciehpc_sync_leds_to_hw(pcie_hp_slot_t *slot_p) 1262 { 1263 pcie_hp_led_state_t power, attn; 1264 uint16_t orig_ctrl, ctrl; 1265 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 1266 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1267 1268 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 1269 1270 1271 if (slot_p->hs_power_usr_ovr) { 1272 power = slot_p->hs_power_usr_ovr_state; 1273 } else { 1274 power = pciehpc_calc_logical_led(slot_p, PCIEHPC_PLAT_ID_POWER); 1275 } 1276 1277 if (slot_p->hs_attn_usr_ovr) { 1278 attn = slot_p->hs_attn_usr_ovr_state; 1279 } else { 1280 attn = pciehpc_calc_logical_led(slot_p, PCIEHPC_PLAT_ID_ATTN); 1281 } 1282 1283 slot_p->hs_power_led_state = power; 1284 slot_p->hs_attn_led_state = attn; 1285 orig_ctrl = ctrl = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + 1286 PCIE_SLOTCTL); 1287 1288 ctrl = pcie_slotctl_attn_indicator_set(ctrl, 1289 pciehpc_led_state_to_pcie(attn)); 1290 ctrl = pcie_slotctl_pwr_indicator_set(ctrl, 1291 pciehpc_led_state_to_pcie(power)); 1292 if (orig_ctrl != ctrl) { 1293 pciehpc_issue_hpc_command(ctrl_p, ctrl); 1294 } 1295 } 1296 1297 /* 1298 * Initialize HPC hardware, install interrupt handler, etc. It doesn't 1299 * enable hot plug interrupts. 1300 * 1301 * (Note: It is called only from pciehpc_init().) 1302 */ 1303 static int 1304 pciehpc_hpc_init(pcie_hp_ctrl_t *ctrl_p) 1305 { 1306 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1307 uint16_t reg; 1308 1309 /* read the Slot Control Register */ 1310 reg = pciehpc_reg_get16(ctrl_p, 1311 bus_p->bus_pcie_off + PCIE_SLOTCTL); 1312 1313 /* disable all interrupts */ 1314 reg &= ~(PCIE_SLOTCTL_INTR_MASK); 1315 pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off + 1316 PCIE_SLOTCTL, reg); 1317 1318 /* clear any interrupt status bits */ 1319 reg = pciehpc_reg_get16(ctrl_p, 1320 bus_p->bus_pcie_off + PCIE_SLOTSTS); 1321 pciehpc_reg_put16(ctrl_p, 1322 bus_p->bus_pcie_off + PCIE_SLOTSTS, reg); 1323 1324 return (DDI_SUCCESS); 1325 } 1326 1327 /* 1328 * Uninitialize HPC hardware, uninstall interrupt handler, etc. 1329 * 1330 * (Note: It is called only from pciehpc_uninit().) 1331 */ 1332 static int 1333 pciehpc_hpc_uninit(pcie_hp_ctrl_t *ctrl_p) 1334 { 1335 /* disable interrupts */ 1336 (void) pciehpc_disable_intr(ctrl_p); 1337 1338 return (DDI_SUCCESS); 1339 } 1340 1341 /* 1342 * Initialize the PCIe LED tracking and policy. 1343 */ 1344 void 1345 pciehpc_led_init(pcie_hp_slot_t *slot_p) 1346 { 1347 int vid, did, subvid, subsys; 1348 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 1349 1350 slot_p->hs_power_usr_ovr = false; 1351 slot_p->hs_attn_usr_ovr = false; 1352 slot_p->hs_power_usr_ovr_state = PCIE_HP_LED_OFF; 1353 slot_p->hs_attn_usr_ovr_state = PCIE_HP_LED_OFF; 1354 bzero(slot_p->hs_led_plat_en, sizeof (slot_p->hs_led_plat_en)); 1355 1356 slot_p->hs_led_plat_conf = pciehpc_std_leds; 1357 1358 vid = ddi_prop_get_int(DDI_DEV_T_ANY, ctrl_p->hc_dip, DDI_PROP_DONTPASS, 1359 "vendor-id", PCI_EINVAL16); 1360 did = ddi_prop_get_int(DDI_DEV_T_ANY, ctrl_p->hc_dip, DDI_PROP_DONTPASS, 1361 "device-id", PCI_EINVAL16); 1362 subvid = ddi_prop_get_int(DDI_DEV_T_ANY, ctrl_p->hc_dip, 1363 DDI_PROP_DONTPASS, "subsystem-vendor-id", PCI_EINVAL16); 1364 subsys = ddi_prop_get_int(DDI_DEV_T_ANY, ctrl_p->hc_dip, 1365 DDI_PROP_DONTPASS, "subsystem-id", PCI_EINVAL16); 1366 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_led_plat_map); i++) { 1367 if (vid == pciehpc_led_plat_map[i].plpm_vid && 1368 did == pciehpc_led_plat_map[i].plpm_did && 1369 subvid == pciehpc_led_plat_map[i].plpm_svid && 1370 subsys == pciehpc_led_plat_map[i].plpm_ssys) { 1371 slot_p->hs_led_plat_conf = 1372 pciehpc_led_plat_map[i].plpm_map; 1373 break; 1374 } 1375 } 1376 1377 /* 1378 * Finally, enable the base state for the slot which is meant to always 1379 * be true. We'll catch up the rest of the states when we get the slot 1380 * state there. 1381 */ 1382 slot_p->hs_led_plat_en[PCIE_LL_BASE] = true; 1383 } 1384 1385 bool 1386 pciehpc_slot_kstat_init(pcie_hp_slot_t *slot_p) 1387 { 1388 /* 1389 * Many if not most PCs have firmware bugs that cause multiple slots to 1390 * end up with the same physical slot number in the slot cap register. 1391 * This is a clear and direct violation of PCIe4 7.5.3.9, but that 1392 * doesn't seem to matter to the people who write firmware. This is 1393 * going to end up confusing the hotplug subsystem and the time to deal 1394 * with it is probably before we arrive here, but in order to avoid 1395 * additional warning messages during boot on such machines, we will use 1396 * the hotplug-capable bridge's instance number when creating event 1397 * counter kstats instead of hs_phy_slot_num (or hs_info.cn_num, which 1398 * is usually the same). In the unlikely event that the broken firmware 1399 * has given us unique names (even if not slot numbers) for a slot, 1400 * we'll still have a unique name for each kstat, just as we will for 1401 * each AP. Otherwise the kstat names will at least match the still 1402 * possibly duplicated AP names. 1403 */ 1404 int inst = ddi_get_instance(slot_p->hs_ctrl->hc_dip); 1405 1406 /* 1407 * Although the interrupts we are counting are generated by the hotplug 1408 * controller, they are conceptually associated with the slot so we 1409 * store them with it. The PCIe hotplug controller as currently defined 1410 * supports only a single slot (0), but in principle a future controller 1411 * might support multiple slots and we would have some way of 1412 * determining the set of events that have been detected for each slot 1413 * even the state changes for all slots share a single interrupt. 1414 * 1415 * The statistics are persistent because we want to keep counting them 1416 * over the entire lifetime of this kernel; if the slot's occupant is 1417 * removed and that leads to pciehpc_uninit() being called, we don't 1418 * want to lose the previous statistics. Indeed, observing what led up 1419 * to such an event is a key purpose of this infrastructure. 1420 */ 1421 slot_p->hs_kstat = kstat_create_zone("pcie", inst, 1422 slot_p->hs_info.cn_name, "controller", KSTAT_TYPE_NAMED, 1423 sizeof (pciehpc_stat_data_t) / sizeof (kstat_named_t), 1424 KSTAT_FLAG_PERSISTENT, GLOBAL_ZONEID); 1425 1426 if (slot_p->hs_kstat == NULL) { 1427 PCIE_DBG("pciehpc_slot_kstat_init: %d:%s kstat_create failed", 1428 inst, slot_p->hs_info.cn_name); 1429 return (false); 1430 } 1431 1432 slot_p->hs_stat_data = (pciehpc_stat_data_t *)slot_p->hs_kstat->ks_data; 1433 1434 /* 1435 * We would like to report only the set of kstats that correspond to the 1436 * events for which the controller advertises support. However, it is 1437 * possible for a buggy controller to set status bits that correspond to 1438 * bits that aren't set in the capabilities register. If this were to 1439 * occur, we'll still increment the counters and the kstat framework 1440 * doesn't really guarantee that we're allowed to do so. Therefore we 1441 * will initialise all the counters, even those that should not or 1442 * cannot have meaningful values for this slot. 1443 */ 1444 kstat_named_init(&slot_p->hs_stat_data->psd_attnsw_count, 1445 "attention_switch_count", KSTAT_DATA_UINT64); 1446 kstat_named_init(&slot_p->hs_stat_data->psd_attnsw_ts, 1447 "attention_switch_ts", KSTAT_DATA_UINT64); 1448 kstat_named_init(&slot_p->hs_stat_data->psd_pwrflt_count, 1449 "power_fault_count", KSTAT_DATA_UINT64); 1450 kstat_named_init(&slot_p->hs_stat_data->psd_pwrflt_ts, 1451 "power_fault_ts", KSTAT_DATA_UINT64); 1452 kstat_named_init(&slot_p->hs_stat_data->psd_mrl_chg_count, 1453 "mrl_change_count", KSTAT_DATA_UINT64); 1454 kstat_named_init(&slot_p->hs_stat_data->psd_mrl_chg_ts, 1455 "mrl_change_ts", KSTAT_DATA_UINT64); 1456 kstat_named_init(&slot_p->hs_stat_data->psd_pres_chg_count, 1457 "presence_change_count", KSTAT_DATA_UINT64); 1458 kstat_named_init(&slot_p->hs_stat_data->psd_pres_chg_ts, 1459 "presence_change_ts", KSTAT_DATA_UINT64); 1460 kstat_named_init(&slot_p->hs_stat_data->psd_cmd_cpl_count, 1461 "command_completion_count", KSTAT_DATA_UINT64); 1462 kstat_named_init(&slot_p->hs_stat_data->psd_cmd_cpl_ts, 1463 "command_completion_ts", KSTAT_DATA_UINT64); 1464 kstat_named_init(&slot_p->hs_stat_data->psd_dll_chg_count, 1465 "dll_active_change_count", KSTAT_DATA_UINT64); 1466 kstat_named_init(&slot_p->hs_stat_data->psd_dll_chg_ts, 1467 "dll_active_change_ts", KSTAT_DATA_UINT64); 1468 kstat_named_init(&slot_p->hs_stat_data->psd_intr_count, 1469 "interrupt_count", KSTAT_DATA_UINT64); 1470 kstat_named_init(&slot_p->hs_stat_data->psd_intr_ts, 1471 "interrupt_ts", KSTAT_DATA_UINT64); 1472 1473 kstat_install(slot_p->hs_kstat); 1474 1475 return (true); 1476 } 1477 1478 /* 1479 * Setup slot information for use with DDI HP framework. Per the theory 1480 * statement, this is where we need to go through and look at whether or not we 1481 * have a child and whether or not we want the 1s later timeout to get things 1482 * into a reasonable state. 1483 */ 1484 static int 1485 pciehpc_slotinfo_init(pcie_hp_ctrl_t *ctrl_p) 1486 { 1487 uint32_t slot_capabilities, link_capabilities; 1488 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1489 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1490 boolean_t have_child; 1491 1492 /* 1493 * First we look to see if we have any children at all. If we do, then 1494 * we assume that things were initialized prior to our existence as 1495 * discussed by state initialization (2). 1496 */ 1497 ndi_devi_enter(ctrl_p->hc_dip); 1498 have_child = ddi_get_child(ctrl_p->hc_dip) != NULL; 1499 ndi_devi_exit(ctrl_p->hc_dip); 1500 1501 /* 1502 * There's no expectation for two threads to be here at the same time: 1503 * we arrive here through the attach path and the DDI guarantees 1504 * exclusion. We take the mutex because some of the functions we call 1505 * assert that we have it. 1506 */ 1507 mutex_enter(&ctrl_p->hc_mutex); 1508 /* 1509 * setup DDI HP framework slot information structure 1510 */ 1511 slot_p->hs_device_num = 0; 1512 1513 slot_p->hs_info.cn_type = DDI_HP_CN_TYPE_PCIE; 1514 slot_p->hs_info.cn_type_str = (ctrl_p->hc_regops.get == NULL) ? 1515 PCIE_NATIVE_HP_TYPE : PCIE_PROP_HP_TYPE; 1516 slot_p->hs_info.cn_child = NULL; 1517 1518 slot_p->hs_minor = 1519 PCI_MINOR_NUM(ddi_get_instance(ctrl_p->hc_dip), 1520 slot_p->hs_device_num); 1521 slot_p->hs_condition = AP_COND_UNKNOWN; 1522 1523 /* read Slot Capabilities Register */ 1524 slot_capabilities = pciehpc_reg_get32(ctrl_p, 1525 bus_p->bus_pcie_off + PCIE_SLOTCAP); 1526 1527 /* set slot-name/slot-number info */ 1528 pciehpc_set_slot_name(ctrl_p); 1529 1530 /* check if Attn Button present */ 1531 ctrl_p->hc_has_attn = (slot_capabilities & PCIE_SLOTCAP_ATTN_BUTTON) ? 1532 B_TRUE : B_FALSE; 1533 1534 /* check if Manual Retention Latch sensor present */ 1535 ctrl_p->hc_has_mrl = (slot_capabilities & PCIE_SLOTCAP_MRL_SENSOR) ? 1536 B_TRUE : B_FALSE; 1537 1538 /* 1539 * Contrary to what one might expect, not all systems actually have 1540 * power control despite having hot-swap capabilities. This is most 1541 * commonly due to the Enterprise SSD specification which doesn't call 1542 * for power-control in the PCIe native hotplug implementation. 1543 */ 1544 ctrl_p->hc_has_pwr = (slot_capabilities & 1545 PCIE_SLOTCAP_POWER_CONTROLLER) ? B_TRUE: B_FALSE; 1546 1547 /* 1548 * PCI-E version 1.1 defines EMI Lock Present bit 1549 * in Slot Capabilities register. Check for it. 1550 */ 1551 ctrl_p->hc_has_emi_lock = (slot_capabilities & 1552 PCIE_SLOTCAP_EMI_LOCK_PRESENT) ? B_TRUE : B_FALSE; 1553 1554 link_capabilities = pciehpc_reg_get32(ctrl_p, 1555 bus_p->bus_pcie_off + PCIE_LINKCAP); 1556 ctrl_p->hc_dll_active_rep = (link_capabilities & 1557 PCIE_LINKCAP_DLL_ACTIVE_REP_CAPABLE) ? B_TRUE : B_FALSE; 1558 if (ctrl_p->hc_dll_active_rep) 1559 cv_init(&slot_p->hs_dll_active_cv, NULL, CV_DRIVER, NULL); 1560 1561 /* setup thread for handling ATTN button events */ 1562 if (ctrl_p->hc_has_attn) { 1563 PCIE_DBG("pciehpc_slotinfo_init: setting up ATTN button event " 1564 "handler thread for slot %d\n", slot_p->hs_phy_slot_num); 1565 1566 cv_init(&slot_p->hs_attn_btn_cv, NULL, CV_DRIVER, NULL); 1567 slot_p->hs_attn_btn_pending = B_FALSE; 1568 slot_p->hs_attn_btn_threadp = thread_create(NULL, 0, 1569 pciehpc_attn_btn_handler, 1570 (void *)ctrl_p, 0, &p0, TS_RUN, minclsyspri); 1571 slot_p->hs_attn_btn_thread_exit = B_FALSE; 1572 } 1573 1574 /* 1575 * Initialize our LED state tracking. 1576 */ 1577 pciehpc_led_init(slot_p); 1578 1579 /* get current slot state from the hw */ 1580 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_EMPTY; 1581 pciehpc_get_slot_state(slot_p); 1582 1583 /* 1584 * If the kernel has enumerated a device, note that we have performed 1585 * the enabled transition. 1586 */ 1587 if (slot_p->hs_info.cn_state == DDI_HP_CN_STATE_POWERED && 1588 have_child) { 1589 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_ENABLED; 1590 } 1591 1592 if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED) 1593 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = true; 1594 1595 if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_ENABLED) 1596 slot_p->hs_condition = AP_COND_OK; 1597 mutex_exit(&ctrl_p->hc_mutex); 1598 1599 if (!pciehpc_slot_kstat_init(slot_p)) { 1600 (void) pciehpc_slotinfo_uninit(ctrl_p); 1601 return (DDI_FAILURE); 1602 } 1603 1604 return (DDI_SUCCESS); 1605 } 1606 1607 void 1608 pciehpc_slot_kstat_fini(pcie_hp_slot_t *slot_p) 1609 { 1610 if (slot_p->hs_kstat != NULL) { 1611 kstat_delete(slot_p->hs_kstat); 1612 slot_p->hs_kstat = NULL; 1613 slot_p->hs_stat_data = NULL; 1614 } 1615 } 1616 1617 static int 1618 pciehpc_slotinfo_uninit(pcie_hp_ctrl_t *ctrl_p) 1619 { 1620 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1621 1622 if (slot_p->hs_attn_btn_threadp != NULL) { 1623 mutex_enter(&ctrl_p->hc_mutex); 1624 slot_p->hs_attn_btn_thread_exit = B_TRUE; 1625 cv_signal(&slot_p->hs_attn_btn_cv); 1626 PCIE_DBG("pciehpc_slotinfo_uninit: " 1627 "waiting for ATTN thread exit\n"); 1628 cv_wait(&slot_p->hs_attn_btn_cv, &ctrl_p->hc_mutex); 1629 PCIE_DBG("pciehpc_slotinfo_uninit: ATTN thread exit\n"); 1630 cv_destroy(&slot_p->hs_attn_btn_cv); 1631 slot_p->hs_attn_btn_threadp = NULL; 1632 mutex_exit(&ctrl_p->hc_mutex); 1633 } 1634 1635 if (ctrl_p->hc_dll_active_rep) 1636 cv_destroy(&slot_p->hs_dll_active_cv); 1637 if (slot_p->hs_info.cn_name) 1638 kmem_free(slot_p->hs_info.cn_name, 1639 strlen(slot_p->hs_info.cn_name) + 1); 1640 1641 pciehpc_slot_kstat_fini(slot_p); 1642 1643 return (DDI_SUCCESS); 1644 } 1645 1646 /* 1647 * This is the synchronization function that is discussed in the 'State 1648 * Initialization' portion of the theory statement in this file. It is 1649 * responsible for trying to make sure that devices are in a usable state during 1650 * a potentially turbulent start up sequence. 1651 */ 1652 static void 1653 pciehpc_state_sync(void *arg) 1654 { 1655 pciehpc_sync_task_t *sync = arg; 1656 pcie_hp_ctrl_t *ctrl_p = sync->pst_ctrl; 1657 dev_info_t *dip = ctrl_p->hc_dip; 1658 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1659 1660 mutex_enter(&ctrl_p->hc_mutex); 1661 if (ctrl_p->hc_startup_sync == TASKQID_INVALID) { 1662 mutex_exit(&ctrl_p->hc_mutex); 1663 kmem_free(sync, sizeof (pciehpc_sync_task_t)); 1664 return; 1665 } 1666 1667 if ((ctrl_p->hc_flags & PCIE_HP_SYNC_PENDING) == 0) { 1668 goto done; 1669 } 1670 1671 cmn_err(CE_NOTE, "pciehpc (%s%d): synchronizing state in slot %s to " 1672 "0x%x", ddi_driver_name(dip), ddi_get_instance(dip), 1673 slot_p->hs_info.cn_name, sync->pst_targ); 1674 1675 ASSERT3U(slot_p->hs_info.cn_state, ==, sync->pst_cur); 1676 1677 ctrl_p->hc_flags &= ~PCIE_HP_SYNC_PENDING; 1678 ctrl_p->hc_flags |= PCIE_HP_SYNC_RUNNING; 1679 mutex_exit(&ctrl_p->hc_mutex); 1680 1681 (void) ndi_hp_state_change_req(dip, slot_p->hs_info.cn_name, 1682 sync->pst_targ, DDI_HP_REQ_SYNC); 1683 1684 /* 1685 * Now that we're done with operating this way, go ahead and clear 1686 * things up. 1687 */ 1688 mutex_enter(&ctrl_p->hc_mutex); 1689 done: 1690 ctrl_p->hc_flags &= ~PCIE_HP_SYNC_RUNNING; 1691 ctrl_p->hc_startup_sync = TASKQID_INVALID; 1692 mutex_exit(&ctrl_p->hc_mutex); 1693 kmem_free(sync, sizeof (pciehpc_sync_task_t)); 1694 } 1695 1696 static void 1697 pciehpc_dispatch_state_sync(pcie_hp_ctrl_t *ctrl_p, ddi_hp_cn_state_t targ) 1698 { 1699 pciehpc_sync_task_t *sync; 1700 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1701 1702 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 1703 sync = kmem_alloc(sizeof (pciehpc_sync_task_t), KM_SLEEP); 1704 sync->pst_ctrl = ctrl_p; 1705 sync->pst_targ = targ; 1706 sync->pst_cur = slot_p->hs_info.cn_state; 1707 1708 ctrl_p->hc_flags |= PCIE_HP_SYNC_PENDING; 1709 ctrl_p->hc_startup_sync = taskq_dispatch(system_taskq, 1710 pciehpc_state_sync, sync, TQ_SLEEP); 1711 } 1712 1713 /* 1714 * The point of this is to forcibly set the logical LED states to the 1715 * corresponding ones that make sense for the corresponding hotplug state. 1716 */ 1717 static void 1718 pciehpc_enable_state_sync_leds(pcie_hp_ctrl_t *ctrl_p) 1719 { 1720 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1721 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 1722 1723 bzero(slot_p->hs_led_plat_en, sizeof (slot_p->hs_led_plat_en)); 1724 1725 switch (slot_p->hs_info.cn_state) { 1726 case DDI_HP_CN_STATE_ENABLED: 1727 case DDI_HP_CN_STATE_POWERED: 1728 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = true; 1729 slot_p->hs_led_plat_en[PCIE_LL_BASE] = true; 1730 break; 1731 case DDI_HP_CN_STATE_PRESENT: 1732 case DDI_HP_CN_STATE_EMPTY: 1733 slot_p->hs_led_plat_en[PCIE_LL_BASE] = true; 1734 break; 1735 default: 1736 dev_err(ctrl_p->hc_dip, CE_PANIC, "encountered invalid " 1737 "connector state: 0x%x", slot_p->hs_info.cn_state); 1738 break; 1739 } 1740 1741 pciehpc_sync_leds_to_hw(slot_p); 1742 } 1743 1744 /* 1745 * We have just enabled interrupts and cleared any changes that may or may not 1746 * have been valid from the hardware perspective. There are a few key 1747 * assumptions that we're making right now as discussed in the theory statement: 1748 * 1749 * o If we are currently enabled, then we know that we have children and 1750 * nothing has changed from our init. 1751 * o Because we have just enabled interrupts, but have not relinquished our 1752 * exclusion on the controller hardware, nothing else could have come in and 1753 * started reacting to an actual change. 1754 * o Even though someone could come and call DDI_HPOP_CN_GET_STATE, that could 1755 * not transition us to enabled yet. 1756 * o Because interrupt enable is still called in attach context, we cannot have 1757 * a user accessing the node and requesting a state change. 1758 * 1759 * Finally there are a few things that we need to be mindful of. We must set any 1760 * updates to the state prior to calling into any request to update the LED 1761 * state as that may rely on getting an async callback. 1762 */ 1763 static void 1764 pciehpc_enable_state_sync(pcie_hp_ctrl_t *ctrl_p) 1765 { 1766 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1767 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1768 uint16_t control, status; 1769 ddi_hp_cn_state_t curr_state, online_targ; 1770 1771 online_targ = (pcie_auto_online != 0) ? DDI_HP_CN_STATE_ENABLED : 1772 DDI_HP_CN_STATE_PRESENT; 1773 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 1774 1775 /* 1776 * We manually compute the status from a single read of things rather 1777 * than go through and use pciehpc_get_slot_state(). This is important 1778 * to make sure that we can get hardware in sync with the kernel. 1779 */ 1780 curr_state = slot_p->hs_info.cn_state; 1781 control = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTCTL); 1782 status = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTSTS); 1783 1784 if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) { 1785 switch (curr_state) { 1786 case DDI_HP_CN_STATE_ENABLED: 1787 pciehpc_dispatch_state_sync(ctrl_p, 1788 DDI_HP_CN_STATE_EMPTY); 1789 break; 1790 case DDI_HP_CN_STATE_EMPTY: 1791 case DDI_HP_CN_STATE_PRESENT: 1792 case DDI_HP_CN_STATE_POWERED: 1793 if (ctrl_p->hc_has_pwr && 1794 (control & PCIE_SLOTCTL_PWR_CONTROL) == 0) { 1795 slot_p->hs_info.cn_state = 1796 DDI_HP_CN_STATE_POWERED; 1797 pciehpc_dispatch_state_sync(ctrl_p, 1798 DDI_HP_CN_STATE_EMPTY); 1799 } else { 1800 slot_p->hs_info.cn_state = 1801 DDI_HP_CN_STATE_EMPTY; 1802 pciehpc_enable_state_sync_leds(ctrl_p); 1803 } 1804 break; 1805 default: 1806 dev_err(ctrl_p->hc_dip, CE_PANIC, "encountered invalid " 1807 "connector state: 0x%x", curr_state); 1808 break; 1809 } 1810 1811 return; 1812 } 1813 1814 /* 1815 * If we don't have a power controller, don't bother looking at this. 1816 * There's nothing we can really do and we'll let the main case attempt 1817 * to online this. 1818 */ 1819 if (ctrl_p->hc_has_pwr && (control & PCIE_SLOTCTL_PWR_CONTROL) != 0) { 1820 switch (curr_state) { 1821 case DDI_HP_CN_STATE_EMPTY: 1822 pciehpc_dispatch_state_sync(ctrl_p, online_targ); 1823 break; 1824 case DDI_HP_CN_STATE_PRESENT: 1825 if (curr_state == online_targ) { 1826 pciehpc_enable_state_sync_leds(ctrl_p); 1827 break; 1828 } 1829 pciehpc_dispatch_state_sync(ctrl_p, online_targ); 1830 break; 1831 case DDI_HP_CN_STATE_POWERED: 1832 dev_err(ctrl_p->hc_dip, CE_WARN, "device powered off " 1833 "somehow from prior powered state, attempting " 1834 "recovery"); 1835 slot_p->hs_info.cn_state = DDI_HP_CN_STATE_PRESENT; 1836 if (online_targ > DDI_HP_CN_STATE_PRESENT) { 1837 pciehpc_dispatch_state_sync(ctrl_p, 1838 online_targ); 1839 } else { 1840 pciehpc_enable_state_sync_leds(ctrl_p); 1841 } 1842 break; 1843 case DDI_HP_CN_STATE_ENABLED: 1844 /* 1845 * This case seems very strange. We had a device that we 1846 * enumerated and was online and something that wasn't 1847 * us powerd off the slot. This is possibly a 1848 * recoverable state, but it seems hard to understand 1849 * what the proper path to go here is. While we could 1850 * try to unprobe it, it's a real mystery how that 1851 * happened and even that path might not be safe. If 1852 * this kind of state is actually encountered in the 1853 * wild and during this startup window of the device, 1854 * then we'll need to figure out how to handle it there. 1855 * Odds are it's either a software bug in this driver or 1856 * something is going very wrong with hardware and as 1857 * such, it's hard to predict what the solution is. 1858 */ 1859 dev_err(ctrl_p->hc_dip, CE_PANIC, "device powered off " 1860 "somehow from prior enabled state unable to " 1861 "recover"); 1862 break; 1863 default: 1864 dev_err(ctrl_p->hc_dip, CE_PANIC, "encountered invalid " 1865 "connector state: 0x%x", curr_state); 1866 } 1867 return; 1868 } 1869 1870 /* 1871 * While we should consider checking for a power fault here, if it was 1872 * injected just after we cleared everythign as part of interrupt 1873 * enable, then we'll get that injected normally and allow that to 1874 * happen naturally. 1875 */ 1876 1877 switch (curr_state) { 1878 case DDI_HP_CN_STATE_ENABLED: 1879 pciehpc_enable_state_sync_leds(ctrl_p); 1880 break; 1881 case DDI_HP_CN_STATE_POWERED: 1882 case DDI_HP_CN_STATE_EMPTY: 1883 case DDI_HP_CN_STATE_PRESENT: 1884 if (curr_state == online_targ) { 1885 pciehpc_enable_state_sync_leds(ctrl_p); 1886 } else { 1887 pciehpc_dispatch_state_sync(ctrl_p, online_targ); 1888 } 1889 break; 1890 default: 1891 dev_err(ctrl_p->hc_dip, CE_PANIC, "encountered invalid " 1892 "connector state: 0x%x", curr_state); 1893 } 1894 } 1895 1896 /* 1897 * Enable hot plug interrupts. 1898 * Note: this is only for Native hot plug mode. 1899 */ 1900 static int 1901 pciehpc_enable_intr(pcie_hp_ctrl_t *ctrl_p) 1902 { 1903 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 1904 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1905 uint16_t reg; 1906 uint16_t intr_mask = PCIE_SLOTCTL_INTR_MASK; 1907 1908 mutex_enter(&ctrl_p->hc_mutex); 1909 1910 /* 1911 * power fault detection interrupt is enabled only 1912 * when the slot is powered ON 1913 */ 1914 if (slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED) 1915 intr_mask &= ~PCIE_SLOTCTL_PWR_FAULT_EN; 1916 1917 /* 1918 * enable interrupt sources but leave the top-level 1919 * interrupt disabled. some sources may generate a 1920 * spurrious event when they are first enabled. 1921 * by leaving the top-level interrupt disabled, those 1922 * can be cleared first. 1923 */ 1924 reg = pciehpc_reg_get16(ctrl_p, 1925 bus_p->bus_pcie_off + PCIE_SLOTCTL); 1926 pciehpc_reg_put16(ctrl_p, 1927 bus_p->bus_pcie_off + PCIE_SLOTCTL, 1928 reg | (intr_mask & ~PCIE_SLOTCTL_HP_INTR_EN)); 1929 1930 /* clear any interrupt status bits */ 1931 reg = pciehpc_reg_get16(ctrl_p, 1932 bus_p->bus_pcie_off + PCIE_SLOTSTS); 1933 pciehpc_reg_put16(ctrl_p, 1934 bus_p->bus_pcie_off + PCIE_SLOTSTS, reg); 1935 1936 /* enable top-level interrupt */ 1937 reg = pciehpc_reg_get16(ctrl_p, 1938 bus_p->bus_pcie_off + PCIE_SLOTCTL); 1939 pciehpc_reg_put16(ctrl_p, 1940 bus_p->bus_pcie_off + PCIE_SLOTCTL, 1941 reg | intr_mask); 1942 1943 /* 1944 * Now, and only now that interrupts are enabled can we go back and 1945 * perform state synchronization that is required of the system. This 1946 * happens in a few steps. We have previously checked to see if we 1947 * should be in the ENABLED or POWERED state. However, it is quite 1948 * possible that hardware was left at its PCIe default of power being 1949 * enabled, even if no device is present. Because we have interrupts 1950 * enabled, if there is a change after this point, then it will be 1951 * caught. See the theory statement for more information. 1952 */ 1953 pciehpc_enable_state_sync(ctrl_p); 1954 mutex_exit(&ctrl_p->hc_mutex); 1955 1956 return (DDI_SUCCESS); 1957 } 1958 1959 /* 1960 * Disable hot plug interrupts. 1961 * Note: this is only for Native hot plug mode. 1962 */ 1963 static int 1964 pciehpc_disable_intr(pcie_hp_ctrl_t *ctrl_p) 1965 { 1966 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 1967 uint16_t reg; 1968 1969 /* read the Slot Control Register */ 1970 reg = pciehpc_reg_get16(ctrl_p, 1971 bus_p->bus_pcie_off + PCIE_SLOTCTL); 1972 1973 /* disable all interrupts */ 1974 reg &= ~(PCIE_SLOTCTL_INTR_MASK); 1975 pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTCTL, reg); 1976 1977 /* clear any interrupt status bits */ 1978 reg = pciehpc_reg_get16(ctrl_p, 1979 bus_p->bus_pcie_off + PCIE_SLOTSTS); 1980 pciehpc_reg_put16(ctrl_p, 1981 bus_p->bus_pcie_off + PCIE_SLOTSTS, reg); 1982 1983 return (DDI_SUCCESS); 1984 } 1985 1986 /* 1987 * Allocate a new hotplug controller and slot structures for HPC 1988 * associated with this dip. 1989 */ 1990 static pcie_hp_ctrl_t * 1991 pciehpc_create_controller(dev_info_t *dip) 1992 { 1993 pcie_hp_ctrl_t *ctrl_p; 1994 pcie_bus_t *bus_p = PCIE_DIP2BUS(dip); 1995 1996 ctrl_p = kmem_zalloc(sizeof (pcie_hp_ctrl_t), KM_SLEEP); 1997 ctrl_p->hc_dip = dip; 1998 1999 /* Allocate a new slot structure. */ 2000 ctrl_p->hc_slots[0] = kmem_zalloc(sizeof (pcie_hp_slot_t), KM_SLEEP); 2001 ctrl_p->hc_slots[0]->hs_num = 0; 2002 ctrl_p->hc_slots[0]->hs_ctrl = ctrl_p; 2003 2004 /* Initialize the interrupt mutex */ 2005 mutex_init(&ctrl_p->hc_mutex, NULL, MUTEX_DRIVER, 2006 (void *)PCIE_INTR_PRI); 2007 2008 /* Initialize synchronization conditional variable */ 2009 cv_init(&ctrl_p->hc_cmd_comp_cv, NULL, CV_DRIVER, NULL); 2010 ctrl_p->hc_cmd_pending = B_FALSE; 2011 2012 bus_p->bus_hp_curr_mode = PCIE_NATIVE_HP_MODE; 2013 PCIE_SET_HP_CTRL(dip, ctrl_p); 2014 2015 return (ctrl_p); 2016 } 2017 2018 /* 2019 * Remove the HPC controller and slot structures 2020 */ 2021 static void 2022 pciehpc_destroy_controller(dev_info_t *dip) 2023 { 2024 pcie_hp_ctrl_t *ctrl_p; 2025 pcie_bus_t *bus_p = PCIE_DIP2BUS(dip); 2026 2027 /* get the soft state structure for this dip */ 2028 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) == NULL) 2029 return; 2030 2031 PCIE_SET_HP_CTRL(dip, NULL); 2032 bus_p->bus_hp_curr_mode = PCIE_NONE_HP_MODE; 2033 2034 mutex_destroy(&ctrl_p->hc_mutex); 2035 cv_destroy(&ctrl_p->hc_cmd_comp_cv); 2036 kmem_free(ctrl_p->hc_slots[0], sizeof (pcie_hp_slot_t)); 2037 kmem_free(ctrl_p, sizeof (pcie_hp_ctrl_t)); 2038 } 2039 2040 /* 2041 * Register the PCI-E hot plug slot with DDI HP framework. 2042 */ 2043 static int 2044 pciehpc_register_slot(pcie_hp_ctrl_t *ctrl_p) 2045 { 2046 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 2047 dev_info_t *dip = ctrl_p->hc_dip; 2048 2049 /* register the slot with DDI HP framework */ 2050 if (ndi_hp_register(dip, &slot_p->hs_info) != NDI_SUCCESS) { 2051 PCIE_DBG("pciehpc_register_slot() failed to register slot %d\n", 2052 slot_p->hs_phy_slot_num); 2053 return (DDI_FAILURE); 2054 } 2055 2056 pcie_hp_create_occupant_props(dip, makedevice(ddi_driver_major(dip), 2057 slot_p->hs_minor), slot_p->hs_device_num); 2058 2059 PCIE_DBG("pciehpc_register_slot(): registered slot %d\n", 2060 slot_p->hs_phy_slot_num); 2061 2062 return (DDI_SUCCESS); 2063 } 2064 2065 /* 2066 * Unregister the PCI-E hot plug slot from DDI HP framework. 2067 */ 2068 static int 2069 pciehpc_unregister_slot(pcie_hp_ctrl_t *ctrl_p) 2070 { 2071 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 2072 dev_info_t *dip = ctrl_p->hc_dip; 2073 2074 pcie_hp_delete_occupant_props(dip, makedevice(ddi_driver_major(dip), 2075 slot_p->hs_minor)); 2076 2077 /* unregister the slot with DDI HP framework */ 2078 if (ndi_hp_unregister(dip, slot_p->hs_info.cn_name) != NDI_SUCCESS) { 2079 PCIE_DBG("pciehpc_unregister_slot() " 2080 "failed to unregister slot %d\n", slot_p->hs_phy_slot_num); 2081 return (DDI_FAILURE); 2082 } 2083 2084 PCIE_DBG("pciehpc_unregister_slot(): unregistered slot %d\n", 2085 slot_p->hs_phy_slot_num); 2086 2087 return (DDI_SUCCESS); 2088 } 2089 2090 static pciehpc_slot_power_t 2091 pciehpc_slot_power_state(pcie_hp_slot_t *slot_p) 2092 { 2093 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2094 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 2095 uint16_t control, status; 2096 pciehpc_slot_power_t state = 0; 2097 2098 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 2099 2100 if (!ctrl_p->hc_has_pwr) { 2101 return (PSP_NO_CONTROLLER); 2102 } else { 2103 state |= PSP_HAS_CONTROLLER; 2104 } 2105 2106 control = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTCTL); 2107 status = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTSTS); 2108 2109 if ((control & PCIE_SLOTCTL_PWR_CONTROL) != 0) 2110 state |= PSP_OFF; 2111 2112 if ((status & PCIE_SLOTSTS_PWR_FAULT_DETECTED) != 0) 2113 state |= PSP_FAULT; 2114 2115 return (state); 2116 } 2117 2118 /* 2119 * Wait for a PCIe slot to be considered active per the PCIe hotplug rules. If 2120 * there is no DLL active reporting capability then we wait up to 1 second and 2121 * just assume it was successful. Regardless of whether or not we have explicit 2122 * power control, the device is still powering on and may not be ready to work. 2123 */ 2124 static boolean_t 2125 pciehpc_slot_wait_for_active(pcie_hp_slot_t *slot_p) 2126 { 2127 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2128 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 2129 2130 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 2131 2132 if (ctrl_p->hc_dll_active_rep) { 2133 clock_t deadline; 2134 uint16_t status; 2135 2136 /* wait 1 sec for the DLL State Changed event */ 2137 status = pciehpc_reg_get16(ctrl_p, 2138 bus_p->bus_pcie_off + PCIE_LINKSTS); 2139 2140 deadline = ddi_get_lbolt() + 2141 SEC_TO_TICK(PCIE_HP_DLL_STATE_CHANGE_TIMEOUT); 2142 2143 while ((status & PCIE_LINKSTS_DLL_LINK_ACTIVE) == 0 && 2144 ddi_get_lbolt() < deadline) { 2145 (void) cv_timedwait(&slot_p->hs_dll_active_cv, 2146 &ctrl_p->hc_mutex, deadline); 2147 2148 /* check Link status */ 2149 status = pciehpc_reg_get16(ctrl_p, 2150 bus_p->bus_pcie_off + 2151 PCIE_LINKSTS); 2152 } 2153 2154 if ((status & PCIE_LINKSTS_DLL_LINK_ACTIVE) == 0) { 2155 return (B_FALSE); 2156 } 2157 } else { 2158 /* wait 1 sec for link to come up */ 2159 delay(drv_usectohz(1000000)); 2160 } 2161 2162 return (B_TRUE); 2163 } 2164 2165 /* 2166 * This takes care of all the logic for trying to verify a slot's state that 2167 * does not have an explicit power controller. If this is a surprise insertion, 2168 * we still need to wait for the data link layer to become active even if we 2169 * don't explicitly control power. We do this in three steps: 2170 * 2171 * 1) Verify the slot is powered at least. 2172 * 2) Wait for the slot to be active. 2173 * 3) Verify the slot is still powered after that. 2174 */ 2175 static int 2176 pciehpc_slot_noctrl_active(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result) 2177 { 2178 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2179 2180 VERIFY3U(ctrl_p->hc_has_pwr, ==, B_FALSE); 2181 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 2182 2183 pciehpc_get_slot_state(slot_p); 2184 if (slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED) { 2185 return (DDI_FAILURE); 2186 } 2187 2188 /* 2189 * Regardless of whether this worked or failed we must check the slot 2190 * state again. 2191 */ 2192 if (!pciehpc_slot_wait_for_active(slot_p)) { 2193 cmn_err(CE_WARN, "pciehpc_slot_poweron_noctrl (slot %d): " 2194 "device failed to become active", slot_p->hs_phy_slot_num); 2195 return (DDI_FAILURE); 2196 } 2197 pciehpc_get_slot_state(slot_p); 2198 *result = slot_p->hs_info.cn_state; 2199 if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED) { 2200 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = true; 2201 slot_p->hs_led_plat_en[PCIE_LL_POWER_FAULT] = false; 2202 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2203 pciehpc_sync_leds_to_hw(slot_p); 2204 return (DDI_SUCCESS); 2205 } else { 2206 return (DDI_FAILURE); 2207 } 2208 } 2209 2210 /* 2211 * Poweron/Enable the slot. 2212 * 2213 * Note: This function is called by DDI HP framework at kernel context only 2214 * 2215 * We intend for this function to be idempotent. That is, when we return, if 2216 * the slot we've been asked to turn on has a device present, and has a power 2217 * controller, then a successful return guarantees all of the following, 2218 * regardless of the hardware or software state that existed when called: 2219 * 2220 * 1. The power controller enable bit is clear (asserted). 2221 * 2. If DLL State Change is supported by the bridge, we waited until DLL Active 2222 * was asserted; otherwise we waited at least one second after the first 2223 * moment we knew for certain that the power controller was enabled. 2224 * 3. Any power fault that was previously asserted in the status register has 2225 * been acknowledged and cleared, allowing detection of subsequent faults if 2226 * supported by hardware. 2227 * 4. The power indicator is on (if it exists). 2228 * 5. The MRL, if it exists, is latched. 2229 * 2230 * If we fail, either this slot has no power control capability or the following 2231 * guarantees are made: 2232 * 2233 * 1. We have attempted to disable the power controller for this slot. 2234 * 2. We have attempted to disable the power indicator for this slot. 2235 * 2236 * In the failure case, *result has undefined contents. This function does not 2237 * change the contents of slot_p->hs_info.cn_state. This allows callers to act 2238 * upon the previous software state (preserved by this function), the new 2239 * software state (in *result if successful), and the current hardware state 2240 * which can be obtained via pciehpc_get_slot_state(). 2241 */ 2242 static int 2243 pciehpc_slot_poweron(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result) 2244 { 2245 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2246 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 2247 uint16_t status, control; 2248 2249 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 2250 2251 /* 2252 * If the hardware doesn't have support for a power controller, then 2253 * that generally means that power is already on or at the least there 2254 * isn't very much else we can do and the PCIe spec says it's the 2255 * responsibility of the controller to have turned it on if a device is 2256 * present. We don't care whether a device is present in this case, 2257 * though, because we've been asked to turn on power and we know that we 2258 * cannot. Either a device is present and power is already on, in which 2259 * case calling code can figure that out, or no device is present and 2260 * we'd fail even if we had a controller. Either way, we still indicate 2261 * that is a failure since we can't change it and instead rely on code 2262 * executing the actual state machine to figure out how to handle this. 2263 */ 2264 if (!ctrl_p->hc_has_pwr) { 2265 PCIE_DBG("pciehpc_slot_poweron (slot %d): no power control " 2266 "capability, but was asked to power on\n", 2267 slot_p->hs_phy_slot_num); 2268 return (DDI_FAILURE); 2269 } 2270 2271 /* 2272 * We need the current state of the slot control register to figure out 2273 * whether the power controller is enabled already. Note that this is 2274 * not a status bit: it can't tell us whether power is actually on or 2275 * off, only what the last control input was. We also grab the status 2276 * register here as we need several bits from it. 2277 */ 2278 control = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTCTL); 2279 status = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTSTS); 2280 2281 /* 2282 * If there's no device present, we need to fail. 2283 */ 2284 if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) { 2285 /* slot is empty */ 2286 PCIE_DBG("pciehpc_slot_poweron (slot %d): slot is empty\n", 2287 slot_p->hs_phy_slot_num); 2288 goto cleanup; 2289 } 2290 2291 /* 2292 * If there's an MRL and it's open, we need to fail. 2293 */ 2294 if ((ctrl_p->hc_has_mrl) && (status & PCIE_SLOTSTS_MRL_SENSOR_OPEN)) { 2295 cmn_err(CE_WARN, "pciehpc_slot_poweron (slot %d): MRL switch " 2296 "is open", slot_p->hs_phy_slot_num); 2297 goto cleanup; 2298 } 2299 2300 /* 2301 * The power controller is already on, but we're in a state below 2302 * POWERED. This shouldn't happen, but there are any number of ways 2303 * that it can; we simply note this if debugging and move on. 2304 */ 2305 if ((control & PCIE_SLOTCTL_PWR_CONTROL) == 0 && 2306 slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED) { 2307 PCIE_DBG("pciehpc_slot_poweron (slot %d): controller is " 2308 "already enabled in SW state %d; continuing\n", 2309 slot_p->hs_phy_slot_num, slot_p->hs_info.cn_state); 2310 goto alreadyon; 2311 } 2312 2313 /* 2314 * The power controller has been turned off (which doesn't mean it *is* 2315 * off), but software thinks it's on. This is pretty bad, and we 2316 * probably need to consider doing something here to reset the state 2317 * machine because upper layers are likely to be confused. We will 2318 * nevertheless turn on the controller and hope the right things happen 2319 * above us. 2320 */ 2321 if ((control & PCIE_SLOTCTL_PWR_CONTROL) != 0 && 2322 slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED) { 2323 cmn_err(CE_WARN, "pciehpc_slot_poweron (slot %d): SW state is " 2324 "already %d but power controller is disabled; continuing", 2325 slot_p->hs_phy_slot_num, slot_p->hs_info.cn_state); 2326 } 2327 2328 /* 2329 * Enabling power to the slot involves: 2330 * 1. Updating our LED state to indicate the transition is 2331 * beginning and clearing out other aspects. 2332 * 2. Set power control ON in Slot Control Reigster and 2333 * wait for Command Completed Interrupt or 1 sec timeout. 2334 * 3. If Data Link Layer State Changed events are supported 2335 * then wait for the event to indicate Data Layer Link 2336 * is active. The time out value for this event is 1 second. 2337 * This is specified in PCI-E version 1.1. 2338 * 4. Set power LED to be ON. 2339 */ 2340 2341 /* 2342 * If power is already on, we skip indicating a power transition is 2343 * going on. However, we always try to clear out the error state LEDs at 2344 * this point. 2345 */ 2346 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = true; 2347 alreadyon: 2348 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2349 slot_p->hs_led_plat_en[PCIE_LL_POWER_FAULT] = false; 2350 pciehpc_sync_leds_to_hw(slot_p); 2351 2352 /* 2. set power control to ON */ 2353 control = pciehpc_reg_get16(ctrl_p, 2354 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2355 control &= ~PCIE_SLOTCTL_PWR_CONTROL; 2356 pciehpc_issue_hpc_command(ctrl_p, control); 2357 2358 /* 3. wait for DLL State Change event, if it's supported */ 2359 if (!pciehpc_slot_wait_for_active(slot_p)) 2360 goto cleanup; 2361 2362 /* check power is really turned ON */ 2363 control = pciehpc_reg_get16(ctrl_p, 2364 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2365 2366 if (control & PCIE_SLOTCTL_PWR_CONTROL) { 2367 PCIE_DBG("pciehpc_slot_poweron (slot %d): power controller " 2368 "enable was disabled autonomously after SW enable", 2369 slot_p->hs_phy_slot_num); 2370 2371 goto cleanup; 2372 } 2373 2374 /* clear power fault status */ 2375 status = pciehpc_reg_get16(ctrl_p, 2376 bus_p->bus_pcie_off + PCIE_SLOTSTS); 2377 status |= PCIE_SLOTSTS_PWR_FAULT_DETECTED; 2378 pciehpc_reg_put16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTSTS, 2379 status); 2380 2381 /* enable power fault detection interrupt */ 2382 control |= PCIE_SLOTCTL_PWR_FAULT_EN; 2383 pciehpc_issue_hpc_command(ctrl_p, control); 2384 2385 /* 4. Set power LED to be ON */ 2386 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = false; 2387 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = true; 2388 pciehpc_sync_leds_to_hw(slot_p); 2389 2390 /* if EMI is present, turn it ON */ 2391 if (ctrl_p->hc_has_emi_lock) { 2392 status = pciehpc_reg_get16(ctrl_p, 2393 bus_p->bus_pcie_off + PCIE_SLOTSTS); 2394 2395 if (!(status & PCIE_SLOTSTS_EMI_LOCK_SET)) { 2396 control = pciehpc_reg_get16(ctrl_p, 2397 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2398 control |= PCIE_SLOTCTL_EMI_LOCK_CONTROL; 2399 pciehpc_issue_hpc_command(ctrl_p, control); 2400 2401 /* wait 1 sec after toggling the state of EMI lock */ 2402 delay(drv_usectohz(1000000)); 2403 } 2404 } 2405 2406 *result = slot_p->hs_info.cn_state = DDI_HP_CN_STATE_POWERED; 2407 2408 return (DDI_SUCCESS); 2409 2410 cleanup: 2411 control = pciehpc_reg_get16(ctrl_p, 2412 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2413 2414 /* if power is ON, set power control to OFF */ 2415 if ((control & PCIE_SLOTCTL_PWR_CONTROL) == 0) { 2416 control |= PCIE_SLOTCTL_PWR_CONTROL; 2417 pciehpc_issue_hpc_command(ctrl_p, control); 2418 } 2419 2420 /* set power led to OFF XXX what if HW/FW refused to turn off? */ 2421 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = false; 2422 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = false; 2423 pciehpc_sync_leds_to_hw(slot_p); 2424 2425 return (DDI_FAILURE); 2426 } 2427 2428 /* 2429 * All the same considerations apply to poweroff; see notes above. 2430 */ 2431 static int 2432 pciehpc_slot_poweroff(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result) 2433 { 2434 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2435 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 2436 uint16_t status, control; 2437 2438 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 2439 2440 /* 2441 * Some devices do not have a power controller. In such cases we need to 2442 * fail any request to power it off. If a device is being pulled, the 2443 * state will generally have automatically been updated; however, if 2444 * someone is asking for us to do something via an explicit request, 2445 * then this will fail. 2446 */ 2447 if (!ctrl_p->hc_has_pwr) { 2448 PCIE_DBG("pciehpc_slot_poweroff (slot %d): no power control " 2449 "capability, but was asked to power off\n", 2450 slot_p->hs_phy_slot_num); 2451 return (DDI_ENOTSUP); 2452 } 2453 2454 /* 2455 * SW thinks the slot is already powered off. Note this unexpected 2456 * condition and continue. 2457 */ 2458 if (slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED) { 2459 PCIE_DBG("pciehpc_slot_poweroff (slot %d): SW state is " 2460 "already %d; continuing\n", 2461 slot_p->hs_phy_slot_num, slot_p->hs_info.cn_state); 2462 } 2463 2464 control = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTCTL); 2465 status = pciehpc_reg_get16(ctrl_p, bus_p->bus_pcie_off + PCIE_SLOTSTS); 2466 2467 /* 2468 * The power controller has been turned off (which doesn't mean it *is* 2469 * off), but software thinks it's on. Note this unexpected condition 2470 * for debugging and continue; we'll do what we can to get the state 2471 * machines back in sync. 2472 */ 2473 if ((control & PCIE_SLOTCTL_PWR_CONTROL) != 0 && 2474 slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED) { 2475 cmn_err(CE_WARN, "pciehpc_slot_poweroff (slot %d): SW state is " 2476 "%d but power controller is already disabled; continuing", 2477 slot_p->hs_phy_slot_num, slot_p->hs_info.cn_state); 2478 goto alreadyoff; 2479 } 2480 2481 if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) { 2482 PCIE_DBG("pciehpc_slot_poweroff (slot %d): powering off " 2483 "empty slot\n", slot_p->hs_phy_slot_num); 2484 } 2485 2486 /* 2487 * Disable power to the slot involves: 2488 * 1. Set power LED to blink. 2489 * 2. Set power control OFF in Slot Control Reigster and 2490 * wait for Command Completed Interrupt or 1 sec timeout. 2491 * 3. Set POWER led and ATTN led to be OFF. 2492 */ 2493 2494 /* 2495 * We don't bother indicating a power transition if the device is 2496 * already off. The act of turning it off does clear out a probe 2497 * failure, but it doesn't clear out a power fault. That is only 2498 * reserved for a removal. 2499 */ 2500 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = true; 2501 alreadyoff: 2502 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2503 pciehpc_sync_leds_to_hw(slot_p); 2504 2505 /* disable power fault detection interrupt */ 2506 control = pciehpc_reg_get16(ctrl_p, 2507 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2508 control &= ~PCIE_SLOTCTL_PWR_FAULT_EN; 2509 pciehpc_issue_hpc_command(ctrl_p, control); 2510 2511 /* 2. set power control to OFF */ 2512 control = pciehpc_reg_get16(ctrl_p, 2513 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2514 control |= PCIE_SLOTCTL_PWR_CONTROL; 2515 pciehpc_issue_hpc_command(ctrl_p, control); 2516 2517 /* 2518 * Make sure our control input has been acknowledged. Some 2519 * implementations may clear the control bit if the power controller 2520 * couldn't be disabled for some reasons, or if firmware decided to 2521 * disallow our command. 2522 */ 2523 control = pciehpc_reg_get16(ctrl_p, 2524 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2525 if ((control & PCIE_SLOTCTL_PWR_CONTROL) == 0) { 2526 /* 2527 * Well, this is unfortunate: we couldn't turn power off. 2528 * XXX Should we turn on the ATTN indicator? For now we just 2529 * log a warning and fail. 2530 */ 2531 cmn_err(CE_WARN, "pciehpc_slot_poweroff (slot %d): power " 2532 "controller completed our disable command but is still " 2533 "enabled", slot_p->hs_phy_slot_num); 2534 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = false; 2535 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = true; 2536 pciehpc_sync_leds_to_hw(slot_p); 2537 2538 return (DDI_FAILURE); 2539 } 2540 2541 /* 3. Set power LED to be OFF */ 2542 slot_p->hs_led_plat_en[PCIE_LL_POWER_TRANSITION] = false; 2543 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = false; 2544 pciehpc_sync_leds_to_hw(slot_p); 2545 2546 /* if EMI is present, turn it OFF */ 2547 if (ctrl_p->hc_has_emi_lock) { 2548 status = pciehpc_reg_get16(ctrl_p, 2549 bus_p->bus_pcie_off + PCIE_SLOTSTS); 2550 2551 if (status & PCIE_SLOTSTS_EMI_LOCK_SET) { 2552 control = pciehpc_reg_get16(ctrl_p, 2553 bus_p->bus_pcie_off + PCIE_SLOTCTL); 2554 control |= PCIE_SLOTCTL_EMI_LOCK_CONTROL; 2555 pciehpc_issue_hpc_command(ctrl_p, control); 2556 2557 /* wait 1 sec after toggling the state of EMI lock */ 2558 delay(drv_usectohz(1000000)); 2559 } 2560 } 2561 2562 /* get the current state of the slot */ 2563 pciehpc_get_slot_state(slot_p); 2564 2565 *result = slot_p->hs_info.cn_state; 2566 2567 return (DDI_SUCCESS); 2568 } 2569 2570 /* 2571 * pciehpc_slot_probe() 2572 * 2573 * Probe the slot. 2574 * 2575 * Note: This function is called by DDI HP framework at kernel context only 2576 */ 2577 static int 2578 pciehpc_slot_probe(pcie_hp_slot_t *slot_p) 2579 { 2580 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2581 int ret = DDI_SUCCESS; 2582 2583 mutex_enter(&ctrl_p->hc_mutex); 2584 2585 /* 2586 * Because we've been asked to probe again, make sure we aren't actively 2587 * suggesting probe failed from an LED perspective. 2588 */ 2589 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2590 pciehpc_sync_leds_to_hw(slot_p); 2591 2592 /* get the current state of the slot */ 2593 pciehpc_get_slot_state(slot_p); 2594 2595 /* 2596 * Probe a given PCIe Hotplug Connection (CN). 2597 */ 2598 PCIE_DISABLE_ERRORS(ctrl_p->hc_dip); 2599 ret = pcie_hp_probe(slot_p); 2600 2601 if (ret != DDI_SUCCESS) { 2602 PCIE_DBG("pciehpc_slot_probe() failed\n"); 2603 2604 /* turn the ATTN led ON for configure failure */ 2605 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = true; 2606 pciehpc_sync_leds_to_hw(slot_p); 2607 mutex_exit(&ctrl_p->hc_mutex); 2608 return (DDI_FAILURE); 2609 } 2610 2611 PCIE_ENABLE_ERRORS(ctrl_p->hc_dip); 2612 2613 /* get the current state of the slot */ 2614 pciehpc_get_slot_state(slot_p); 2615 2616 mutex_exit(&ctrl_p->hc_mutex); 2617 return (DDI_SUCCESS); 2618 } 2619 2620 /* 2621 * pciehpc_slot_unprobe() 2622 * 2623 * Unprobe the slot. 2624 * 2625 * Note: This function is called by DDI HP framework at kernel context only 2626 */ 2627 static int 2628 pciehpc_slot_unprobe(pcie_hp_slot_t *slot_p) 2629 { 2630 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2631 int ret; 2632 2633 mutex_enter(&ctrl_p->hc_mutex); 2634 2635 /* get the current state of the slot */ 2636 pciehpc_get_slot_state(slot_p); 2637 2638 /* 2639 * Unprobe a given PCIe Hotplug Connection (CN). 2640 */ 2641 PCIE_DISABLE_ERRORS(ctrl_p->hc_dip); 2642 ret = pcie_hp_unprobe(slot_p); 2643 2644 if (ret != DDI_SUCCESS) { 2645 PCIE_DBG("pciehpc_slot_unprobe() failed\n"); 2646 PCIE_ENABLE_ERRORS(ctrl_p->hc_dip); 2647 mutex_exit(&ctrl_p->hc_mutex); 2648 return (DDI_FAILURE); 2649 } 2650 2651 /* get the current state of the slot */ 2652 pciehpc_get_slot_state(slot_p); 2653 2654 mutex_exit(&ctrl_p->hc_mutex); 2655 return (DDI_SUCCESS); 2656 } 2657 2658 static int 2659 pciehpc_upgrade_slot_state(pcie_hp_slot_t *slot_p, 2660 ddi_hp_cn_state_t target_state) 2661 { 2662 ddi_hp_cn_state_t curr_state; 2663 int rv = DDI_SUCCESS; 2664 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2665 2666 if (target_state > DDI_HP_CN_STATE_ENABLED) { 2667 return (DDI_EINVAL); 2668 } 2669 2670 curr_state = slot_p->hs_info.cn_state; 2671 while ((curr_state < target_state) && (rv == DDI_SUCCESS)) { 2672 2673 switch (curr_state) { 2674 case DDI_HP_CN_STATE_EMPTY: 2675 /* 2676 * From EMPTY to PRESENT, just check the hardware 2677 * slot state. 2678 */ 2679 pciehpc_get_slot_state(slot_p); 2680 curr_state = slot_p->hs_info.cn_state; 2681 if (curr_state < DDI_HP_CN_STATE_PRESENT) 2682 rv = DDI_FAILURE; 2683 break; 2684 case DDI_HP_CN_STATE_PRESENT: 2685 if (!ctrl_p->hc_has_pwr) { 2686 pciehpc_get_slot_state(slot_p); 2687 curr_state = slot_p->hs_info.cn_state; 2688 if (curr_state < DDI_HP_CN_STATE_POWERED) 2689 rv = DDI_FAILURE; 2690 break; 2691 } 2692 2693 rv = (ctrl_p->hc_ops.poweron_hpc_slot)(slot_p, 2694 &curr_state); 2695 2696 break; 2697 case DDI_HP_CN_STATE_POWERED: 2698 /* 2699 * If we're performing a synchronization, then the 2700 * POWERED state isn't quite accurate. Power is enabled, 2701 * but we haven't really done all the actual steps that 2702 * are expected. As such, we will do another call to 2703 * power on and if successful, then do the change to 2704 * ENABLED. If the call to power on did not work, then 2705 * we must transition back to PRESENT. If there is no 2706 * power controller, then this is a no-op. 2707 */ 2708 if ((ctrl_p->hc_flags & PCIE_HP_SYNC_RUNNING) != 0 && 2709 ctrl_p->hc_has_pwr) { 2710 rv = (ctrl_p->hc_ops.poweron_hpc_slot)(slot_p, 2711 &curr_state); 2712 if (rv != DDI_SUCCESS) { 2713 slot_p->hs_info.cn_state = 2714 DDI_HP_CN_STATE_PRESENT; 2715 break; 2716 } 2717 } else if (!ctrl_p->hc_has_pwr) { 2718 rv = pciehpc_slot_noctrl_active(slot_p, 2719 &curr_state); 2720 if (rv != DDI_SUCCESS) 2721 break; 2722 } 2723 2724 curr_state = slot_p->hs_info.cn_state = 2725 DDI_HP_CN_STATE_ENABLED; 2726 break; 2727 default: 2728 /* should never reach here */ 2729 ASSERT("unknown devinfo state"); 2730 } 2731 } 2732 2733 return (rv); 2734 } 2735 2736 /* 2737 * Remove and clear out LEDs given a slot state downgrade. In particular, we 2738 * have three states that we need to worry about: whether the device is powered, 2739 * a power fault, and a probe failure. 2740 * 2741 * Removing power removes the powered state and a probe failure, but retains a 2742 * power fault. Removing a device ensures that all three are off. 2743 */ 2744 static void 2745 pciehpc_downgrade_slot_leds(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t state) 2746 { 2747 switch (state) { 2748 case DDI_HP_CN_STATE_EMPTY: 2749 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = false; 2750 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2751 slot_p->hs_led_plat_en[PCIE_LL_POWER_FAULT] = false; 2752 break; 2753 case DDI_HP_CN_STATE_PRESENT: 2754 slot_p->hs_led_plat_en[PCIE_LL_POWERED] = false; 2755 slot_p->hs_led_plat_en[PCIE_LL_PROBE_FAILED] = false; 2756 break; 2757 default: 2758 break; 2759 } 2760 2761 pciehpc_sync_leds_to_hw(slot_p); 2762 } 2763 2764 static int 2765 pciehpc_downgrade_slot_state(pcie_hp_slot_t *slot_p, 2766 ddi_hp_cn_state_t target_state) 2767 { 2768 ddi_hp_cn_state_t curr_state; 2769 int rv = DDI_SUCCESS; 2770 2771 2772 curr_state = slot_p->hs_info.cn_state; 2773 while ((curr_state > target_state) && (rv == DDI_SUCCESS)) { 2774 2775 switch (curr_state) { 2776 case DDI_HP_CN_STATE_PRESENT: 2777 /* 2778 * From PRESENT to EMPTY, just check hardware slot 2779 * state. Removal of a device means we should make sure 2780 * that the LEDs are cleaned up. 2781 */ 2782 pciehpc_get_slot_state(slot_p); 2783 curr_state = slot_p->hs_info.cn_state; 2784 if (curr_state >= DDI_HP_CN_STATE_PRESENT) { 2785 rv = DDI_FAILURE; 2786 } else { 2787 pciehpc_downgrade_slot_leds(slot_p, curr_state); 2788 } 2789 break; 2790 case DDI_HP_CN_STATE_POWERED: 2791 /* 2792 * If the device doesn't have power control then we 2793 * cannot ask it to power off the slot. However, a 2794 * device may have been removed and therefore we need to 2795 * manually check if the device was removed by getting 2796 * the state. Otherwise we let power control do 2797 * everything. 2798 */ 2799 if (!slot_p->hs_ctrl->hc_has_pwr) { 2800 pciehpc_get_slot_state(slot_p); 2801 curr_state = slot_p->hs_info.cn_state; 2802 if (curr_state >= DDI_HP_CN_STATE_POWERED) { 2803 rv = DDI_FAILURE; 2804 } else { 2805 pciehpc_downgrade_slot_leds(slot_p, 2806 curr_state); 2807 } 2808 break; 2809 } 2810 2811 rv = (slot_p->hs_ctrl->hc_ops.poweroff_hpc_slot)( 2812 slot_p, &curr_state); 2813 2814 break; 2815 case DDI_HP_CN_STATE_ENABLED: 2816 curr_state = slot_p->hs_info.cn_state = 2817 DDI_HP_CN_STATE_POWERED; 2818 2819 break; 2820 default: 2821 /* should never reach here */ 2822 ASSERT("unknown devinfo state"); 2823 } 2824 } 2825 2826 return (rv); 2827 } 2828 2829 /* Change slot state to a target state */ 2830 static int 2831 pciehpc_change_slot_state(pcie_hp_slot_t *slot_p, 2832 ddi_hp_cn_state_t target_state) 2833 { 2834 ddi_hp_cn_state_t curr_state; 2835 pciehpc_slot_power_t pwr_state; 2836 boolean_t sync = B_FALSE; 2837 int rv = 0; 2838 2839 ASSERT(MUTEX_HELD(&slot_p->hs_ctrl->hc_mutex)); 2840 2841 pciehpc_get_slot_state(slot_p); 2842 curr_state = slot_p->hs_info.cn_state; 2843 pwr_state = pciehpc_slot_power_state(slot_p); 2844 2845 /* 2846 * We've been asked to change the slot state. If we still had an 2847 * outstanding synchronization task, then we should remove that because 2848 * we've had an explicit state change. In essence we take over that sync 2849 * and note that it's running. 2850 */ 2851 if ((slot_p->hs_ctrl->hc_flags & PCIE_HP_SYNC_PENDING) != 0 && 2852 slot_p->hs_info.cn_state == DDI_HP_CN_STATE_POWERED) { 2853 sync = B_TRUE; 2854 slot_p->hs_ctrl->hc_flags |= PCIE_HP_SYNC_RUNNING; 2855 } 2856 slot_p->hs_ctrl->hc_flags &= ~PCIE_HP_SYNC_PENDING; 2857 2858 /* 2859 * We need to see whether the power controller state (if there is one) 2860 * matches the DDI slot state. If not, it may be necessary to perform 2861 * the upgrade or downgrade procedure even if the DDI slot state matches 2862 * the target already. We'll make sure that curr_state reflects the 2863 * state of the power controller with respect to our desired target 2864 * state, even if the slot is empty. 2865 */ 2866 if (pwr_state == PSP_NO_CONTROLLER) 2867 goto skip_sync; 2868 2869 switch (target_state) { 2870 case DDI_HP_CN_STATE_EMPTY: 2871 case DDI_HP_CN_STATE_PRESENT: 2872 /* 2873 * Power controller is on but software doesn't know that, and 2874 * wants to enter a state in which power should be off. 2875 */ 2876 if ((pwr_state & PSP_OFF) == 0 && 2877 curr_state < DDI_HP_CN_STATE_POWERED) { 2878 curr_state = DDI_HP_CN_STATE_POWERED; 2879 } 2880 break; 2881 case DDI_HP_CN_STATE_POWERED: 2882 case DDI_HP_CN_STATE_ENABLED: 2883 /* 2884 * Power controller is off but software doesn't know that, and 2885 * wants to enter a state in which power should be on. 2886 */ 2887 if ((pwr_state & PSP_OFF) != 0 && 2888 curr_state >= DDI_HP_CN_STATE_POWERED) { 2889 curr_state = DDI_HP_CN_STATE_PRESENT; 2890 } 2891 break; 2892 default: 2893 break; 2894 } 2895 2896 slot_p->hs_info.cn_state = curr_state; 2897 2898 skip_sync: 2899 if (curr_state == target_state) { 2900 return (DDI_SUCCESS); 2901 } 2902 2903 if (curr_state < target_state) { 2904 rv = pciehpc_upgrade_slot_state(slot_p, target_state); 2905 } else { 2906 rv = pciehpc_downgrade_slot_state(slot_p, target_state); 2907 } 2908 2909 if (sync) { 2910 slot_p->hs_ctrl->hc_flags &= ~PCIE_HP_SYNC_RUNNING; 2911 } 2912 2913 return (rv); 2914 } 2915 2916 typedef struct pciehpc_prop { 2917 const char *prop_name; 2918 const char *prop_value; 2919 bool (*prop_valid)(const char *); 2920 int (*prop_get)(pcie_hp_slot_t *, const char **); 2921 void (*prop_set)(pcie_hp_slot_t *, const char *); 2922 } pciehpc_prop_t; 2923 2924 static bool 2925 pciehpc_prop_led_valid(const char *value) 2926 { 2927 return (strcmp(value, PCIEHPC_PROP_VALUE_ON) == 0 || 2928 strcmp(value, PCIEHPC_PROP_VALUE_OFF) == 0 || 2929 strcmp(value, PCIEHPC_PROP_VALUE_BLINK) == 0 || 2930 strcmp(value, PCIEHPC_PROP_VALUE_DEFAULT) == 0); 2931 } 2932 2933 static int 2934 pciehpc_prop_card_get(pcie_hp_slot_t *slot_p, const char **value_p) 2935 { 2936 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 2937 ddi_acc_handle_t handle; 2938 dev_info_t *cdip; 2939 uint8_t prog_class, base_class, sub_class; 2940 2941 mutex_exit(&ctrl_p->hc_mutex); 2942 cdip = pcie_hp_devi_find(ctrl_p->hc_dip, slot_p->hs_device_num, 0); 2943 mutex_enter(&ctrl_p->hc_mutex); 2944 2945 if ((slot_p->hs_info.cn_state != DDI_HP_CN_STATE_ENABLED) || 2946 cdip == NULL) { 2947 /* 2948 * When getting all properties, just ignore the 2949 * one that's not available under certain state. 2950 */ 2951 return (DDI_ENOTSUP); 2952 } 2953 2954 if (pci_config_setup(cdip, &handle) != DDI_SUCCESS) { 2955 return (DDI_FAILURE); 2956 } 2957 2958 prog_class = pci_config_get8(handle, PCI_CONF_PROGCLASS); 2959 base_class = pci_config_get8(handle, PCI_CONF_BASCLASS); 2960 sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS); 2961 pci_config_teardown(&handle); 2962 2963 *value_p = PCIEHPC_PROP_VALUE_UNKNOWN; 2964 for (size_t i = 0; i < class_pci_items; i++) { 2965 if ((base_class == class_pci[i].base_class) && 2966 (sub_class == class_pci[i].sub_class) && 2967 (prog_class == class_pci[i].prog_class)) { 2968 *value_p = class_pci[i].short_desc; 2969 break; 2970 } 2971 } 2972 2973 return (DDI_SUCCESS); 2974 } 2975 2976 static int 2977 pciehpc_prop_board_get(pcie_hp_slot_t *slot_p, const char **value_p) 2978 { 2979 if (slot_p->hs_info.cn_state <= DDI_HP_CN_STATE_EMPTY) { 2980 *value_p = PCIEHPC_PROP_VALUE_UNKNOWN; 2981 } else { 2982 *value_p = PCIEHPC_PROP_VALUE_PCIHOTPLUG; 2983 } 2984 2985 return (DDI_SUCCESS); 2986 } 2987 2988 static int 2989 pciehpc_prop_slot_get(pcie_hp_slot_t *slot_p, const char **value_p) 2990 { 2991 *value_p = pcie_slot_condition_text(slot_p->hs_condition); 2992 return (DDI_SUCCESS); 2993 } 2994 2995 static int 2996 pciehpc_prop_led_get_power(pcie_hp_slot_t *slot_p, const char **value_p) 2997 { 2998 if (slot_p->hs_power_usr_ovr) { 2999 *value_p = pcie_led_state_text(slot_p->hs_power_usr_ovr_state); 3000 } else { 3001 *value_p = PCIEHPC_PROP_VALUE_DEFAULT; 3002 } 3003 return (DDI_SUCCESS); 3004 } 3005 3006 static int 3007 pciehpc_prop_led_get_attn(pcie_hp_slot_t *slot_p, const char **value_p) 3008 { 3009 if (slot_p->hs_attn_usr_ovr) { 3010 *value_p = pcie_led_state_text(slot_p->hs_attn_usr_ovr_state); 3011 } else { 3012 *value_p = PCIEHPC_PROP_VALUE_DEFAULT; 3013 } 3014 return (DDI_SUCCESS); 3015 } 3016 3017 static void 3018 pciehpc_prop_led_set_common(bool *ovr, pcie_hp_led_state_t *state, 3019 const char *val) 3020 { 3021 if (strcmp(val, PCIEHPC_PROP_VALUE_DEFAULT) == 0) { 3022 *ovr = false; 3023 return; 3024 } 3025 3026 *ovr = true; 3027 if (strcmp(val, PCIEHPC_PROP_VALUE_ON) == 0) { 3028 *state = PCIE_HP_LED_ON; 3029 } else if (strcmp(val, PCIEHPC_PROP_VALUE_OFF) == 0) { 3030 *state = PCIE_HP_LED_OFF; 3031 } else if (strcmp(val, PCIEHPC_PROP_VALUE_BLINK) == 0) { 3032 *state = PCIE_HP_LED_BLINK; 3033 } 3034 } 3035 3036 static void 3037 pciehpc_prop_led_set_attn(pcie_hp_slot_t *slot_p, const char *value) 3038 { 3039 pciehpc_prop_led_set_common(&slot_p->hs_attn_usr_ovr, 3040 &slot_p->hs_attn_usr_ovr_state, value); 3041 } 3042 3043 static void 3044 pciehpc_prop_led_set_power(pcie_hp_slot_t *slot_p, const char *value) 3045 { 3046 pciehpc_prop_led_set_common(&slot_p->hs_power_usr_ovr, 3047 &slot_p->hs_power_usr_ovr_state, value); 3048 } 3049 3050 static pciehpc_prop_t pciehpc_props[] = { 3051 { PCIEHPC_PROP_LED_POWER, PCIEHPC_PROP_VALUE_LED_DEF, 3052 pciehpc_prop_led_valid, pciehpc_prop_led_get_power, 3053 pciehpc_prop_led_set_power }, 3054 { PCIEHPC_PROP_LED_ATTN, PCIEHPC_PROP_VALUE_LED_DEF, 3055 pciehpc_prop_led_valid, pciehpc_prop_led_get_attn, 3056 pciehpc_prop_led_set_attn }, 3057 { PCIEHPC_PROP_CARD_TYPE, PCIEHPC_PROP_VALUE_TYPE, NULL, 3058 pciehpc_prop_card_get, NULL }, 3059 { PCIEHPC_PROP_BOARD_TYPE, PCIEHPC_PROP_VALUE_TYPE, NULL, 3060 pciehpc_prop_board_get, NULL }, 3061 { PCIEHPC_PROP_SLOT_CONDITION, PCIEHPC_PROP_VALUE_TYPE, NULL, 3062 pciehpc_prop_slot_get, NULL }, 3063 }; 3064 3065 static bool 3066 pciehpc_slot_prop_copyin(uintptr_t arg, ddi_hp_property_t *prop) 3067 { 3068 switch (ddi_model_convert_from(get_udatamodel())) { 3069 #ifdef _MULTI_DATAMODEL 3070 case DDI_MODEL_ILP32: { 3071 ddi_hp_property32_t prop32; 3072 if (ddi_copyin((void *)arg, &prop32, sizeof (prop32), 0) != 0) { 3073 return (false); 3074 } 3075 bzero(prop, sizeof (prop)); 3076 prop->nvlist_buf = (void *)(uintptr_t)prop32.nvlist_buf; 3077 prop->buf_size = prop32.buf_size; 3078 break; 3079 } 3080 #endif 3081 case DDI_MODEL_NONE: 3082 if (ddi_copyin((void *)arg, prop, sizeof (*prop), 0) != 0) { 3083 return (false); 3084 } 3085 break; 3086 default: 3087 return (false); 3088 } 3089 3090 return (true); 3091 } 3092 3093 static bool 3094 pciehpc_slot_prop_copyout(uintptr_t dest, const ddi_hp_property_t *prop) 3095 { 3096 switch (ddi_model_convert_from(get_udatamodel())) { 3097 #ifdef _MULTI_DATAMODEL 3098 case DDI_MODEL_ILP32: { 3099 ddi_hp_property32_t prop32; 3100 3101 if ((uintptr_t)prop->nvlist_buf > UINT32_MAX || 3102 prop->buf_size > UINT32_MAX) { 3103 return (false); 3104 } 3105 bzero(&prop32, sizeof (prop32)); 3106 prop32.nvlist_buf = (caddr32_t)(uintptr_t)prop->nvlist_buf; 3107 prop32.buf_size = (uint32_t)prop->buf_size; 3108 if (ddi_copyout(&prop32, (void *)dest, sizeof (prop32), 0) != 3109 0) { 3110 return (false); 3111 } 3112 break; 3113 } 3114 #endif 3115 case DDI_MODEL_NONE: 3116 if (ddi_copyout(prop, (void *)dest, sizeof (ddi_hp_property_t), 3117 0) != 0) { 3118 return (false); 3119 } 3120 break; 3121 default: 3122 return (false); 3123 } 3124 3125 return (true); 3126 } 3127 3128 int 3129 pciehpc_slot_get_property(pcie_hp_slot_t *slot_p, uintptr_t arg, uintptr_t rval) 3130 { 3131 ddi_hp_property_t request, result; 3132 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 3133 nvlist_t *prop_list; 3134 nvlist_t *prop_rlist; /* nvlist for return values */ 3135 nvpair_t *prop_pair; 3136 int ret = DDI_SUCCESS; 3137 boolean_t get_all_prop = B_FALSE; 3138 3139 if (!pciehpc_slot_prop_copyin(arg, &request) || 3140 !pciehpc_slot_prop_copyin(rval, &result)) 3141 return (false); 3142 3143 if ((ret = pcie_copyin_nvlist(request.nvlist_buf, request.buf_size, 3144 &prop_list)) != DDI_SUCCESS) 3145 return (ret); 3146 3147 if (nvlist_alloc(&prop_rlist, NV_UNIQUE_NAME, 0)) { 3148 ret = DDI_ENOMEM; 3149 goto get_prop_cleanup; 3150 } 3151 3152 /* check whether the requested property is "all" or "help" */ 3153 prop_pair = nvlist_next_nvpair(prop_list, NULL); 3154 if (prop_pair && !nvlist_next_nvpair(prop_list, prop_pair)) { 3155 const char *name = nvpair_name(prop_pair); 3156 3157 if (strcmp(name, PCIEHPC_PROP_ALL) == 0) { 3158 (void) nvlist_remove_all(prop_list, PCIEHPC_PROP_ALL); 3159 3160 /* 3161 * Add all properties into the request list, so that we 3162 * will get the values in the following for loop. 3163 */ 3164 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3165 if (nvlist_add_string(prop_list, 3166 pciehpc_props[i].prop_name, "") != 0) { 3167 ret = DDI_FAILURE; 3168 goto get_prop_cleanup1; 3169 } 3170 } 3171 get_all_prop = B_TRUE; 3172 } else if (strcmp(name, PCIEHPC_PROP_HELP) == 0) { 3173 /* 3174 * Empty the request list, and add help strings into the 3175 * return list. We will pass the following for loop. 3176 */ 3177 (void) nvlist_remove_all(prop_list, PCIEHPC_PROP_HELP); 3178 3179 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3180 if (nvlist_add_string(prop_rlist, 3181 pciehpc_props[i].prop_name, 3182 pciehpc_props[i].prop_value) != 0) { 3183 ret = DDI_FAILURE; 3184 goto get_prop_cleanup1; 3185 } 3186 } 3187 } 3188 } 3189 3190 mutex_enter(&ctrl_p->hc_mutex); 3191 3192 /* get the current slot state */ 3193 pciehpc_get_slot_state(slot_p); 3194 3195 /* for each requested property, get the value and add it to nvlist */ 3196 prop_pair = NULL; 3197 while ((prop_pair = nvlist_next_nvpair(prop_list, prop_pair)) != NULL) { 3198 const char *name = nvpair_name(prop_pair); 3199 const pciehpc_prop_t *prop = NULL; 3200 const char *value = NULL; 3201 3202 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3203 if (strcmp(pciehpc_props[i].prop_name, name) == 0) { 3204 prop = &pciehpc_props[i]; 3205 break; 3206 } 3207 } 3208 3209 if (prop == NULL) { 3210 PCIE_DBG("Unsupported property: %s\n", name); 3211 ret = DDI_EINVAL; 3212 goto get_prop_cleanup2; 3213 } 3214 3215 /* 3216 * Get the property. Some things may fail with ENOTSUP and we 3217 * allow that if we are being asked to get everything. 3218 */ 3219 ret = prop->prop_get(slot_p, &value); 3220 if (ret != DDI_SUCCESS && 3221 (get_all_prop && ret != DDI_ENOTSUP)) { 3222 goto get_prop_cleanup2; 3223 } 3224 3225 if (nvlist_add_string(prop_rlist, name, value) != 0) { 3226 ret = DDI_FAILURE; 3227 goto get_prop_cleanup2; 3228 } 3229 } 3230 3231 /* pack nvlist and copyout */ 3232 if ((ret = pcie_copyout_nvlist(prop_rlist, result.nvlist_buf, 3233 &result.buf_size)) != DDI_SUCCESS) { 3234 goto get_prop_cleanup2; 3235 } 3236 3237 if (!pciehpc_slot_prop_copyout(rval, &result)) { 3238 ret = DDI_FAILURE; 3239 } 3240 3241 get_prop_cleanup2: 3242 mutex_exit(&ctrl_p->hc_mutex); 3243 get_prop_cleanup1: 3244 nvlist_free(prop_rlist); 3245 get_prop_cleanup: 3246 nvlist_free(prop_list); 3247 return (ret); 3248 } 3249 3250 3251 int 3252 pciehpc_slot_set_property(pcie_hp_slot_t *slot_p, uintptr_t arg, 3253 uintptr_t rval) 3254 { 3255 ddi_hp_property_t request, result; 3256 pcie_hp_ctrl_t *ctrl_p = slot_p->hs_ctrl; 3257 nvlist_t *prop_list; 3258 nvlist_t *prop_rlist; 3259 nvpair_t *prop_pair; 3260 int ret = DDI_SUCCESS; 3261 3262 if (!pciehpc_slot_prop_copyin(arg, &request) || 3263 !pciehpc_slot_prop_copyin(rval, &result)) 3264 return (false); 3265 3266 if ((ret = pcie_copyin_nvlist(request.nvlist_buf, request.buf_size, 3267 &prop_list)) != DDI_SUCCESS) 3268 return (ret); 3269 3270 /* check whether the requested property is "help" */ 3271 prop_pair = nvlist_next_nvpair(prop_list, NULL); 3272 if (prop_pair && !nvlist_next_nvpair(prop_list, prop_pair) && 3273 (strcmp(nvpair_name(prop_pair), PCIEHPC_PROP_HELP) == 0)) { 3274 if (!rval) { 3275 ret = DDI_ENOTSUP; 3276 goto set_prop_cleanup; 3277 } 3278 3279 if (nvlist_alloc(&prop_rlist, NV_UNIQUE_NAME, 0)) { 3280 ret = DDI_ENOMEM; 3281 goto set_prop_cleanup; 3282 } 3283 3284 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3285 if (pciehpc_props[i].prop_valid == NULL) 3286 continue; 3287 3288 if (nvlist_add_string(prop_rlist, 3289 pciehpc_props[i].prop_name, 3290 pciehpc_props[i].prop_value) != 0) { 3291 ret = DDI_FAILURE; 3292 goto set_prop_cleanup1; 3293 } 3294 } 3295 3296 if ((ret = pcie_copyout_nvlist(prop_rlist, result.nvlist_buf, 3297 &result.buf_size)) != DDI_SUCCESS) { 3298 goto set_prop_cleanup1; 3299 } 3300 3301 if (!pciehpc_slot_prop_copyout(rval, &result)) { 3302 ret = DDI_FAILURE; 3303 } 3304 3305 set_prop_cleanup1: 3306 nvlist_free(prop_rlist); 3307 nvlist_free(prop_list); 3308 return (ret); 3309 } 3310 3311 /* Validate the request */ 3312 prop_pair = NULL; 3313 while ((prop_pair = nvlist_next_nvpair(prop_list, prop_pair)) != NULL) { 3314 const pciehpc_prop_t *prop; 3315 char *value; 3316 const char *name = nvpair_name(prop_pair); 3317 3318 if (nvpair_type(prop_pair) != DATA_TYPE_STRING) { 3319 PCIE_DBG("Unexpected data type of setting " 3320 "property %s.\n", name); 3321 ret = DDI_EINVAL; 3322 goto set_prop_cleanup; 3323 } 3324 3325 if (nvpair_value_string(prop_pair, &value)) { 3326 PCIE_DBG("Get string value failed for property %s.\n", 3327 name); 3328 ret = DDI_FAILURE; 3329 goto set_prop_cleanup; 3330 } 3331 3332 prop = NULL; 3333 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3334 if (strcmp(pciehpc_props[i].prop_name, name) == 0) { 3335 prop = &pciehpc_props[i]; 3336 break; 3337 } 3338 } 3339 3340 if (prop == NULL) { 3341 PCIE_DBG("Unsupported property: %s\n", name); 3342 ret = DDI_EINVAL; 3343 goto set_prop_cleanup; 3344 } 3345 3346 if (prop->prop_valid == NULL) { 3347 PCIE_DBG("Read only property: %s\n", name); 3348 ret = DDI_ENOTSUP; 3349 goto set_prop_cleanup; 3350 } else if (!prop->prop_valid(value)) { 3351 PCIE_DBG("Unsupported value ('%s') for property: %s\n", 3352 value, name); 3353 ret = DDI_EINVAL; 3354 goto set_prop_cleanup; 3355 } 3356 } 3357 mutex_enter(&ctrl_p->hc_mutex); 3358 3359 /* get the current slot state */ 3360 pciehpc_get_slot_state(slot_p); 3361 3362 /* set each property */ 3363 prop_pair = NULL; 3364 while ((prop_pair = nvlist_next_nvpair(prop_list, prop_pair)) != NULL) { 3365 const char *name = nvpair_name(prop_pair); 3366 const pciehpc_prop_t *prop = NULL; 3367 char *value; 3368 3369 (void) nvpair_value_string(prop_pair, &value); 3370 for (size_t i = 0; i < ARRAY_SIZE(pciehpc_props); i++) { 3371 if (strcmp(pciehpc_props[i].prop_name, name) == 0) { 3372 prop = &pciehpc_props[i]; 3373 break; 3374 } 3375 } 3376 3377 ASSERT3P(prop, !=, NULL); 3378 prop->prop_set(slot_p, value); 3379 } 3380 3381 /* 3382 * Because the only properties we can set are LED related, always 3383 * resync. 3384 */ 3385 pciehpc_sync_leds_to_hw(slot_p); 3386 3387 if (rval != 0) { 3388 result.buf_size = 0; 3389 if (!pciehpc_slot_prop_copyout(rval, &result)) { 3390 ret = DDI_FAILURE; 3391 } 3392 } 3393 3394 mutex_exit(&ctrl_p->hc_mutex); 3395 set_prop_cleanup: 3396 nvlist_free(prop_list); 3397 return (ret); 3398 } 3399 3400 /* 3401 * Send a command to the PCI-E Hot Plug Controller. 3402 * 3403 * NOTES: The PCI-E spec defines the following semantics for issuing hot plug 3404 * commands. 3405 * 1) If Command Complete events/interrupts are supported then software 3406 * waits for Command Complete event after issuing a command (i.e writing 3407 * to the Slot Control register). The command completion could take as 3408 * long as 1 second so software should be prepared to wait for 1 second 3409 * before issuing another command. 3410 * 3411 * 2) If Command Complete events/interrupts are not supported then 3412 * software could issue multiple Slot Control writes without any delay 3413 * between writes. 3414 */ 3415 static void 3416 pciehpc_issue_hpc_command(pcie_hp_ctrl_t *ctrl_p, uint16_t control) 3417 { 3418 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 3419 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 3420 uint16_t status; 3421 uint32_t slot_cap; 3422 3423 /* 3424 * PCI-E version 1.1 spec defines No Command Completed 3425 * Support bit (bit#18) in Slot Capabilities register. If this 3426 * bit is set then slot doesn't support notification of command 3427 * completion events. 3428 */ 3429 slot_cap = pciehpc_reg_get32(ctrl_p, 3430 bus_p->bus_pcie_off + PCIE_SLOTCAP); 3431 3432 /* 3433 * If no Command Completion event is supported or it is ACPI 3434 * hot plug mode then just issue the command and return. 3435 */ 3436 if ((slot_cap & PCIE_SLOTCAP_NO_CMD_COMP_SUPP) || 3437 (bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE)) { 3438 pciehpc_reg_put16(ctrl_p, 3439 bus_p->bus_pcie_off + PCIE_SLOTCTL, control); 3440 return; 3441 } 3442 3443 /* 3444 * ************************************** 3445 * Command Complete events are supported. 3446 * ************************************** 3447 */ 3448 3449 /* 3450 * If HPC is not yet initialized then just poll for the Command 3451 * Completion interrupt. 3452 */ 3453 if (!(ctrl_p->hc_flags & PCIE_HP_INITIALIZED_FLAG)) { 3454 int retry = PCIE_HP_CMD_WAIT_RETRY; 3455 3456 /* write the command to the HPC */ 3457 pciehpc_reg_put16(ctrl_p, 3458 bus_p->bus_pcie_off + PCIE_SLOTCTL, control); 3459 3460 /* poll for status completion */ 3461 while (retry--) { 3462 /* wait for 10 msec before checking the status */ 3463 delay(drv_usectohz(PCIE_HP_CMD_WAIT_TIME)); 3464 3465 status = pciehpc_reg_get16(ctrl_p, 3466 bus_p->bus_pcie_off + PCIE_SLOTSTS); 3467 3468 if (status & PCIE_SLOTSTS_COMMAND_COMPLETED) { 3469 /* clear the status bits */ 3470 pciehpc_reg_put16(ctrl_p, 3471 bus_p->bus_pcie_off + PCIE_SLOTSTS, status); 3472 break; 3473 } 3474 } 3475 return; 3476 } 3477 3478 /* HPC is already initialized */ 3479 3480 ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex)); 3481 3482 /* 3483 * If previous command is still pending then wait for its 3484 * completion. i.e cv_wait() 3485 */ 3486 3487 while (ctrl_p->hc_cmd_pending == B_TRUE) 3488 cv_wait(&ctrl_p->hc_cmd_comp_cv, &ctrl_p->hc_mutex); 3489 3490 /* 3491 * Issue the command and wait for Command Completion or 3492 * the 1 sec timeout. 3493 */ 3494 pciehpc_reg_put16(ctrl_p, 3495 bus_p->bus_pcie_off + PCIE_SLOTCTL, control); 3496 3497 ctrl_p->hc_cmd_pending = B_TRUE; 3498 3499 if (cv_timedwait(&ctrl_p->hc_cmd_comp_cv, &ctrl_p->hc_mutex, 3500 ddi_get_lbolt() + SEC_TO_TICK(1)) == -1) { 3501 3502 /* it is a timeout */ 3503 PCIE_DBG("pciehpc_issue_hpc_command: Command Complete" 3504 " interrupt is not received for slot %d\n", 3505 slot_p->hs_phy_slot_num); 3506 3507 /* clear the status info in case interrupts are disabled? */ 3508 status = pciehpc_reg_get16(ctrl_p, 3509 bus_p->bus_pcie_off + PCIE_SLOTSTS); 3510 3511 if (status & PCIE_SLOTSTS_COMMAND_COMPLETED) { 3512 /* clear the status bits */ 3513 pciehpc_reg_put16(ctrl_p, 3514 bus_p->bus_pcie_off + PCIE_SLOTSTS, status); 3515 } 3516 } 3517 3518 ctrl_p->hc_cmd_pending = B_FALSE; 3519 3520 /* wake up any one waiting for issuing another command to HPC */ 3521 cv_signal(&ctrl_p->hc_cmd_comp_cv); 3522 } 3523 3524 /* 3525 * pciehcp_attn_btn_handler() 3526 * 3527 * This handles ATTN button pressed event as per the PCI-E 1.1 spec. 3528 */ 3529 static void 3530 pciehpc_attn_btn_handler(pcie_hp_ctrl_t *ctrl_p) 3531 { 3532 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 3533 callb_cpr_t cprinfo; 3534 3535 PCIE_DBG("pciehpc_attn_btn_handler: thread started\n"); 3536 3537 CALLB_CPR_INIT(&cprinfo, &ctrl_p->hc_mutex, callb_generic_cpr, 3538 "pciehpc_attn_btn_handler"); 3539 3540 mutex_enter(&ctrl_p->hc_mutex); 3541 3542 /* wait for ATTN button event */ 3543 cv_wait(&slot_p->hs_attn_btn_cv, &ctrl_p->hc_mutex); 3544 3545 while (slot_p->hs_attn_btn_thread_exit == B_FALSE) { 3546 if (slot_p->hs_attn_btn_pending == B_TRUE) { 3547 /* 3548 * Allow the platform to toggle an appropriate LED while 3549 * we're waiting for this to take effect (generally 3550 * blinking the power LED). 3551 */ 3552 slot_p->hs_led_plat_en[PCIE_LL_ATTENTION_BUTTON] = true; 3553 pciehpc_sync_leds_to_hw(slot_p); 3554 3555 /* wait for 5 seconds before taking any action */ 3556 if (cv_timedwait(&slot_p->hs_attn_btn_cv, 3557 &ctrl_p->hc_mutex, 3558 ddi_get_lbolt() + SEC_TO_TICK(5)) == -1) { 3559 /* 3560 * It is a time out; make sure the ATTN pending 3561 * flag is still ON before sending the event to 3562 * DDI HP framework. 3563 */ 3564 if (slot_p->hs_attn_btn_pending == B_TRUE) { 3565 int hint; 3566 3567 slot_p->hs_attn_btn_pending = B_FALSE; 3568 pciehpc_get_slot_state(slot_p); 3569 3570 if (slot_p->hs_info.cn_state <= 3571 DDI_HP_CN_STATE_PRESENT) { 3572 /* 3573 * Insertion. 3574 */ 3575 hint = SE_INCOMING_RES; 3576 } else { 3577 /* 3578 * Want to remove; 3579 */ 3580 hint = SE_OUTGOING_RES; 3581 } 3582 3583 /* 3584 * We can't call ddihp_cn_gen_sysevent 3585 * here since it's not a DDI interface. 3586 */ 3587 pcie_hp_gen_sysevent_req( 3588 slot_p->hs_info.cn_name, 3589 hint, 3590 ctrl_p->hc_dip, 3591 KM_SLEEP); 3592 } 3593 } 3594 3595 /* restore the power LED state */ 3596 slot_p->hs_led_plat_en[PCIE_LL_ATTENTION_BUTTON] = 3597 false; 3598 pciehpc_sync_leds_to_hw(slot_p); 3599 continue; 3600 } 3601 3602 /* wait for another ATTN button event */ 3603 cv_wait(&slot_p->hs_attn_btn_cv, &ctrl_p->hc_mutex); 3604 } 3605 3606 PCIE_DBG("pciehpc_attn_btn_handler: thread exit\n"); 3607 cv_signal(&slot_p->hs_attn_btn_cv); 3608 CALLB_CPR_EXIT(&cprinfo); 3609 thread_exit(); 3610 } 3611 3612 /* 3613 * convert LED state from PCIE HPC definition to pcie_hp_led_state_t 3614 * definition. 3615 */ 3616 static pcie_hp_led_state_t 3617 pciehpc_led_state_to_hpc(uint16_t state) 3618 { 3619 switch (state) { 3620 case PCIE_SLOTCTL_INDICATOR_STATE_ON: 3621 return (PCIE_HP_LED_ON); 3622 case PCIE_SLOTCTL_INDICATOR_STATE_BLINK: 3623 return (PCIE_HP_LED_BLINK); 3624 case PCIE_SLOTCTL_INDICATOR_STATE_OFF: 3625 default: 3626 return (PCIE_HP_LED_OFF); 3627 } 3628 } 3629 3630 static void 3631 pciehpc_handle_power_fault(dev_info_t *dip) 3632 { 3633 /* 3634 * Hold the parent's ref so that it won't disappear when the taskq is 3635 * scheduled to run. 3636 */ 3637 ndi_hold_devi(dip); 3638 3639 if (taskq_dispatch(system_taskq, pciehpc_power_fault_handler, dip, 3640 TQ_NOSLEEP) == TASKQID_INVALID) { 3641 ndi_rele_devi(dip); 3642 PCIE_DBG("pciehpc_intr(): " 3643 "Failed to dispatch power fault handler, dip %p\n", dip); 3644 } 3645 } 3646 3647 static void 3648 pciehpc_power_fault_handler(void *arg) 3649 { 3650 dev_info_t *dip = (dev_info_t *)arg; 3651 pcie_hp_ctrl_t *ctrl_p; 3652 pcie_hp_slot_t *slot_p; 3653 3654 /* get the soft state structure for this dip */ 3655 if ((ctrl_p = PCIE_GET_HP_CTRL(dip)) == NULL) { 3656 ndi_rele_devi(dip); 3657 return; 3658 } 3659 slot_p = ctrl_p->hc_slots[0]; 3660 3661 /* 3662 * Send the event to DDI Hotplug framework, power off 3663 * the slot 3664 */ 3665 (void) ndi_hp_state_change_req(dip, 3666 slot_p->hs_info.cn_name, 3667 DDI_HP_CN_STATE_PRESENT, DDI_HP_REQ_SYNC); 3668 3669 mutex_enter(&ctrl_p->hc_mutex); 3670 slot_p->hs_led_plat_en[PCIE_LL_POWER_FAULT] = true; 3671 pciehpc_sync_leds_to_hw(slot_p); 3672 mutex_exit(&ctrl_p->hc_mutex); 3673 ndi_rele_devi(dip); 3674 } 3675 3676 #ifdef DEBUG 3677 /* 3678 * Dump PCI-E Hot Plug registers. 3679 */ 3680 static void 3681 pciehpc_dump_hpregs(pcie_hp_ctrl_t *ctrl_p) 3682 { 3683 pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0]; 3684 pcie_bus_t *bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip); 3685 uint16_t control; 3686 uint32_t capabilities; 3687 3688 if (!pcie_debug_flags) 3689 return; 3690 3691 capabilities = pciehpc_reg_get32(ctrl_p, 3692 bus_p->bus_pcie_off + PCIE_SLOTCAP); 3693 3694 control = pciehpc_reg_get16(ctrl_p, 3695 bus_p->bus_pcie_off + PCIE_SLOTCTL); 3696 3697 PCIE_DBG("pciehpc_dump_hpregs: Found PCI-E hot plug slot %d\n", 3698 slot_p->hs_phy_slot_num); 3699 3700 PCIE_DBG("Attention Button Present = %s\n", 3701 capabilities & PCIE_SLOTCAP_ATTN_BUTTON ? "Yes":"No"); 3702 3703 PCIE_DBG("Power controller Present = %s\n", 3704 capabilities & PCIE_SLOTCAP_POWER_CONTROLLER ? "Yes":"No"); 3705 3706 PCIE_DBG("MRL Sensor Present = %s\n", 3707 capabilities & PCIE_SLOTCAP_MRL_SENSOR ? "Yes":"No"); 3708 3709 PCIE_DBG("Attn Indicator Present = %s\n", 3710 capabilities & PCIE_SLOTCAP_ATTN_INDICATOR ? "Yes":"No"); 3711 3712 PCIE_DBG("Power Indicator Present = %s\n", 3713 capabilities & PCIE_SLOTCAP_PWR_INDICATOR ? "Yes":"No"); 3714 3715 PCIE_DBG("HotPlug Surprise = %s\n", 3716 capabilities & PCIE_SLOTCAP_HP_SURPRISE ? "Yes":"No"); 3717 3718 PCIE_DBG("HotPlug Capable = %s\n", 3719 capabilities & PCIE_SLOTCAP_HP_CAPABLE ? "Yes":"No"); 3720 3721 PCIE_DBG("Physical Slot Number = %d\n", 3722 PCIE_SLOTCAP_PHY_SLOT_NUM(capabilities)); 3723 3724 PCIE_DBG("Attn Button interrupt Enabled = %s\n", 3725 control & PCIE_SLOTCTL_ATTN_BTN_EN ? "Yes":"No"); 3726 3727 PCIE_DBG("Power Fault interrupt Enabled = %s\n", 3728 control & PCIE_SLOTCTL_PWR_FAULT_EN ? "Yes":"No"); 3729 3730 PCIE_DBG("MRL Sensor INTR Enabled = %s\n", 3731 control & PCIE_SLOTCTL_MRL_SENSOR_EN ? "Yes":"No"); 3732 3733 PCIE_DBG("Presence interrupt Enabled = %s\n", 3734 control & PCIE_SLOTCTL_PRESENCE_CHANGE_EN ? "Yes":"No"); 3735 3736 PCIE_DBG("Cmd Complete interrupt Enabled = %s\n", 3737 control & PCIE_SLOTCTL_CMD_INTR_EN ? "Yes":"No"); 3738 3739 PCIE_DBG("HotPlug interrupt Enabled = %s\n", 3740 control & PCIE_SLOTCTL_HP_INTR_EN ? "Yes":"No"); 3741 3742 PCIE_DBG("Power Indicator LED = %s", pcie_led_state_text( 3743 pciehpc_led_state_to_hpc(pcie_slotctl_pwr_indicator_get(control)))); 3744 3745 PCIE_DBG("Attn Indicator LED = %s\n", 3746 pcie_led_state_text(pciehpc_led_state_to_hpc( 3747 pcie_slotctl_attn_indicator_get(control)))); 3748 } 3749 #endif /* DEBUG */ 3750