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