xref: /illumos-gate/usr/src/uts/intel/io/pci/pci_pci.c (revision b5cf5bc277244cdacc06d213322ec98e76ef8d89)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
27  * Copyright 2018 Joyent, Inc.
28  */
29 
30 /*
31  * PCI to PCI bus bridge nexus driver
32  */
33 
34 #include <sys/conf.h>
35 #include <sys/kmem.h>
36 #include <sys/debug.h>
37 #include <sys/modctl.h>
38 #include <sys/autoconf.h>
39 #include <sys/ddi_impldefs.h>
40 #include <sys/pci.h>
41 #include <sys/pci_impl.h>
42 #include <sys/pcie_impl.h>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 #include <sys/sunndi.h>
46 #include <sys/ddifm.h>
47 #include <sys/ndifm.h>
48 #include <sys/fm/protocol.h>
49 #include <sys/hotplug/pci/pcie_hp.h>
50 #include <sys/hotplug/pci/pcihp.h>
51 #include <sys/pci_intr_lib.h>
52 #include <sys/psm.h>
53 #include <sys/pci_cap.h>
54 
55 /*
56  * The variable controls the default setting of the command register
57  * for pci devices.  See ppb_initchild() for details.
58  */
59 static ushort_t ppb_command_default = PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO;
60 
61 
62 static int	ppb_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
63 		    off_t, off_t, caddr_t *);
64 static int	ppb_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
65 		    void *, void *);
66 static int	ppb_fm_init(dev_info_t *, dev_info_t *, int,
67 		    ddi_iblock_cookie_t *);
68 static int	ppb_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
69 static int	ppb_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
70 		    ddi_intr_handle_impl_t *, void *);
71 
72 /*
73  * ppb_support_msi: Flag that controls MSI support across P2P Bridges.
74  * By default, MSI is not supported except for special cases like HT
75  * bridges/tunnels that have HT MSI mapping enabled.
76  *
77  * However, MSI support behavior can be patched on a system by changing
78  * the value of this flag as shown below:-
79  *	 0 = default value, MSI is allowed by this driver for special cases
80  *	 1 = MSI supported without any checks for this driver
81  *	-1 = MSI not supported at all
82  */
83 int ppb_support_msi = 0;
84 
85 /*
86  * Controls the usage of the Hypertransport MSI mapping capability
87  *	0 = default value, leave hardware function as it is
88  *	1 = always enable HT MSI mapping
89  *     -1 = always disable HT MSI mapping
90  */
91 int ppb_support_ht_msimap = 0;
92 
93 struct bus_ops ppb_bus_ops = {
94 	BUSO_REV,
95 	ppb_bus_map,
96 	0,
97 	0,
98 	0,
99 	i_ddi_map_fault,
100 	0,
101 	ddi_dma_allochdl,
102 	ddi_dma_freehdl,
103 	ddi_dma_bindhdl,
104 	ddi_dma_unbindhdl,
105 	ddi_dma_flush,
106 	ddi_dma_win,
107 	ddi_dma_mctl,
108 	ppb_ctlops,
109 	ddi_bus_prop_op,
110 	0,			/* (*bus_get_eventcookie)();	*/
111 	0,			/* (*bus_add_eventcall)();	*/
112 	0,			/* (*bus_remove_eventcall)();	*/
113 	0,			/* (*bus_post_event)();		*/
114 	0,			/* (*bus_intr_ctl)();		*/
115 	0,			/* (*bus_config)();		*/
116 	0,			/* (*bus_unconfig)();		*/
117 	ppb_fm_init,		/* (*bus_fm_init)();		*/
118 	NULL,			/* (*bus_fm_fini)();		*/
119 	NULL,			/* (*bus_fm_access_enter)();	*/
120 	NULL,			/* (*bus_fm_access_exit)();	*/
121 	NULL,			/* (*bus_power)();	*/
122 	ppb_intr_ops,		/* (*bus_intr_op)();		*/
123 	pcie_hp_common_ops	/* (*bus_hp_op)();		*/
124 };
125 
126 /*
127  * The goal here is to leverage off of the pcihp.c source without making
128  * changes to it.  Call into it's cb_ops directly if needed.
129  */
130 static int	ppb_open(dev_t *, int, int, cred_t *);
131 static int	ppb_close(dev_t, int, int, cred_t *);
132 static int	ppb_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
133 static int	ppb_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
134 		    caddr_t, int *);
135 static int	ppb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
136 static void	ppb_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
137 
138 struct cb_ops ppb_cb_ops = {
139 	ppb_open,			/* open */
140 	ppb_close,			/* close */
141 	nodev,				/* strategy */
142 	nodev,				/* print */
143 	nodev,				/* dump */
144 	nodev,				/* read */
145 	nodev,				/* write */
146 	ppb_ioctl,			/* ioctl */
147 	nodev,				/* devmap */
148 	nodev,				/* mmap */
149 	nodev,				/* segmap */
150 	nochpoll,			/* poll */
151 	ppb_prop_op,			/* cb_prop_op */
152 	NULL,				/* streamtab */
153 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
154 	CB_REV,				/* rev */
155 	nodev,				/* int (*cb_aread)() */
156 	nodev				/* int (*cb_awrite)() */
157 };
158 
159 
160 static int ppb_probe(dev_info_t *);
161 static int ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
162 static int ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
163 
164 struct dev_ops ppb_ops = {
165 	DEVO_REV,		/* devo_rev */
166 	0,			/* refcnt  */
167 	ppb_info,		/* info */
168 	nulldev,		/* identify */
169 	ppb_probe,		/* probe */
170 	ppb_attach,		/* attach */
171 	ppb_detach,		/* detach */
172 	nulldev,		/* reset */
173 	&ppb_cb_ops,		/* driver operations */
174 	&ppb_bus_ops,		/* bus operations */
175 	NULL,			/* power */
176 	ddi_quiesce_not_needed,		/* quiesce */
177 };
178 
179 /*
180  * Module linkage information for the kernel.
181  */
182 
183 static struct modldrv modldrv = {
184 	&mod_driverops, /* Type of module */
185 	"Standard PCI to PCI bridge nexus driver",
186 	&ppb_ops,	/* driver ops */
187 };
188 
189 static struct modlinkage modlinkage = {
190 	MODREV_1,
191 	(void *)&modldrv,
192 	NULL
193 };
194 
195 /*
196  * soft state pointer and structure template:
197  */
198 static void *ppb_state;
199 
200 typedef struct {
201 	dev_info_t *dip;
202 	int ppb_fmcap;
203 	ddi_iblock_cookie_t ppb_fm_ibc;
204 	kmutex_t ppb_mutex;
205 	kmutex_t ppb_peek_poke_mutex;
206 	kmutex_t ppb_err_mutex;
207 
208 	/*
209 	 * cpr support:
210 	 */
211 	uint_t config_state_index;
212 	struct {
213 		dev_info_t *dip;
214 		ushort_t command;
215 		uchar_t cache_line_size;
216 		uchar_t latency_timer;
217 		uchar_t header_type;
218 		uchar_t sec_latency_timer;
219 		ushort_t bridge_control;
220 	} config_state[PCI_MAX_CHILDREN];
221 
222 	uint16_t parent_bus;
223 } ppb_devstate_t;
224 
225 
226 /*
227  * forward function declarations:
228  */
229 static void	ppb_removechild(dev_info_t *);
230 static int	ppb_initchild(dev_info_t *child);
231 static void	ppb_save_config_regs(ppb_devstate_t *ppb_p);
232 static void	ppb_restore_config_regs(ppb_devstate_t *ppb_p);
233 static boolean_t	ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl);
234 static int	ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd);
235 
236 /*
237  * for <cmd> in ppb_ht_msimap_set
238  */
239 #define	HT_MSIMAP_ENABLE	1
240 #define	HT_MSIMAP_DISABLE	0
241 
242 
243 int
_init(void)244 _init(void)
245 {
246 	int e;
247 
248 	if ((e = ddi_soft_state_init(&ppb_state, sizeof (ppb_devstate_t),
249 	    1)) == 0 && (e = mod_install(&modlinkage)) != 0)
250 		ddi_soft_state_fini(&ppb_state);
251 	return (e);
252 }
253 
254 int
_fini(void)255 _fini(void)
256 {
257 	int e;
258 
259 	if ((e = mod_remove(&modlinkage)) == 0)
260 		ddi_soft_state_fini(&ppb_state);
261 	return (e);
262 }
263 
264 int
_info(struct modinfo * modinfop)265 _info(struct modinfo *modinfop)
266 {
267 	return (mod_info(&modlinkage, modinfop));
268 }
269 
270 /*ARGSUSED*/
271 static int
ppb_probe(dev_info_t * devi)272 ppb_probe(dev_info_t *devi)
273 {
274 	return (DDI_PROBE_SUCCESS);
275 }
276 
277 /*ARGSUSED*/
278 static int
ppb_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)279 ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
280 {
281 	dev_info_t *root = ddi_root_node();
282 	int instance;
283 	ppb_devstate_t *ppb;
284 	dev_info_t *pdip;
285 	ddi_acc_handle_t config_handle;
286 	char *bus;
287 	int ret;
288 
289 	switch (cmd) {
290 	case DDI_ATTACH:
291 
292 		/*
293 		 * Make sure the "device_type" property exists.
294 		 */
295 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
296 		    "device_type", "pci");
297 
298 		/*
299 		 * Allocate and get soft state structure.
300 		 */
301 		instance = ddi_get_instance(devi);
302 		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
303 			return (DDI_FAILURE);
304 		ppb = ddi_get_soft_state(ppb_state, instance);
305 		ppb->dip = devi;
306 
307 		/*
308 		 * don't enable ereports if immediate child of npe
309 		 */
310 		if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0)
311 			ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE |
312 			    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
313 		else
314 			ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE |
315 			    DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
316 			    DDI_FM_DMACHK_CAPABLE;
317 
318 		ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc);
319 		mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
320 		mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER,
321 		    (void *)ppb->ppb_fm_ibc);
322 		mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER,
323 		    (void *)ppb->ppb_fm_ibc);
324 
325 		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
326 		    DDI_FM_EREPORT_CAPABLE))
327 			pci_ereport_setup(devi);
328 		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
329 			ddi_fm_handler_register(devi, ppb_fm_callback, NULL);
330 
331 		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
332 			if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
333 				ddi_fm_handler_unregister(devi);
334 			if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
335 			    DDI_FM_EREPORT_CAPABLE))
336 				pci_ereport_teardown(devi);
337 			ddi_fm_fini(devi);
338 			ddi_soft_state_free(ppb_state, instance);
339 			return (DDI_FAILURE);
340 		}
341 
342 		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
343 		for (pdip = ddi_get_parent(devi); pdip && (pdip != root) &&
344 		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
345 		    pdip = ddi_get_parent(pdip)) {
346 			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
347 			    DDI_PROP_DONTPASS, "device_type", &bus) !=
348 			    DDI_PROP_SUCCESS)
349 				break;
350 
351 			if (strcmp(bus, "pciex") == 0)
352 				ppb->parent_bus =
353 				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;
354 
355 			ddi_prop_free(bus);
356 		}
357 
358 		if (ppb_support_ht_msimap == 1)
359 			(void) ppb_ht_msimap_set(config_handle,
360 			    HT_MSIMAP_ENABLE);
361 		else if (ppb_support_ht_msimap == -1)
362 			(void) ppb_ht_msimap_set(config_handle,
363 			    HT_MSIMAP_DISABLE);
364 
365 		pci_config_teardown(&config_handle);
366 
367 		/*
368 		 * Initialize hotplug support on this bus.
369 		 */
370 		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
371 			ret = pcie_init(devi, NULL);
372 		else
373 			ret = pcihp_init(devi);
374 
375 		if (ret != DDI_SUCCESS) {
376 			cmn_err(CE_WARN,
377 			    "pci: Failed to setup hotplug framework");
378 			(void) ppb_detach(devi, DDI_DETACH);
379 			return (ret);
380 		}
381 
382 		ddi_report_dev(devi);
383 		return (DDI_SUCCESS);
384 
385 	case DDI_RESUME:
386 
387 		/*
388 		 * Get the soft state structure for the bridge.
389 		 */
390 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
391 		ppb_restore_config_regs(ppb);
392 		return (DDI_SUCCESS);
393 
394 	default:
395 		break;
396 	}
397 	return (DDI_FAILURE);
398 }
399 
400 /*ARGSUSED*/
401 static int
ppb_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)402 ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
403 {
404 	ppb_devstate_t *ppb;
405 	int		ret;
406 
407 	switch (cmd) {
408 	case DDI_DETACH:
409 		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");
410 
411 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
412 		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
413 			ddi_fm_handler_unregister(devi);
414 		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
415 		    DDI_FM_EREPORT_CAPABLE))
416 			pci_ereport_teardown(devi);
417 
418 		/*
419 		 * Uninitialize hotplug support on this bus.
420 		 */
421 		ret = (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ?
422 		    pcie_uninit(devi) : pcihp_uninit(devi);
423 		if (ret != DDI_SUCCESS)
424 			return (DDI_FAILURE);
425 
426 		mutex_destroy(&ppb->ppb_peek_poke_mutex);
427 		mutex_destroy(&ppb->ppb_err_mutex);
428 		mutex_destroy(&ppb->ppb_mutex);
429 		ddi_fm_fini(devi);
430 
431 		/*
432 		 * And finally free the per-pci soft state.
433 		 */
434 		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));
435 
436 		return (DDI_SUCCESS);
437 
438 	case DDI_SUSPEND:
439 		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
440 		ppb_save_config_regs(ppb);
441 		return (DDI_SUCCESS);
442 
443 	default:
444 		break;
445 	}
446 	return (DDI_FAILURE);
447 }
448 
449 /*ARGSUSED*/
450 static int
ppb_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)451 ppb_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
452     off_t offset, off_t len, caddr_t *vaddrp)
453 {
454 	dev_info_t *pdip;
455 	ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
456 	    ddi_get_instance(dip));
457 
458 	if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") == 0 &&
459 	    mp->map_handlep != NULL) {
460 		ddi_acc_impl_t *hdlp =
461 		    (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
462 		hdlp->ahi_err_mutexp = &ppb->ppb_err_mutex;
463 		hdlp->ahi_peekpoke_mutexp = &ppb->ppb_peek_poke_mutex;
464 		hdlp->ahi_scan_dip = dip;
465 		hdlp->ahi_scan = ppb_peekpoke_cb;
466 	}
467 	pdip = (dev_info_t *)DEVI(dip)->devi_parent;
468 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
469 	    rdip, mp, offset, len, vaddrp));
470 }
471 
472 /*ARGSUSED*/
473 static int
ppb_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)474 ppb_ctlops(dev_info_t *dip, dev_info_t *rdip,
475     ddi_ctl_enum_t ctlop, void *arg, void *result)
476 {
477 	pci_regspec_t *drv_regp;
478 	int	reglen;
479 	int	rn;
480 	int	totreg;
481 	ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
482 	    ddi_get_instance(dip));
483 	struct detachspec *dsp;
484 	struct attachspec *asp;
485 
486 	switch (ctlop) {
487 	case DDI_CTLOPS_REPORTDEV:
488 		if (rdip == (dev_info_t *)0)
489 			return (DDI_FAILURE);
490 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
491 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
492 		    ddi_driver_name(rdip),
493 		    ddi_get_instance(rdip));
494 		return (DDI_SUCCESS);
495 
496 	case DDI_CTLOPS_INITCHILD:
497 		return (ppb_initchild((dev_info_t *)arg));
498 
499 	case DDI_CTLOPS_UNINITCHILD:
500 		ppb_removechild((dev_info_t *)arg);
501 		return (DDI_SUCCESS);
502 
503 	case DDI_CTLOPS_SIDDEV:
504 		return (DDI_SUCCESS);
505 
506 	case DDI_CTLOPS_REGSIZE:
507 	case DDI_CTLOPS_NREGS:
508 		if (rdip == (dev_info_t *)0)
509 			return (DDI_FAILURE);
510 		break;
511 
512 	/* X86 systems support PME wakeup from suspend */
513 	case DDI_CTLOPS_ATTACH:
514 		if (!pcie_is_child(dip, rdip))
515 			return (DDI_SUCCESS);
516 
517 		asp = (struct attachspec *)arg;
518 		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
519 		    (asp->when == DDI_POST) && (asp->result == DDI_SUCCESS))
520 			pf_init(rdip, (void *)ppb->ppb_fm_ibc, asp->cmd);
521 
522 		if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
523 			if (pci_pre_resume(rdip) != DDI_SUCCESS)
524 				return (DDI_FAILURE);
525 
526 		return (DDI_SUCCESS);
527 
528 	case DDI_CTLOPS_DETACH:
529 		if (!pcie_is_child(dip, rdip))
530 			return (DDI_SUCCESS);
531 
532 		dsp = (struct detachspec *)arg;
533 		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
534 		    (dsp->when == DDI_PRE))
535 			pf_fini(rdip, dsp->cmd);
536 
537 		if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
538 			if (pci_post_suspend(rdip) != DDI_SUCCESS)
539 				return (DDI_FAILURE);
540 
541 		return (DDI_SUCCESS);
542 
543 	case DDI_CTLOPS_PEEK:
544 	case DDI_CTLOPS_POKE:
545 		if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") != 0)
546 			return (ddi_ctlops(dip, rdip, ctlop, arg, result));
547 		return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
548 		    ddi_ctlops, &ppb->ppb_err_mutex,
549 		    &ppb->ppb_peek_poke_mutex, ppb_peekpoke_cb));
550 
551 	default:
552 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
553 	}
554 
555 	*(int *)result = 0;
556 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
557 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
558 	    (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
559 		return (DDI_FAILURE);
560 
561 	totreg = reglen / sizeof (pci_regspec_t);
562 	if (ctlop == DDI_CTLOPS_NREGS)
563 		*(int *)result = totreg;
564 	else if (ctlop == DDI_CTLOPS_REGSIZE) {
565 		uint64_t rs;
566 
567 		rn = *(int *)arg;
568 		if (rn >= totreg) {
569 			kmem_free(drv_regp, reglen);
570 			return (DDI_FAILURE);
571 		}
572 
573 		rs = drv_regp[rn].pci_size_low |
574 		    ((uint64_t)drv_regp[rn].pci_size_hi << 32);
575 		if (rs > OFF_MAX) {
576 			kmem_free(drv_regp, reglen);
577 			return (DDI_FAILURE);
578 		}
579 		*(off_t *)result = rs;
580 	}
581 
582 	kmem_free(drv_regp, reglen);
583 	return (DDI_SUCCESS);
584 }
585 
586 static int
ppb_name_child(dev_info_t * child,char * name,int namelen)587 ppb_name_child(dev_info_t *child, char *name, int namelen)
588 {
589 	pci_regspec_t *pci_rp;
590 	uint_t slot, func;
591 	char **unit_addr;
592 	uint_t n;
593 
594 	/*
595 	 * For .conf nodes, use unit-address property as name
596 	 */
597 	if (ndi_dev_is_persistent_node(child) == 0) {
598 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
599 		    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
600 		    DDI_PROP_SUCCESS) {
601 			cmn_err(CE_WARN,
602 			    "cannot find unit-address in %s.conf",
603 			    ddi_driver_name(child));
604 			return (DDI_FAILURE);
605 		}
606 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
607 			cmn_err(CE_WARN, "unit-address property in %s.conf"
608 			    " not well-formed", ddi_driver_name(child));
609 			ddi_prop_free(unit_addr);
610 			return (DDI_SUCCESS);
611 		}
612 		(void) snprintf(name, namelen, "%s", *unit_addr);
613 		ddi_prop_free(unit_addr);
614 		return (DDI_SUCCESS);
615 	}
616 
617 	/* get child "reg" property */
618 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
619 	    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
620 		return (DDI_FAILURE);
621 	}
622 
623 	/* copy the device identifications */
624 	slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
625 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
626 
627 	if (func != 0)
628 		(void) snprintf(name, namelen, "%x,%x", slot, func);
629 	else
630 		(void) snprintf(name, namelen, "%x", slot);
631 
632 	ddi_prop_free(pci_rp);
633 	return (DDI_SUCCESS);
634 }
635 
636 static int
ppb_initchild(dev_info_t * child)637 ppb_initchild(dev_info_t *child)
638 {
639 	struct ddi_parent_private_data *pdptr;
640 	ppb_devstate_t *ppb;
641 	char name[MAXNAMELEN];
642 	ddi_acc_handle_t config_handle;
643 	ushort_t command_preserve, command;
644 
645 	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
646 	    ddi_get_instance(ddi_get_parent(child)));
647 
648 	if (ppb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
649 		return (DDI_FAILURE);
650 	ddi_set_name_addr(child, name);
651 
652 	/*
653 	 * Pseudo nodes indicate a prototype node with per-instance
654 	 * properties to be merged into the real h/w device node.
655 	 * The interpretation of the unit-address is DD[,F]
656 	 * where DD is the device id and F is the function.
657 	 */
658 	if (ndi_dev_is_persistent_node(child) == 0) {
659 		extern int pci_allow_pseudo_children;
660 
661 		ddi_set_parent_data(child, NULL);
662 
663 		/*
664 		 * Try to merge the properties from this prototype
665 		 * node into real h/w nodes.
666 		 */
667 		if (ndi_merge_node(child, ppb_name_child) == DDI_SUCCESS) {
668 			/*
669 			 * Merged ok - return failure to remove the node.
670 			 */
671 			ddi_set_name_addr(child, NULL);
672 			return (DDI_FAILURE);
673 		}
674 
675 		/* workaround for ddivs to run under PCI */
676 		if (pci_allow_pseudo_children)
677 			return (DDI_SUCCESS);
678 
679 		/*
680 		 * The child was not merged into a h/w node,
681 		 * but there's not much we can do with it other
682 		 * than return failure to cause the node to be removed.
683 		 */
684 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
685 		    ddi_driver_name(child), ddi_get_name_addr(child),
686 		    ddi_driver_name(child));
687 		ddi_set_name_addr(child, NULL);
688 		return (DDI_NOT_WELL_FORMED);
689 	}
690 
691 	ddi_set_parent_data(child, NULL);
692 
693 	/*
694 	 * PCIe FMA specific
695 	 *
696 	 * Note: parent_data for parent is created only if this is PCI-E
697 	 * platform, for which, SG take a different route to handle device
698 	 * errors.
699 	 */
700 	if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
701 		if (pcie_init_cfghdl(child) != DDI_SUCCESS)
702 			return (DDI_FAILURE);
703 		pcie_init_dom(child);
704 	}
705 
706 	/* transfer select properties from PROM to kernel */
707 	if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
708 	    "interrupts", -1) != -1) {
709 		pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) +
710 		    sizeof (struct intrspec)), KM_SLEEP);
711 		pdptr->par_intr = (struct intrspec *)(pdptr + 1);
712 		pdptr->par_nintr = 1;
713 		ddi_set_parent_data(child, pdptr);
714 	} else
715 		ddi_set_parent_data(child, NULL);
716 
717 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
718 		pcie_fini_dom(child);
719 		return (DDI_FAILURE);
720 	}
721 
722 	/*
723 	 * Support for the "command-preserve" property.
724 	 */
725 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
726 	    DDI_PROP_DONTPASS, "command-preserve", 0);
727 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
728 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
729 	command |= (ppb_command_default & ~command_preserve);
730 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
731 
732 	pci_config_teardown(&config_handle);
733 	return (DDI_SUCCESS);
734 }
735 
736 static void
ppb_removechild(dev_info_t * dip)737 ppb_removechild(dev_info_t *dip)
738 {
739 	struct ddi_parent_private_data *pdptr;
740 	ppb_devstate_t *ppb;
741 
742 	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
743 	    ddi_get_instance(ddi_get_parent(dip)));
744 
745 	if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
746 		pcie_fini_dom(dip);
747 		pcie_fini_cfghdl(dip);
748 	} else if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
749 		kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
750 		ddi_set_parent_data(dip, NULL);
751 	}
752 	ddi_set_name_addr(dip, NULL);
753 
754 	/*
755 	 * Strip the node to properly convert it back to prototype form
756 	 */
757 	ddi_remove_minor_node(dip, NULL);
758 
759 	impl_rem_dev_props(dip);
760 }
761 
762 /*
763  * ppb_save_config_regs
764  *
765  * This routine saves the state of the configuration registers of all
766  * the child nodes of each PBM.
767  *
768  * used by: ppb_detach() on suspends
769  *
770  * return value: none
771  */
772 static void
ppb_save_config_regs(ppb_devstate_t * ppb_p)773 ppb_save_config_regs(ppb_devstate_t *ppb_p)
774 {
775 	int i;
776 	dev_info_t *dip;
777 	ddi_acc_handle_t config_handle;
778 
779 	for (i = 0, dip = ddi_get_child(ppb_p->dip); dip != NULL;
780 	    i++, dip = ddi_get_next_sibling(dip)) {
781 
782 		if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
783 			cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
784 			    ddi_driver_name(ppb_p->dip),
785 			    ddi_get_instance(ppb_p->dip),
786 			    ddi_driver_name(dip),
787 			    ddi_get_instance(dip));
788 			continue;
789 		}
790 
791 		ppb_p->config_state[i].dip = dip;
792 		ppb_p->config_state[i].command =
793 		    pci_config_get16(config_handle, PCI_CONF_COMM);
794 		pci_config_teardown(&config_handle);
795 	}
796 	ppb_p->config_state_index = i;
797 }
798 
799 
800 /*
801  * ppb_restore_config_regs
802  *
803  * This routine restores the state of the configuration registers of all
804  * the child nodes of each PBM.
805  *
806  * used by: ppb_attach() on resume
807  *
808  * return value: none
809  */
810 static void
ppb_restore_config_regs(ppb_devstate_t * ppb_p)811 ppb_restore_config_regs(ppb_devstate_t *ppb_p)
812 {
813 	int i;
814 	dev_info_t *dip;
815 	ddi_acc_handle_t config_handle;
816 
817 	for (i = 0; i < ppb_p->config_state_index; i++) {
818 		dip = ppb_p->config_state[i].dip;
819 		if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
820 			cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
821 			    ddi_driver_name(ppb_p->dip),
822 			    ddi_get_instance(ppb_p->dip),
823 			    ddi_driver_name(dip),
824 			    ddi_get_instance(dip));
825 			continue;
826 		}
827 		pci_config_put16(config_handle, PCI_CONF_COMM,
828 		    ppb_p->config_state[i].command);
829 		pci_config_teardown(&config_handle);
830 	}
831 }
832 
833 
834 static boolean_t
ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl)835 ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl)
836 {
837 	uint16_t ptr;
838 
839 	if (pci_htcap_locate(cfg_hdl,
840 	    PCI_HTCAP_TYPE_MASK | PCI_HTCAP_MSIMAP_ENABLE_MASK,
841 	    PCI_HTCAP_MSIMAP_TYPE | PCI_HTCAP_MSIMAP_ENABLE, &ptr) !=
842 	    DDI_SUCCESS)
843 		return (B_FALSE);
844 
845 	return (B_TRUE);
846 }
847 
848 
849 static int
ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl,int cmd)850 ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd)
851 {
852 	uint16_t ptr;
853 	uint16_t reg;
854 
855 	if (pci_htcap_locate(cfg_hdl, PCI_HTCAP_TYPE_MASK,
856 	    PCI_HTCAP_MSIMAP_TYPE, &ptr) != DDI_SUCCESS)
857 		return (0);
858 
859 	reg = pci_config_get16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF);
860 	switch (cmd) {
861 	case HT_MSIMAP_ENABLE:
862 		reg |= PCI_HTCAP_MSIMAP_ENABLE;
863 		break;
864 	case HT_MSIMAP_DISABLE:
865 	default:
866 		reg &= ~(uint16_t)PCI_HTCAP_MSIMAP_ENABLE;
867 	}
868 
869 	pci_config_put16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF, reg);
870 	return (1);
871 }
872 
873 
874 /*
875  * intercept certain interrupt services to handle special cases
876  */
877 static int
ppb_intr_ops(dev_info_t * pdip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)878 ppb_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
879     ddi_intr_handle_impl_t *hdlp, void *result)
880 {
881 	ddi_acc_handle_t cfg_hdl;
882 	int rv = DDI_SUCCESS;
883 
884 	if (intr_op != DDI_INTROP_SUPPORTED_TYPES)
885 		return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
886 
887 	DDI_INTR_NEXDBG((CE_CONT,
888 	    "ppb_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
889 	    (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
890 
891 	/* Fixed interrupt is supported by default */
892 	*(int *)result = DDI_INTR_TYPE_FIXED;
893 
894 	if (ppb_support_msi == -1) {
895 		DDI_INTR_NEXDBG((CE_CONT,
896 		    "ppb_intr_ops: MSI is not allowed\n"));
897 		goto OUT;
898 	}
899 
900 	if (ppb_support_msi == 1) {
901 		DDI_INTR_NEXDBG((CE_CONT,
902 		    "ppb_intr_ops: MSI is always allowed\n"));
903 		rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
904 		goto OUT;
905 	}
906 
907 	if (pci_config_setup(pdip, &cfg_hdl) != DDI_SUCCESS) {
908 		DDI_INTR_NEXDBG((CE_CONT,
909 		    "ppb_intr_ops: pci_config_setup() failed\n"));
910 		goto OUT;
911 	}
912 
913 	/*
914 	 * check for hypertransport msi mapping capability
915 	 */
916 	if (ppb_ht_msimap_check(cfg_hdl)) {
917 		DDI_INTR_NEXDBG((CE_CONT,
918 		    "ppb_intr_ops: HT MSI mapping enabled\n"));
919 		rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
920 	}
921 
922 	/*
923 	 * if we add failure conditions after pci_config_setup, move this to
924 	 * OUT and use an extra flag to indicate the need to teardown cfg_hdl
925 	 */
926 	pci_config_teardown(&cfg_hdl);
927 
928 OUT:
929 	DDI_INTR_NEXDBG((CE_CONT,
930 	    "ppb_intr_ops: rdip 0x%p, returns supported types: 0x%x\n",
931 	    (void *)rdip, *(int *)result));
932 	return (rv);
933 }
934 
935 /* ARGSUSED */
936 static int
ppb_open(dev_t * devp,int flags,int otyp,cred_t * credp)937 ppb_open(dev_t *devp, int flags, int otyp, cred_t *credp)
938 {
939 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(*devp));
940 	ppb_devstate_t	*ppb_p = ddi_get_soft_state(ppb_state, instance);
941 	int	rv;
942 
943 	if (ppb_p == NULL)
944 		return (ENXIO);
945 
946 	/*
947 	 * Ioctls will be handled by PCI Express framework for all
948 	 * PCIe platforms
949 	 */
950 	if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
951 		mutex_enter(&ppb_p->ppb_mutex);
952 		rv = pcie_open(ppb_p->dip, devp, flags, otyp, credp);
953 		mutex_exit(&ppb_p->ppb_mutex);
954 		return (rv);
955 	}
956 
957 	return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
958 }
959 
960 /* ARGSUSED */
961 static int
ppb_close(dev_t dev,int flags,int otyp,cred_t * credp)962 ppb_close(dev_t dev, int flags, int otyp, cred_t *credp)
963 {
964 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
965 	ppb_devstate_t	*ppb_p = ddi_get_soft_state(ppb_state, instance);
966 	int	rv;
967 
968 	if (ppb_p == NULL)
969 		return (ENXIO);
970 
971 	mutex_enter(&ppb_p->ppb_mutex);
972 	/*
973 	 * Ioctls will be handled by PCI Express framework for all
974 	 * PCIe platforms
975 	 */
976 	if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
977 		rv = pcie_close(ppb_p->dip, dev, flags, otyp, credp);
978 		mutex_exit(&ppb_p->ppb_mutex);
979 		return (rv);
980 	}
981 
982 	mutex_exit(&ppb_p->ppb_mutex);
983 	return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
984 }
985 
986 /*
987  * ppb_ioctl: devctl hotplug controls
988  */
989 /* ARGSUSED */
990 static int
ppb_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)991 ppb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
992     int *rvalp)
993 {
994 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
995 	ppb_devstate_t	*ppb_p = ddi_get_soft_state(ppb_state, instance);
996 
997 	if (ppb_p == NULL)
998 		return (ENXIO);
999 
1000 	/*
1001 	 * Ioctls will be handled by PCI Express framework for all
1002 	 * PCIe platforms
1003 	 */
1004 	if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
1005 		return (pcie_ioctl(ppb_p->dip, dev, cmd, arg, mode, credp,
1006 		    rvalp));
1007 
1008 	return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode, credp,
1009 	    rvalp));
1010 }
1011 
1012 static int
ppb_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int flags,char * name,caddr_t valuep,int * lengthp)1013 ppb_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags,
1014     char *name, caddr_t valuep, int *lengthp)
1015 {
1016 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
1017 	ppb_devstate_t	*ppb_p = ddi_get_soft_state(ppb_state, instance);
1018 
1019 	if (ppb_p == NULL)
1020 		return (ENXIO);
1021 
1022 	if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
1023 		return (pcie_prop_op(dev, dip, prop_op, flags, name,
1024 		    valuep, lengthp));
1025 
1026 	return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
1027 	    name, valuep, lengthp));
1028 }
1029 
1030 static int
ppb_info(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)1031 ppb_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1032 {
1033 	minor_t		minor = getminor((dev_t)arg);
1034 	int		instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
1035 	ppb_devstate_t	*ppb_p = ddi_get_soft_state(ppb_state, instance);
1036 
1037 	if (ppb_p == NULL)
1038 		return (DDI_FAILURE);
1039 
1040 	if (ppb_p->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
1041 		return (pcihp_info(dip, cmd, arg, result));
1042 
1043 	switch (cmd) {
1044 	default:
1045 		return (DDI_FAILURE);
1046 
1047 	case DDI_INFO_DEVT2INSTANCE:
1048 		*result = (void *)(uintptr_t)instance;
1049 		return (DDI_SUCCESS);
1050 
1051 	case DDI_INFO_DEVT2DEVINFO:
1052 		if (ppb_p == NULL)
1053 			return (DDI_FAILURE);
1054 		*result = (void *)ppb_p->dip;
1055 		return (DDI_SUCCESS);
1056 	}
1057 }
1058 
ppb_peekpoke_cb(dev_info_t * dip,ddi_fm_error_t * derr)1059 void ppb_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
1060 	(void) pci_ereport_post(dip, derr, NULL);
1061 }
1062 
1063 /*ARGSUSED*/
1064 static int
ppb_fm_init(dev_info_t * dip,dev_info_t * tdip,int cap,ddi_iblock_cookie_t * ibc)1065 ppb_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
1066     ddi_iblock_cookie_t *ibc)
1067 {
1068 	ppb_devstate_t  *ppb = ddi_get_soft_state(ppb_state,
1069 	    ddi_get_instance(dip));
1070 
1071 	ASSERT(ibc != NULL);
1072 	*ibc = ppb->ppb_fm_ibc;
1073 
1074 	return (ppb->ppb_fmcap);
1075 }
1076 
1077 /*ARGSUSED*/
1078 static int
ppb_fm_callback(dev_info_t * dip,ddi_fm_error_t * derr,const void * no_used)1079 ppb_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
1080 {
1081 	ppb_devstate_t  *ppb = ddi_get_soft_state(ppb_state,
1082 	    ddi_get_instance(dip));
1083 
1084 	mutex_enter(&ppb->ppb_err_mutex);
1085 	pci_ereport_post(dip, derr, NULL);
1086 	mutex_exit(&ppb->ppb_err_mutex);
1087 	return (derr->fme_status);
1088 }
1089