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