summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/hotplug/pci/pcie_hp.h
blob: 83b5bde6b59eb045b41a402c6676365caec99d7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 * Copyright 2022 Oxide Computer Company
 */

#ifndef	_SYS_PCIE_HP_H
#define	_SYS_PCIE_HP_H

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL
#include <sys/ddi_hp.h>
#include <sys/pcie_impl.h>
#endif /* _KERNEL */
#include "../../../../../common/pci/pci_strings.h"
#include <sys/hotplug/pci/pcihp.h>

#define	PCIEHPC_PROP_HELP		"help"
#define	PCIEHPC_PROP_ALL		"all"
#define	PCIEHPC_PROP_LED_FAULT		"fault_led"
#define	PCIEHPC_PROP_LED_POWER		"power_led"
#define	PCIEHPC_PROP_LED_ATTN		"attn_led"
#define	PCIEHPC_PROP_LED_ACTIVE		"active_led"
#define	PCIEHPC_PROP_CARD_TYPE		"card_type"
#define	PCIEHPC_PROP_BOARD_TYPE		"board_type"
#define	PCIEHPC_PROP_SLOT_CONDITION	"slot_condition"

#define	PCIEHPC_PROP_VALUE_UNKNOWN	"unknown"
#define	PCIEHPC_PROP_VALUE_ON		"on"
#define	PCIEHPC_PROP_VALUE_OFF		"off"
#define	PCIEHPC_PROP_VALUE_BLINK	"blink"
#define	PCIEHPC_PROP_VALUE_PCIHOTPLUG	"pci hotplug"
#define	PCIEHPC_PROP_VALUE_OK		"ok"
#define	PCIEHPC_PROP_VALUE_FAILING	"failing"
#define	PCIEHPC_PROP_VALUE_FAILED	"failed"
#define	PCIEHPC_PROP_VALUE_UNUSABLE	"unusable"
#define	PCIEHPC_PROP_VALUE_LED		"<on|off|blink>"
#define	PCIEHPC_PROP_VALUE_TYPE		"<type description>"
#define	PCIEHPC_PROP_VALUE_CONDITION	"<unknown|ok|failing|failed|unusable>"

/* condition */
#define	PCIEHPC_PROP_COND_OK		"ok"
#define	PCIEHPC_PROP_COND_FAILING	"failing"
#define	PCIEHPC_PROP_COND_FAILED	"failed"
#define	PCIEHPC_PROP_COND_UNUSABLE	"unusable"
#define	PCIEHPC_PROP_COND_UNKNOWN	"unknown"

#ifdef _KERNEL

#define	PCIE_HP_MAX_SLOTS		31	/* Max # of slots */
#define	PCIE_HP_CMD_WAIT_TIME		10000	/* Delay in microseconds */
#define	PCIE_HP_CMD_WAIT_RETRY		100	/* Max retry count */
#define	PCIE_HP_DLL_STATE_CHANGE_TIMEOUT 1	/* Timeout in seconds */
#define	PCIE_HP_POWER_GOOD_WAIT_TIME	220000	/* Wait time after issuing a */
						/* cmd to change slot state */

/* definations for PCIEHPC/PCISHPC */
#define	PCIE_NATIVE_HP_TYPE	"PCIe-Native"		/* PCIe Native type */
#define	PCIE_ACPI_HP_TYPE	"PCIe-ACPI"		/* PCIe ACPI type */
#define	PCIE_PROP_HP_TYPE	"PCIe-Proprietary"	/* PCIe Prop type */
#define	PCIE_PCI_HP_TYPE	"PCI-SHPC"		/* PCI (SHPC) type */

#define	PCIE_GET_HP_CTRL(dip)	\
	(pcie_hp_ctrl_t *)PCIE_DIP2BUS(dip)->bus_hp_ctrl

#define	PCIE_SET_HP_CTRL(dip, ctrl_p) \
	(PCIE_DIP2BUS(dip)->bus_hp_ctrl) = (pcie_hp_ctrl_t *)ctrl_p

#define	PCIE_IS_PCIE_HOTPLUG_CAPABLE(bus_p) \
	((bus_p->bus_hp_sup_modes & PCIE_ACPI_HP_MODE) || \
	(bus_p->bus_hp_sup_modes & PCIE_NATIVE_HP_MODE))

#define	PCIE_IS_PCI_HOTPLUG_CAPABLE(bus_p) \
	(bus_p->bus_hp_sup_modes & PCIE_PCI_HP_MODE)

#define	PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p) \
	((bus_p->bus_hp_curr_mode == PCIE_ACPI_HP_MODE) || \
	(bus_p->bus_hp_curr_mode == PCIE_NATIVE_HP_MODE))

#define	PCIE_IS_PCI_HOTPLUG_ENABLED(bus_p) \
	(bus_p->bus_hp_curr_mode & PCIE_PCI_HP_MODE)

typedef struct pcie_hp_ctrl pcie_hp_ctrl_t;
typedef struct pcie_hp_slot pcie_hp_slot_t;

/*
 * Maximum length of the string converted from the digital number of pci device
 * number and function number, including the string's end mark. For example,
 * device number 0 and function number 255 (ARI case), then the length is
 * (1 + 3 + 1).
 */
#define	PCIE_HP_DEV_FUNC_NUM_STRING_LEN 5

/*
 * Length of the characters in a PCI port name.
 * The format of the PCI port name is: pci.d,f where d is device number, f is
 * function number. The constant string and characters are "pci." and ",".
 */
#define	PCIE_HP_PORT_NAME_STRING_LEN	5

/* Platform specific ops (Native HP, ACPI, etc.) */
typedef struct pcie_hp_ops {
	/* initialize/setup hot plug controller hw */
	int	(*init_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);

	/* uninitialize hot plug controller hw */
	int	(*uninit_hpc_hw)(pcie_hp_ctrl_t *ctrl_p);

	/* initialize slot information structure */
	int	(*init_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);

	/* uninitialize slot information structure */
	int	(*uninit_hpc_slotinfo)(pcie_hp_ctrl_t *ctrl_p);

	/* slot poweron */
	int	(*poweron_hpc_slot)(pcie_hp_slot_t *slot_p,
	    ddi_hp_cn_state_t *result);

	/* slot poweroff */
	/* uninitialize hot plug controller hw */
	int	(*poweroff_hpc_slot)(pcie_hp_slot_t *slot_p,
	    ddi_hp_cn_state_t *result);

	/* enable hot plug interrupts/events */
	int	(*enable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);

	/* disable hot plug interrupts/events */
	int	(*disable_hpc_intr)(pcie_hp_ctrl_t *ctrl_p);
} pcie_hp_ops_t;

/* Slot occupant information structure */
#define	PCIE_HP_MAX_OCCUPANTS	128
typedef struct pcie_hp_occupant_info {
	int	i;
	char	*id[PCIE_HP_MAX_OCCUPANTS];
} pcie_hp_occupant_info_t;

/*
 * pcie_hp_led_t
 *
 * Type definitions for LED type
 */
typedef	enum {
	PCIE_HP_FAULT_LED,
	PCIE_HP_POWER_LED,
	PCIE_HP_ATTN_LED,
	PCIE_HP_ACTIVE_LED
} pcie_hp_led_t;

/*
 * pcie_hp_led_state_t
 *
 * Type definitions for LED state
 */
typedef	enum {
	PCIE_HP_LED_OFF,
	PCIE_HP_LED_ON,
	PCIE_HP_LED_BLINK
} pcie_hp_led_state_t;

/*
 * PCI and PCI Express Hotplug slot structure
 */
struct pcie_hp_slot {
	uint32_t	hs_num;			/* Logical slot number */
	uint32_t	hs_phy_slot_num;	/* Physical slot number */
	uint32_t	hs_device_num;		/* PCI device num for slot */
	uint16_t	hs_minor;		/* Minor num for this slot */
	ddi_hp_cn_info_t hs_info;		/* Slot information */
	ddi_hp_cn_state_t hs_state;		/* Slot state */

	pcie_hp_led_state_t hs_power_led_state;		/* Power LED state */
	pcie_hp_led_state_t hs_attn_led_state;		/* Attn LED state */
	pcie_hp_led_state_t hs_active_led_state;	/* Active LED state */
	pcie_hp_led_state_t hs_fault_led_state;		/* Fault LED state */

	ap_condition_t	hs_condition;		/* Condition of the slot. */
						/* For cfgadm condition. */

	/* Synchronization variable(s) for hot plug events */
	kcondvar_t	hs_attn_btn_cv;		/* ATTN button pressed intr */
	boolean_t	hs_attn_btn_pending;
	kthread_t	*hs_attn_btn_threadp;	/* ATTN button event thread */
	boolean_t	hs_attn_btn_thread_exit;
	kcondvar_t	hs_dll_active_cv;	/* DLL State Changed intr */

	pcie_hp_ctrl_t	*hs_ctrl;		/* Hotplug ctrl for this slot */
};

/*
 * Register ops for read/write of non-standard HPC (e.g: OPL platform).
 */
typedef struct pcie_hp_regops {
	uint_t	(*get)(void *cookie, off_t offset);
	uint_t	(*put)(void *cookie, off_t offset, uint_t val);
	void	*cookie;
} pcie_hp_regops_t;

/*
 * PCI and PCI Express Hotplug controller structure
 */
struct pcie_hp_ctrl {
	dev_info_t	*hc_dip;		/* DIP for HP controller */
	kmutex_t	hc_mutex;		/* Mutex for this ctrl */
	uint_t		hc_flags;		/* Misc flags */

	/* Slot information */
	pcie_hp_slot_t	*hc_slots[PCIE_HP_MAX_SLOTS]; /* Slot pointers */
	boolean_t	hc_has_attn;		/* Do we have attn btn?	*/
	boolean_t	hc_has_mrl;		/* Do we have MRL? */
	boolean_t	hc_has_pwr;		/* Do we have a power ctl? */
	kcondvar_t	hc_cmd_comp_cv;		/* Command Completion intr */
	boolean_t	hc_cmd_pending;		/* Command completion pending */

	/* PCI Express Hotplug specific fields */
	boolean_t	hc_has_emi_lock;	/* Do we have EMI Lock? */
	boolean_t	hc_dll_active_rep;	/* Report DLL DL_Active state */
	pcie_hp_ops_t	hc_ops;			/* Platform specific ops */
						/* (Native, ACPI) */

	/* PCI Hotplug (SHPC) specific fields */
	uint32_t	hc_num_slots_impl;	/* # of HP Slots Implemented */
	uint32_t	hc_num_slots_connected;	/* # of HP Slots Connected */
	int		hc_curr_bus_speed;	/* Current Bus Speed */
	uint32_t	hc_device_start;	/* 1st PCI Device # */
	uint32_t	hc_phys_start;		/* 1st Phys Device # */
	uint32_t	hc_device_increases;	/* Device # Increases */
	boolean_t	hc_arbiter_timeout;	/* Got a Arb timeout IRQ */

	/* Register read/write ops for non-standard HPC (e.g: OPL) */
	pcie_hp_regops_t hc_regops;

	/* Platform implementation specific data if any: ACPI, CK804,... */
	void		*hc_misc_data;
};

/*
 * Control structure for tree walk during configure/unconfigure operation.
 */
typedef struct pcie_hp_cn_cfg_t {
	void *slotp;
	boolean_t		flag;		/* Flag to ignore errors */
	int			rv;		/* Return error code */
	dev_info_t		*dip;		/* dip at which the (first) */
						/* error occurred */
	void			*cn_private;	/* Connection specific data */
} pcie_hp_cn_cfg_t;

/*
 * arg for unregistering port of a pci bridge
 */
typedef struct pcie_hp_unreg_port {
	/* pci bridge dip to which the port is associated */
	dev_info_t	*nexus_dip;
	/*
	 * Connector number of the physical slot whose dependent ports will be
	 * unregistered. If NULL, then all the ports of the pci bridge dip will
	 * be unregistered.
	 */
	int		connector_num;
	int		rv;
} pcie_hp_unreg_port_t;

/*
 * arg for getting a port's state
 */
typedef struct pcie_hp_port_state {
	char			*cn_name;
	ddi_hp_cn_state_t	cn_state;
	int			rv;
} pcie_hp_port_state_t;

/* hc_flags */
#define	PCIE_HP_INITIALIZED_FLAG	(1 << 0) /* HPC initialized */

/* PCIe hotplug friendly functions */
extern int pcie_hp_init(dev_info_t *dip, caddr_t arg);
extern int pcie_hp_uninit(dev_info_t *dip);
extern int pcie_hp_intr(dev_info_t *dip);
extern int pcie_hp_probe(pcie_hp_slot_t *slot_p);
extern int pcie_hp_unprobe(pcie_hp_slot_t *slot_p);
extern int pcie_hp_common_ops(dev_info_t *dip, char *cn_name, ddi_hp_op_t op,
    void *arg, void *result);
extern dev_info_t *pcie_hp_devi_find(dev_info_t *dip, uint_t device,
    uint_t function);
extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
    int pci_dev);
extern void pcie_hp_create_occupant_props(dev_info_t *self, dev_t dev,
    int pci_dev);
extern void pcie_hp_delete_occupant_props(dev_info_t *dip, dev_t dev);
extern int pcie_copyin_nvlist(char *packed_buf, size_t packed_sz,
    nvlist_t **nvlp);
extern int pcie_copyout_nvlist(nvlist_t *nvl, char *packed_buf,
    size_t *packed_sz);
extern char *pcie_led_state_text(pcie_hp_led_state_t state);
extern char *pcie_slot_condition_text(ap_condition_t condition);
extern int pcie_create_minor_node(pcie_hp_ctrl_t *, int);
extern void pcie_remove_minor_node(pcie_hp_ctrl_t *, int);
extern void pcie_hp_gen_sysevent_req(char *slot_name, int hint,
    dev_info_t *self, int kmflag);

extern const struct pci_class_strings_s class_pci[];
extern int class_pci_items;

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_PCIE_HP_H */