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