xref: /illumos-gate/usr/src/uts/common/sys/hotplug/pci/pcie_hp.h (revision c43efa7f6b109f90d7f4962df8c0e1a94008d2d1)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2023 Oxide Computer Company
25  */
26 
27 #ifndef	_SYS_PCIE_HP_H
28 #define	_SYS_PCIE_HP_H
29 
30 #ifdef	__cplusplus
31 extern "C" {
32 #endif
33 
34 #ifdef _KERNEL
35 #include <sys/ddi_hp.h>
36 #include <sys/pcie_impl.h>
37 #include <sys/stdbool.h>
38 #endif /* _KERNEL */
39 #include "../../../../../common/pci/pci_strings.h"
40 #include <sys/hotplug/pci/pcihp.h>
41 
42 #define	PCIEHPC_PROP_HELP		"help"
43 #define	PCIEHPC_PROP_ALL		"all"
44 #define	PCIEHPC_PROP_LED_FAULT		"fault_led"
45 #define	PCIEHPC_PROP_LED_POWER		"power_led"
46 #define	PCIEHPC_PROP_LED_ATTN		"attn_led"
47 #define	PCIEHPC_PROP_LED_ACTIVE		"active_led"
48 #define	PCIEHPC_PROP_CARD_TYPE		"card_type"
49 #define	PCIEHPC_PROP_BOARD_TYPE		"board_type"
50 #define	PCIEHPC_PROP_SLOT_CONDITION	"slot_condition"
51 
52 #define	PCIEHPC_PROP_VALUE_UNKNOWN	"unknown"
53 #define	PCIEHPC_PROP_VALUE_ON		"on"
54 #define	PCIEHPC_PROP_VALUE_OFF		"off"
55 #define	PCIEHPC_PROP_VALUE_BLINK	"blink"
56 #define	PCIEHPC_PROP_VALUE_DEFAULT	"default"
57 #define	PCIEHPC_PROP_VALUE_PCIHOTPLUG	"pci hotplug"
58 #define	PCIEHPC_PROP_VALUE_OK		"ok"
59 #define	PCIEHPC_PROP_VALUE_FAILING	"failing"
60 #define	PCIEHPC_PROP_VALUE_FAILED	"failed"
61 #define	PCIEHPC_PROP_VALUE_UNUSABLE	"unusable"
62 #define	PCIEHPC_PROP_VALUE_LED		"<on|off|blink>"
63 #define	PCIEHPC_PROP_VALUE_LED_DEF	"<on|off|blink|default>"
64 #define	PCIEHPC_PROP_VALUE_TYPE		"<type description>"
65 #define	PCIEHPC_PROP_VALUE_CONDITION	"<unknown|ok|failing|failed|unusable>"
66 
67 /* condition */
68 #define	PCIEHPC_PROP_COND_OK		"ok"
69 #define	PCIEHPC_PROP_COND_FAILING	"failing"
70 #define	PCIEHPC_PROP_COND_FAILED	"failed"
71 #define	PCIEHPC_PROP_COND_UNUSABLE	"unusable"
72 #define	PCIEHPC_PROP_COND_UNKNOWN	"unknown"
73 
74 #ifdef _KERNEL
75 
76 #define	PCIE_HP_MAX_SLOTS		31	/* Max # of slots */
77 #define	PCIE_HP_CMD_WAIT_TIME		10000	/* Delay in microseconds */
78 #define	PCIE_HP_CMD_WAIT_RETRY		100	/* Max retry count */
79 #define	PCIE_HP_DLL_STATE_CHANGE_TIMEOUT 1	/* Timeout in seconds */
80 #define	PCIE_HP_POWER_GOOD_WAIT_TIME	220000	/* Wait time after issuing a */
81 						/* cmd to change slot state */
82 
83 /* Definitions for PCIEHPC/PCISHPC */
84 #define	PCIE_NATIVE_HP_TYPE	"PCIe-Native"		/* PCIe Native type */
85 #define	PCIE_ACPI_HP_TYPE	"PCIe-ACPI"		/* PCIe ACPI type */
86 #define	PCIE_PROP_HP_TYPE	"PCIe-Proprietary"	/* PCIe Prop type */
87 #define	PCIE_PCI_HP_TYPE	"PCI-SHPC"		/* PCI (SHPC) type */
88 
89 #define	PCIE_GET_HP_CTRL(dip)	\
90 	(pcie_hp_ctrl_t *)PCIE_DIP2BUS(dip)->bus_hp_ctrl
91 
92 #define	PCIE_SET_HP_CTRL(dip, ctrl_p) \
93 	(PCIE_DIP2BUS(dip)->bus_hp_ctrl) = (pcie_hp_ctrl_t *)ctrl_p
94 
95 #define	PCIE_IS_PCIE_HOTPLUG_CAPABLE(bus_p) \
96 	((bus_p->bus_hp_sup_modes & PCIE_ACPI_HP_MODE) || \
97 	(bus_p->bus_hp_sup_modes & PCIE_NATIVE_HP_MODE))
98 
99 #define	PCIE_IS_PCI_HOTPLUG_CAPABLE(bus_p) \
100 	(bus_p->bus_hp_sup_modes & PCIE_PCI_HP_MODE)
101 
102 #define	PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p) \
103 	((bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE) || \
104 	(bus_p->bus_hp_curr_mode == PCIE_NATIVE_HP_MODE))
105 
106 #define	PCIE_IS_PCI_HOTPLUG_ENABLED(bus_p) \
107 	(bus_p->bus_hp_curr_mode & PCIE_PCI_HP_MODE)
108 
109 typedef struct pcie_hp_ctrl pcie_hp_ctrl_t;
110 typedef struct pcie_hp_slot pcie_hp_slot_t;
111 
112 /*
113  * Maximum length of the string converted from the digital number of pci device
114  * number and function number, including the string's end mark. For example,
115  * device number 0 and function number 255 (ARI case), then the length is
116  * (1 + 3 + 1).
117  */
118 #define	PCIE_HP_DEV_FUNC_NUM_STRING_LEN 5
119 
120 /*
121  * Length of the characters in a PCI port name.
122  * The format of the PCI port name is: pci.d,f where d is device number, f is
123  * function number. The constant string and characters are "pci." and ",".
124  */
125 #define	PCIE_HP_PORT_NAME_STRING_LEN	5
126 
127 /* Platform specific ops (Native HP, ACPI, etc.) */
128 typedef struct pcie_hp_ops {
129 	/* initialize/setup hot plug controller hw */
130 	int	(*init_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);
131 
132 	/* uninitialize hot plug controller hw */
133 	int	(*uninit_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);
134 
135 	/* initialize slot information structure */
136 	int	(*init_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);
137 
138 	/* uninitialize slot information structure */
139 	int	(*uninit_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);
140 
141 	/* slot poweron */
142 	int	(*poweron_hpc_slot)(pcie_hp_slot_t *slot_p,
143 	    ddi_hp_cn_state_t *result);
144 
145 	/* slot poweroff */
146 	/* uninitialize hot plug controller hw */
147 	int	(*poweroff_hpc_slot)(pcie_hp_slot_t *slot_p,
148 	    ddi_hp_cn_state_t *result);
149 
150 	/* enable hot plug interrupts/events */
151 	int	(*enable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);
152 
153 	/* disable hot plug interrupts/events */
154 	int	(*disable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);
155 } pcie_hp_ops_t;
156 
157 /* Slot occupant information structure */
158 #define	PCIE_HP_MAX_OCCUPANTS	128
159 typedef struct pcie_hp_occupant_info {
160 	int	i;
161 	char	*id[PCIE_HP_MAX_OCCUPANTS];
162 } pcie_hp_occupant_info_t;
163 
164 /*
165  * pcie_hp_led_t
166  *
167  * Type definitions for LED type. These are all the types of LEDs that the
168  * subsystem knows about; however, both PCIe and SHPC only implement the Power
169  * and Attention LEDs.
170  */
171 typedef	enum {
172 	PCIE_HP_FAULT_LED,
173 	PCIE_HP_POWER_LED,
174 	PCIE_HP_ATTN_LED,
175 	PCIE_HP_ACTIVE_LED
176 } pcie_hp_led_t;
177 
178 /*
179  * pcie_hp_led_state_t
180  *
181  * Type definitions for LED state. This structure represents the underlying
182  * hardware state and not what we are using for tracking the meta state
183  * ourselves.
184  */
185 typedef	enum {
186 	PCIE_HP_LED_OFF = 0,
187 	PCIE_HP_LED_ON,
188 	PCIE_HP_LED_BLINK
189 } pcie_hp_led_state_t;
190 
191 /*
192  * The following enumerations and structures are used to track the way that we
193  * manage LEDs for the native PCIe hotplug subsystem. See the 'LED Management'
194  * section of the theory statement of uts/common/io/pciex/hotplug/pciehpc.c for
195  * more information. While this is all specific to the native PCIe
196  * implementation there and not used for the SHPC bits, because everything uses
197  * a shared structure for slots, we must track that here.
198  *
199  * Roughly the pcie_hp_led_act_t is used to describe what we can do to an LED in
200  * our table. The pciehpc_logical_led_t describes the different LED states that
201  * we can be in. Finally, the pciehpc_led_plat_id_t is yet another LED
202  * definition. This would be much simpler if the pcie_hp_led_t reflected
203  * reality.
204  */
205 typedef enum pcie_hp_led_act {
206 	PCIE_HLA_PASS,
207 	PCIE_HLA_OFF,
208 	PCIE_HLA_ON,
209 	PCIE_HLA_BLINK
210 } pcie_hp_led_act_t;
211 
212 typedef enum pciehpc_logical_led {
213 	/*
214 	 * The base case here indicates what should happen when we have a slot
215 	 * without power and no device present.
216 	 */
217 	PCIE_LL_BASE			= 0,
218 	/*
219 	 * This is the state that the system should be in when a device is
220 	 * powered.
221 	 */
222 	PCIE_LL_POWERED,
223 	/*
224 	 * This indicates what should happen when an explicit power transition
225 	 * has been requested. The standard PCIe activity is to blink the power
226 	 * LED.
227 	 */
228 	PCIE_LL_POWER_TRANSITION,
229 	/*
230 	 * This is the activity to take when a device driver probe has failed.
231 	 * This lasts until another state transition or acknowledgement.
232 	 */
233 	PCIE_LL_PROBE_FAILED,
234 	/*
235 	 * This is the activity to take when a power fault occurs. This will
236 	 * remain until a device is removed or an active state transition
237 	 * occurs.
238 	 */
239 	PCIE_LL_POWER_FAULT,
240 	/*
241 	 * This is the activity to take when the attention button has been
242 	 * pushed during the 5 second window that is used to confirm behavior.
243 	 */
244 	PCIE_LL_ATTENTION_BUTTON
245 } pciehpc_logical_led_t;
246 
247 #define	PCIEHPC_LED_NSTATES	6
248 CTASSERT(PCIEHPC_LED_NSTATES == PCIE_LL_ATTENTION_BUTTON + 1);
249 
250 typedef enum {
251 	PCIEHPC_PLAT_ID_POWER,
252 	PCIEHPC_PLAT_ID_ATTN
253 } pciehpc_led_plat_id_t;
254 
255 #define	PCIEHPC_LED_NLEDS	2
256 CTASSERT(PCIEHPC_LED_NLEDS == PCIEHPC_PLAT_ID_ATTN + 1);
257 
258 typedef struct pciehpc_led_plat_state {
259 	pcie_hp_led_act_t plps_acts[PCIEHPC_LED_NLEDS];
260 } pciehpc_led_plat_state_t;
261 
262 /*
263  * PCI and PCI Express Hotplug slot structure
264  */
265 struct pcie_hp_slot {
266 	uint32_t	hs_num;			/* Logical slot number */
267 	uint32_t	hs_phy_slot_num;	/* Physical slot number */
268 	uint32_t	hs_device_num;		/* PCI device num for slot */
269 	uint16_t	hs_minor;		/* Minor num for this slot */
270 	ddi_hp_cn_info_t hs_info;		/* Slot information */
271 	ddi_hp_cn_state_t hs_state;		/* Slot state */
272 
273 	/*
274 	 * LED states are split into three groups. The first group is the state
275 	 * that we believe we should have set into hardware. This state is the
276 	 * only state the SHPC form of the hotplug controller uses. While there
277 	 * are four LEDs here, only two are actually supported by the SHPC and
278 	 * PCIe controllers: the attention and power LEDs.
279 	 *
280 	 * The subsequent two groups are only used by the PCIe backend. In the
281 	 * future we should consider whether or not these structures really
282 	 * should be shared by all hotplug backends (especially when we add the
283 	 * ACPI/PCI hotplug scheme that virtual machines use).
284 	 */
285 	pcie_hp_led_state_t hs_power_led_state;		/* Power LED state */
286 	pcie_hp_led_state_t hs_attn_led_state;		/* Attn LED state */
287 	pcie_hp_led_state_t hs_active_led_state;	/* Active LED state */
288 	pcie_hp_led_state_t hs_fault_led_state;		/* Fault LED state */
289 
290 	/*
291 	 * The second of three LED groups. This is used to track when a user
292 	 * overrides an LED. This is separate from the third group so we can
293 	 * always return to the expected LED behavior when the override is
294 	 * disabled again. Currently only used by the PCIe backend.
295 	 */
296 	pcie_hp_led_state_t hs_power_usr_ovr_state;
297 	pcie_hp_led_state_t hs_attn_usr_ovr_state;
298 	bool hs_power_usr_ovr;
299 	bool hs_attn_usr_ovr;
300 
301 	/*
302 	 * The final group of LED state. This array tracks logical events that
303 	 * have occurred in the hotplug controller. Higher indexed events that
304 	 * are true take priority over lower indexed ones. The actual mapping of
305 	 * states to LEDs is in hs_led_plat_conf. For more information see the
306 	 * pciehpc.c theory statement.
307 	 */
308 	bool hs_led_plat_en[PCIEHPC_LED_NSTATES];
309 	const pciehpc_led_plat_state_t *hs_led_plat_conf;
310 
311 	ap_condition_t	hs_condition;		/* Condition of the slot. */
312 						/* For cfgadm condition. */
313 
314 	/* Synchronization variable(s) for hot plug events */
315 	kcondvar_t	hs_attn_btn_cv;		/* ATTN button pressed intr */
316 	boolean_t	hs_attn_btn_pending;
317 	kthread_t	*hs_attn_btn_threadp;	/* ATTN button event thread */
318 	boolean_t	hs_attn_btn_thread_exit;
319 	kcondvar_t	hs_dll_active_cv;	/* DLL State Changed intr */
320 
321 	pcie_hp_ctrl_t	*hs_ctrl;		/* Hotplug ctrl for this slot */
322 };
323 
324 /*
325  * Register ops for read/write of non-standard HPC (e.g: OPL platform).
326  */
327 typedef struct pcie_hp_regops {
328 	uint_t	(*get)(void *cookie, off_t offset);
329 	uint_t	(*put)(void *cookie, off_t offset, uint_t val);
330 	void	*cookie;
331 } pcie_hp_regops_t;
332 
333 /*
334  * PCI and PCI Express Hotplug controller structure
335  */
336 struct pcie_hp_ctrl {
337 	dev_info_t	*hc_dip;		/* DIP for HP controller */
338 	kmutex_t	hc_mutex;		/* Mutex for this ctrl */
339 	uint_t		hc_flags;		/* Misc flags */
340 
341 	/* Slot information */
342 	pcie_hp_slot_t	*hc_slots[PCIE_HP_MAX_SLOTS]; /* Slot pointers */
343 	boolean_t	hc_has_attn;		/* Do we have attn btn?	*/
344 	boolean_t	hc_has_mrl;		/* Do we have MRL? */
345 	boolean_t	hc_has_pwr;		/* Do we have a power ctl? */
346 	kcondvar_t	hc_cmd_comp_cv;		/* Command Completion intr */
347 	boolean_t	hc_cmd_pending;		/* Command completion pending */
348 
349 	/* PCI Express Hotplug specific fields */
350 	boolean_t	hc_has_emi_lock;	/* Do we have EMI Lock? */
351 	boolean_t	hc_dll_active_rep;	/* Report DLL DL_Active state */
352 	taskqid_t	hc_startup_sync;	/* Startup synched? */
353 	pcie_hp_ops_t	hc_ops;			/* Platform specific ops */
354 						/* (Native, ACPI) */
355 
356 	/* PCI Hotplug (SHPC) specific fields */
357 	uint32_t	hc_num_slots_impl;	/* # of HP Slots Implemented */
358 	uint32_t	hc_num_slots_connected;	/* # of HP Slots Connected */
359 	int		hc_curr_bus_speed;	/* Current Bus Speed */
360 	uint32_t	hc_device_start;	/* 1st PCI Device # */
361 	uint32_t	hc_phys_start;		/* 1st Phys Device # */
362 	uint32_t	hc_device_increases;	/* Device # Increases */
363 	boolean_t	hc_arbiter_timeout;	/* Got a Arb timeout IRQ */
364 
365 	/* Register read/write ops for non-standard HPC (e.g: OPL) */
366 	pcie_hp_regops_t hc_regops;
367 
368 	/* Platform implementation specific data if any: ACPI, CK804,... */
369 	void		*hc_misc_data;
370 };
371 
372 /*
373  * Control structure for tree walk during configure/unconfigure operation.
374  */
375 typedef struct pcie_hp_cn_cfg_t {
376 	void *slotp;
377 	boolean_t		flag;		/* Flag to ignore errors */
378 	int			rv;		/* Return error code */
379 	dev_info_t		*dip;		/* dip at which the (first) */
380 						/* error occurred */
381 	void			*cn_private;	/* Connection specific data */
382 } pcie_hp_cn_cfg_t;
383 
384 /*
385  * arg for unregistering port of a pci bridge
386  */
387 typedef struct pcie_hp_unreg_port {
388 	/* pci bridge dip to which the port is associated */
389 	dev_info_t	*nexus_dip;
390 	/*
391 	 * Connector number of the physical slot whose dependent ports will be
392 	 * unregistered. If NULL, then all the ports of the pci bridge dip will
393 	 * be unregistered.
394 	 */
395 	int		connector_num;
396 	int		rv;
397 } pcie_hp_unreg_port_t;
398 
399 /*
400  * arg for getting a port's state
401  */
402 typedef struct pcie_hp_port_state {
403 	char			*cn_name;
404 	ddi_hp_cn_state_t	cn_state;
405 	int			rv;
406 } pcie_hp_port_state_t;
407 
408 /* hc_flags */
409 #define	PCIE_HP_INITIALIZED_FLAG	(1 << 0) /* HPC initialized */
410 /*
411  * These two flags are all related to initial synchronization. See
412  * uts/common/io/pciex/hotplug/pciehpc.c for more information. The first is used
413  * to track that this is required while the second indicates that it's actively
414  * occurring.
415  */
416 #define	PCIE_HP_SYNC_PENDING		(1 << 1)
417 #define	PCIE_HP_SYNC_RUNNING		(1 << 2)
418 
419 /* PCIe hotplug friendly functions */
420 extern int pcie_hp_init(dev_info_t *dip, caddr_t arg);
421 extern int pcie_hp_uninit(dev_info_t *dip);
422 extern int pcie_hp_intr(dev_info_t *dip);
423 extern int pcie_hp_probe(pcie_hp_slot_t *slot_p);
424 extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p);
425 extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op,
426     void *arg, void *result);
427 extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device,
428     uint_t function);
429 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
430     int pci_dev);
431 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
432     int pci_dev);
433 extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev);
434 extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz,
435     nvlist_t **nvlp);
436 extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf,
437     size_t *packed_sz);
438 extern char *pcie_led_state_text(pcie_hp_led_state_t state);
439 extern char *pcie_slot_condition_text(ap_condition_t condition);
440 extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int);
441 extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int);
442 extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint,
443     dev_info_t *self, int kmflag);
444 
445 #endif /* _KERNEL */
446 
447 #ifdef	__cplusplus
448 }
449 #endif
450 
451 #endif	/* _SYS_PCIE_HP_H */
452