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