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