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