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