xref: /illumos-gate/usr/src/uts/common/sys/hotplug/pci/pcie_hp.h (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 2022 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 #endif /* _KERNEL */
38 #include "../../../../../common/pci/pci_strings.h"
39 #include <sys/hotplug/pci/pcihp.h>
40 
41 #define	PCIEHPC_PROP_HELP		"help"
42 #define	PCIEHPC_PROP_ALL		"all"
43 #define	PCIEHPC_PROP_LED_FAULT		"fault_led"
44 #define	PCIEHPC_PROP_LED_POWER		"power_led"
45 #define	PCIEHPC_PROP_LED_ATTN		"attn_led"
46 #define	PCIEHPC_PROP_LED_ACTIVE		"active_led"
47 #define	PCIEHPC_PROP_CARD_TYPE		"card_type"
48 #define	PCIEHPC_PROP_BOARD_TYPE		"board_type"
49 #define	PCIEHPC_PROP_SLOT_CONDITION	"slot_condition"
50 
51 #define	PCIEHPC_PROP_VALUE_UNKNOWN	"unknown"
52 #define	PCIEHPC_PROP_VALUE_ON		"on"
53 #define	PCIEHPC_PROP_VALUE_OFF		"off"
54 #define	PCIEHPC_PROP_VALUE_BLINK	"blink"
55 #define	PCIEHPC_PROP_VALUE_PCIHOTPLUG	"pci hotplug"
56 #define	PCIEHPC_PROP_VALUE_OK		"ok"
57 #define	PCIEHPC_PROP_VALUE_FAILING	"failing"
58 #define	PCIEHPC_PROP_VALUE_FAILED	"failed"
59 #define	PCIEHPC_PROP_VALUE_UNUSABLE	"unusable"
60 #define	PCIEHPC_PROP_VALUE_LED		"<on|off|blink>"
61 #define	PCIEHPC_PROP_VALUE_TYPE		"<type description>"
62 #define	PCIEHPC_PROP_VALUE_CONDITION	"<unknown|ok|failing|failed|unusable>"
63 
64 /* condition */
65 #define	PCIEHPC_PROP_COND_OK		"ok"
66 #define	PCIEHPC_PROP_COND_FAILING	"failing"
67 #define	PCIEHPC_PROP_COND_FAILED	"failed"
68 #define	PCIEHPC_PROP_COND_UNUSABLE	"unusable"
69 #define	PCIEHPC_PROP_COND_UNKNOWN	"unknown"
70 
71 #ifdef _KERNEL
72 
73 #define	PCIE_HP_MAX_SLOTS		31	/* Max # of slots */
74 #define	PCIE_HP_CMD_WAIT_TIME		10000	/* Delay in microseconds */
75 #define	PCIE_HP_CMD_WAIT_RETRY		100	/* Max retry count */
76 #define	PCIE_HP_DLL_STATE_CHANGE_TIMEOUT 1	/* Timeout in seconds */
77 #define	PCIE_HP_POWER_GOOD_WAIT_TIME	220000	/* Wait time after issuing a */
78 						/* cmd to change slot state */
79 
80 /* definations for PCIEHPC/PCISHPC */
81 #define	PCIE_NATIVE_HP_TYPE	"PCIe-Native"		/* PCIe Native type */
82 #define	PCIE_ACPI_HP_TYPE	"PCIe-ACPI"		/* PCIe ACPI type */
83 #define	PCIE_PROP_HP_TYPE	"PCIe-Proprietary"	/* PCIe Prop type */
84 #define	PCIE_PCI_HP_TYPE	"PCI-SHPC"		/* PCI (SHPC) type */
85 
86 #define	PCIE_GET_HP_CTRL(dip)	\
87 	(pcie_hp_ctrl_t *)PCIE_DIP2BUS(dip)->bus_hp_ctrl
88 
89 #define	PCIE_SET_HP_CTRL(dip, ctrl_p) \
90 	(PCIE_DIP2BUS(dip)->bus_hp_ctrl) = (pcie_hp_ctrl_t *)ctrl_p
91 
92 #define	PCIE_IS_PCIE_HOTPLUG_CAPABLE(bus_p) \
93 	((bus_p->bus_hp_sup_modes & PCIE_ACPI_HP_MODE) || \
94 	(bus_p->bus_hp_sup_modes & PCIE_NATIVE_HP_MODE))
95 
96 #define	PCIE_IS_PCI_HOTPLUG_CAPABLE(bus_p) \
97 	(bus_p->bus_hp_sup_modes & PCIE_PCI_HP_MODE)
98 
99 #define	PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p) \
100 	((bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE) || \
101 	(bus_p->bus_hp_curr_mode == PCIE_NATIVE_HP_MODE))
102 
103 #define	PCIE_IS_PCI_HOTPLUG_ENABLED(bus_p) \
104 	(bus_p->bus_hp_curr_mode & PCIE_PCI_HP_MODE)
105 
106 typedef struct pcie_hp_ctrl pcie_hp_ctrl_t;
107 typedef struct pcie_hp_slot pcie_hp_slot_t;
108 
109 /*
110  * Maximum length of the string converted from the digital number of pci device
111  * number and function number, including the string's end mark. For example,
112  * device number 0 and function number 255 (ARI case), then the length is
113  * (1 + 3 + 1).
114  */
115 #define	PCIE_HP_DEV_FUNC_NUM_STRING_LEN 5
116 
117 /*
118  * Length of the characters in a PCI port name.
119  * The format of the PCI port name is: pci.d,f where d is device number, f is
120  * function number. The constant string and characters are "pci." and ",".
121  */
122 #define	PCIE_HP_PORT_NAME_STRING_LEN	5
123 
124 /* Platform specific ops (Native HP, ACPI, etc.) */
125 typedef struct pcie_hp_ops {
126 	/* initialize/setup hot plug controller hw */
127 	int	(*init_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);
128 
129 	/* uninitialize hot plug controller hw */
130 	int	(*uninit_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);
131 
132 	/* initialize slot information structure */
133 	int	(*init_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);
134 
135 	/* uninitialize slot information structure */
136 	int	(*uninit_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);
137 
138 	/* slot poweron */
139 	int	(*poweron_hpc_slot)(pcie_hp_slot_t *slot_p,
140 	    ddi_hp_cn_state_t *result);
141 
142 	/* slot poweroff */
143 	/* uninitialize hot plug controller hw */
144 	int	(*poweroff_hpc_slot)(pcie_hp_slot_t *slot_p,
145 	    ddi_hp_cn_state_t *result);
146 
147 	/* enable hot plug interrupts/events */
148 	int	(*enable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);
149 
150 	/* disable hot plug interrupts/events */
151 	int	(*disable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);
152 } pcie_hp_ops_t;
153 
154 /* Slot occupant information structure */
155 #define	PCIE_HP_MAX_OCCUPANTS	128
156 typedef struct pcie_hp_occupant_info {
157 	int	i;
158 	char	*id[PCIE_HP_MAX_OCCUPANTS];
159 } pcie_hp_occupant_info_t;
160 
161 /*
162  * pcie_hp_led_t
163  *
164  * Type definitions for LED type
165  */
166 typedef	enum {
167 	PCIE_HP_FAULT_LED,
168 	PCIE_HP_POWER_LED,
169 	PCIE_HP_ATTN_LED,
170 	PCIE_HP_ACTIVE_LED
171 } pcie_hp_led_t;
172 
173 /*
174  * pcie_hp_led_state_t
175  *
176  * Type definitions for LED state
177  */
178 typedef	enum {
179 	PCIE_HP_LED_OFF,
180 	PCIE_HP_LED_ON,
181 	PCIE_HP_LED_BLINK
182 } pcie_hp_led_state_t;
183 
184 /*
185  * PCI and PCI Express Hotplug slot structure
186  */
187 struct pcie_hp_slot {
188 	uint32_t	hs_num;			/* Logical slot number */
189 	uint32_t	hs_phy_slot_num;	/* Physical slot number */
190 	uint32_t	hs_device_num;		/* PCI device num for slot */
191 	uint16_t	hs_minor;		/* Minor num for this slot */
192 	ddi_hp_cn_info_t hs_info;		/* Slot information */
193 	ddi_hp_cn_state_t hs_state;		/* Slot state */
194 
195 	pcie_hp_led_state_t hs_power_led_state;		/* Power LED state */
196 	pcie_hp_led_state_t hs_attn_led_state;		/* Attn LED state */
197 	pcie_hp_led_state_t hs_active_led_state;	/* Active LED state */
198 	pcie_hp_led_state_t hs_fault_led_state;		/* Fault LED state */
199 
200 	ap_condition_t	hs_condition;		/* Condition of the slot. */
201 						/* For cfgadm condition. */
202 
203 	/* Synchronization variable(s) for hot plug events */
204 	kcondvar_t	hs_attn_btn_cv;		/* ATTN button pressed intr */
205 	boolean_t	hs_attn_btn_pending;
206 	kthread_t	*hs_attn_btn_threadp;	/* ATTN button event thread */
207 	boolean_t	hs_attn_btn_thread_exit;
208 	kcondvar_t	hs_dll_active_cv;	/* DLL State Changed intr */
209 
210 	pcie_hp_ctrl_t	*hs_ctrl;		/* Hotplug ctrl for this slot */
211 };
212 
213 /*
214  * Register ops for read/write of non-standard HPC (e.g: OPL platform).
215  */
216 typedef struct pcie_hp_regops {
217 	uint_t	(*get)(void *cookie, off_t offset);
218 	uint_t	(*put)(void *cookie, off_t offset, uint_t val);
219 	void	*cookie;
220 } pcie_hp_regops_t;
221 
222 /*
223  * PCI and PCI Express Hotplug controller structure
224  */
225 struct pcie_hp_ctrl {
226 	dev_info_t	*hc_dip;		/* DIP for HP controller */
227 	kmutex_t	hc_mutex;		/* Mutex for this ctrl */
228 	uint_t		hc_flags;		/* Misc flags */
229 
230 	/* Slot information */
231 	pcie_hp_slot_t	*hc_slots[PCIE_HP_MAX_SLOTS]; /* Slot pointers */
232 	boolean_t	hc_has_attn;		/* Do we have attn btn?	*/
233 	boolean_t	hc_has_mrl;		/* Do we have MRL? */
234 	boolean_t	hc_has_pwr;		/* Do we have a power ctl? */
235 	kcondvar_t	hc_cmd_comp_cv;		/* Command Completion intr */
236 	boolean_t	hc_cmd_pending;		/* Command completion pending */
237 
238 	/* PCI Express Hotplug specific fields */
239 	boolean_t	hc_has_emi_lock;	/* Do we have EMI Lock? */
240 	boolean_t	hc_dll_active_rep;	/* Report DLL DL_Active state */
241 	pcie_hp_ops_t	hc_ops;			/* Platform specific ops */
242 						/* (Native, ACPI) */
243 
244 	/* PCI Hotplug (SHPC) specific fields */
245 	uint32_t	hc_num_slots_impl;	/* # of HP Slots Implemented */
246 	uint32_t	hc_num_slots_connected;	/* # of HP Slots Connected */
247 	int		hc_curr_bus_speed;	/* Current Bus Speed */
248 	uint32_t	hc_device_start;	/* 1st PCI Device # */
249 	uint32_t	hc_phys_start;		/* 1st Phys Device # */
250 	uint32_t	hc_device_increases;	/* Device # Increases */
251 	boolean_t	hc_arbiter_timeout;	/* Got a Arb timeout IRQ */
252 
253 	/* Register read/write ops for non-standard HPC (e.g: OPL) */
254 	pcie_hp_regops_t hc_regops;
255 
256 	/* Platform implementation specific data if any: ACPI, CK804,... */
257 	void		*hc_misc_data;
258 };
259 
260 /*
261  * Control structure for tree walk during configure/unconfigure operation.
262  */
263 typedef struct pcie_hp_cn_cfg_t {
264 	void *slotp;
265 	boolean_t		flag;		/* Flag to ignore errors */
266 	int			rv;		/* Return error code */
267 	dev_info_t		*dip;		/* dip at which the (first) */
268 						/* error occurred */
269 	void			*cn_private;	/* Connection specific data */
270 } pcie_hp_cn_cfg_t;
271 
272 /*
273  * arg for unregistering port of a pci bridge
274  */
275 typedef struct pcie_hp_unreg_port {
276 	/* pci bridge dip to which the port is associated */
277 	dev_info_t	*nexus_dip;
278 	/*
279 	 * Connector number of the physical slot whose dependent ports will be
280 	 * unregistered. If NULL, then all the ports of the pci bridge dip will
281 	 * be unregistered.
282 	 */
283 	int		connector_num;
284 	int		rv;
285 } pcie_hp_unreg_port_t;
286 
287 /*
288  * arg for getting a port's state
289  */
290 typedef struct pcie_hp_port_state {
291 	char			*cn_name;
292 	ddi_hp_cn_state_t	cn_state;
293 	int			rv;
294 } pcie_hp_port_state_t;
295 
296 /* hc_flags */
297 #define	PCIE_HP_INITIALIZED_FLAG	(1 << 0) /* HPC initialized */
298 
299 /* PCIe hotplug friendly functions */
300 extern int pcie_hp_init(dev_info_t *dip, caddr_t arg);
301 extern int pcie_hp_uninit(dev_info_t *dip);
302 extern int pcie_hp_intr(dev_info_t *dip);
303 extern int pcie_hp_probe(pcie_hp_slot_t *slot_p);
304 extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p);
305 extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op,
306     void *arg, void *result);
307 extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device,
308     uint_t function);
309 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
310     int pci_dev);
311 extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
312     int pci_dev);
313 extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev);
314 extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz,
315     nvlist_t **nvlp);
316 extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf,
317     size_t *packed_sz);
318 extern char *pcie_led_state_text(pcie_hp_led_state_t state);
319 extern char *pcie_slot_condition_text(ap_condition_t condition);
320 extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int);
321 extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int);
322 extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint,
323     dev_info_t *self, int kmflag);
324 
325 extern const struct pci_class_strings_s class_pci[];
326 extern int class_pci_items;
327 
328 #endif /* _KERNEL */
329 
330 #ifdef	__cplusplus
331 }
332 #endif
333 
334 #endif	/* _SYS_PCIE_HP_H */
335