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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * OPL CMU-CH PCI nexus driver.
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <sys/systm.h>
35 #include <sys/intreg.h>
37 #include <sys/machsystm.h>
41 #include <sys/async.h>
42 #include <sys/ivintr.h>
43 #include <sys/sunddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/ndifm.h>
46 #include <sys/ontrap.h>
47 #include <sys/ddi_impldefs.h>
48 #include <sys/ddi_subrdefs.h>
51 #include <sys/fm/util.h>
52 #include <sys/fm/util.h>
53 #include <sys/fm/protocol.h>
54 #include <sys/fm/io/pci.h>
55 #include <sys/fm/io/sun4upci.h>
56 #include <sys/pcicmu/pcicmu.h>
58 #include <sys/cmn_err.h>
61 #include <sys/modctl.h>
63 #include <sys/errno.h>
67 uint32_t pcmu_spurintr_duration
= 60000000; /* One minute */
70 * The variable controls the default setting of the command register
71 * for pci devices. See pcmu_init_child() for details.
73 * This flags also controls the setting of bits in the bridge control
74 * register pci to pci bridges. See pcmu_init_child() for details.
76 ushort_t pcmu_command_default
= PCI_COMM_SERR_ENABLE
|
77 PCI_COMM_WAIT_CYC_ENAB
|
78 PCI_COMM_PARITY_DETECT
|
83 * The following driver parameters are defined as variables to allow
84 * patching for debugging and tuning. Flags that can be set on a per
85 * PBM basis are bit fields where the PBM device instance number maps
86 * to the bit position.
89 uint64_t pcmu_debug_flags
= 0;
91 uint_t ecc_error_intr_enable
= 1;
93 uint_t pcmu_ecc_afsr_retries
= 100; /* XXX - what's a good value? */
95 uint_t pcmu_intr_retry_intv
= 5; /* for interrupt retry reg */
96 uint_t pcmu_panic_on_fatal_errors
= 1; /* should be 1 at beta */
98 hrtime_t pcmu_intrpend_timeout
= 5ll * NANOSEC
; /* 5 seconds in nanoseconds */
100 uint64_t pcmu_errtrig_pa
= 0x0;
104 * The following value is the number of consecutive unclaimed interrupts that
105 * will be tolerated for a particular ino_p before the interrupt is deemed to
106 * be jabbering and is blocked.
108 uint_t pcmu_unclaimed_intr_max
= 20;
111 * function prototypes for dev ops routines:
113 static int pcmu_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
114 static int pcmu_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
115 static int pcmu_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
116 void *arg
, void **result
);
117 static int pcmu_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
);
118 static int pcmu_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
);
119 static int pcmu_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
,
120 cred_t
*credp
, int *rvalp
);
121 static int pcmu_prop_op(dev_t dev
, dev_info_t
*dip
, ddi_prop_op_t prop_op
,
122 int flags
, char *name
, caddr_t valuep
, int *lengthp
);
123 static int pcmu_ctlops_poke(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
);
124 static int pcmu_ctlops_peek(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
,
127 static int map_pcmu_registers(pcmu_t
*, dev_info_t
*);
128 static void unmap_pcmu_registers(pcmu_t
*);
129 static void pcmu_pbm_clear_error(pcmu_pbm_t
*);
131 static int pcmu_ctlops(dev_info_t
*, dev_info_t
*, ddi_ctl_enum_t
,
133 static int pcmu_map(dev_info_t
*, dev_info_t
*, ddi_map_req_t
*,
134 off_t
, off_t
, caddr_t
*);
135 static int pcmu_intr_ops(dev_info_t
*, dev_info_t
*, ddi_intr_op_t
,
136 ddi_intr_handle_impl_t
*, void *);
138 static uint32_t pcmu_identity_init(pcmu_t
*pcmu_p
);
139 static int pcmu_intr_setup(pcmu_t
*pcmu_p
);
140 static void pcmu_pbm_errstate_get(pcmu_t
*pcmu_p
,
141 pcmu_pbm_errstate_t
*pbm_err_p
);
142 static int pcmu_obj_setup(pcmu_t
*pcmu_p
);
143 static void pcmu_obj_destroy(pcmu_t
*pcmu_p
);
144 static void pcmu_obj_resume(pcmu_t
*pcmu_p
);
145 static void pcmu_obj_suspend(pcmu_t
*pcmu_p
);
147 static void u2u_ittrans_init(pcmu_t
*, u2u_ittrans_data_t
**);
148 static void u2u_ittrans_resume(u2u_ittrans_data_t
**);
149 static void u2u_ittrans_uninit(u2u_ittrans_data_t
*);
151 static pcmu_ksinfo_t
*pcmu_name_kstat
;
154 * bus ops and dev ops structures:
156 static struct bus_ops pcmu_bus_ops
= {
173 ndi_busop_get_eventcookie
, /* (*bus_get_eventcookie)(); */
174 ndi_busop_add_eventcall
, /* (*bus_add_eventcall)(); */
175 ndi_busop_remove_eventcall
, /* (*bus_remove_eventcall)(); */
176 ndi_post_event
, /* (*bus_post_event)(); */
177 NULL
, /* (*bus_intr_ctl)(); */
178 NULL
, /* (*bus_config)(); */
179 NULL
, /* (*bus_unconfig)(); */
180 NULL
, /* (*bus_fm_init)(); */
181 NULL
, /* (*bus_fm_fini)(); */
182 NULL
, /* (*bus_fm_access_enter)(); */
183 NULL
, /* (*bus_fm_access_fini)(); */
184 NULL
, /* (*bus_power)(); */
185 pcmu_intr_ops
/* (*bus_intr_op)(); */
188 struct cb_ops pcmu_cb_ops
= {
189 pcmu_open
, /* open */
190 pcmu_close
, /* close */
191 nodev
, /* strategy */
196 pcmu_ioctl
, /* ioctl */
201 pcmu_prop_op
, /* cb_prop_op */
202 NULL
, /* streamtab */
203 D_NEW
| D_MP
| D_HOTPLUG
, /* Driver compatibility flag */
205 nodev
, /* int (*cb_aread)() */
206 nodev
/* int (*cb_awrite)() */
209 static struct dev_ops pcmu_ops
= {
221 ddi_quiesce_not_needed
, /* quiesce */
226 * module definitions:
228 extern struct mod_ops mod_driverops
;
230 static struct modldrv modldrv
= {
231 &mod_driverops
, /* Type of module - driver */
232 "OPL CMU-CH PCI Nexus driver", /* Name of module. */
233 &pcmu_ops
, /* driver ops */
236 static struct modlinkage modlinkage
= {
237 MODREV_1
, (void *)&modldrv
, NULL
241 * driver global data:
243 void *per_pcmu_state
; /* per-pbm soft state pointer */
244 kmutex_t pcmu_global_mutex
; /* attach/detach common struct lock */
245 errorq_t
*pcmu_ecc_queue
= NULL
; /* per-system ecc handling queue */
247 extern void pcmu_child_cfg_save(dev_info_t
*dip
);
248 extern void pcmu_child_cfg_restore(dev_info_t
*dip
);
256 * Initialize per-pci bus soft state pointer.
258 e
= ddi_soft_state_init(&per_pcmu_state
, sizeof (pcmu_t
), 1);
263 * Initialize global mutexes.
265 mutex_init(&pcmu_global_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
268 * Create the performance kstats.
273 * Install the module.
275 e
= mod_install(&modlinkage
);
277 ddi_soft_state_fini(&per_pcmu_state
);
278 mutex_destroy(&pcmu_global_mutex
);
291 e
= mod_remove(&modlinkage
);
297 * Destroy pcmu_ecc_queue, and set it to NULL.
299 if (pcmu_ecc_queue
) {
300 errorq_destroy(pcmu_ecc_queue
);
301 pcmu_ecc_queue
= NULL
;
305 * Destroy the performance kstats.
310 * Free the per-pci and per-CMU-CH soft state info and destroy
311 * mutex for per-CMU-CH soft state.
313 ddi_soft_state_fini(&per_pcmu_state
);
314 mutex_destroy(&pcmu_global_mutex
);
319 _info(struct modinfo
*modinfop
)
321 return (mod_info(&modlinkage
, modinfop
));
326 pcmu_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
328 int instance
= getminor((dev_t
)arg
) >> 8;
329 pcmu_t
*pcmu_p
= get_pcmu_soft_state(instance
);
332 case DDI_INFO_DEVT2INSTANCE
:
333 *result
= (void *)(uintptr_t)instance
;
334 return (DDI_SUCCESS
);
336 case DDI_INFO_DEVT2DEVINFO
:
338 return (DDI_FAILURE
);
339 *result
= (void *)pcmu_p
->pcmu_dip
;
340 return (DDI_SUCCESS
);
343 return (DDI_FAILURE
);
348 /* device driver entry points */
350 * attach entry point:
353 pcmu_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
356 int instance
= ddi_get_instance(dip
);
360 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
, "DDI_ATTACH\n");
363 * Allocate and get the per-pci soft state structure.
365 if (alloc_pcmu_soft_state(instance
) != DDI_SUCCESS
) {
366 cmn_err(CE_WARN
, "%s%d: can't allocate pci state",
367 ddi_driver_name(dip
), instance
);
368 goto err_bad_pcmu_softstate
;
370 pcmu_p
= get_pcmu_soft_state(instance
);
371 pcmu_p
->pcmu_dip
= dip
;
372 mutex_init(&pcmu_p
->pcmu_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
373 pcmu_p
->pcmu_soft_state
= PCMU_SOFT_STATE_CLOSED
;
374 pcmu_p
->pcmu_open_count
= 0;
377 * Get key properties of the pci bridge node.
379 if (get_pcmu_properties(pcmu_p
, dip
) == DDI_FAILURE
) {
380 goto err_bad_pcmu_prop
;
384 * Map in the registers.
386 if (map_pcmu_registers(pcmu_p
, dip
) == DDI_FAILURE
) {
387 goto err_bad_reg_prop
;
389 if (pcmu_obj_setup(pcmu_p
) != DDI_SUCCESS
) {
393 if (ddi_create_minor_node(dip
, "devctl", S_IFCHR
,
394 (uint_t
)instance
<<8 | 0xff,
395 DDI_NT_NEXUS
, 0) != DDI_SUCCESS
) {
396 goto err_bad_devctl_node
;
400 * Due to unresolved hardware issues, disable PCIPM until
401 * the problem is fully understood.
403 * pcmu_pwr_setup(pcmu_p, dip);
408 pcmu_p
->pcmu_state
= PCMU_ATTACHED
;
409 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
, "attach success\n");
413 ddi_remove_minor_node(dip
, "devctl");
415 unmap_pcmu_registers(pcmu_p
);
417 free_pcmu_properties(pcmu_p
);
419 mutex_destroy(&pcmu_p
->pcmu_mutex
);
420 free_pcmu_soft_state(instance
);
421 err_bad_pcmu_softstate
:
422 return (DDI_FAILURE
);
425 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
, "DDI_RESUME\n");
428 * Make sure the CMU-CH control registers
429 * are configured properly.
431 pcmu_p
= get_pcmu_soft_state(instance
);
432 mutex_enter(&pcmu_p
->pcmu_mutex
);
435 * Make sure this instance has been suspended.
437 if (pcmu_p
->pcmu_state
!= PCMU_SUSPENDED
) {
438 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
,
439 "instance NOT suspended\n");
440 mutex_exit(&pcmu_p
->pcmu_mutex
);
441 return (DDI_FAILURE
);
443 pcmu_obj_resume(pcmu_p
);
444 pcmu_p
->pcmu_state
= PCMU_ATTACHED
;
446 pcmu_child_cfg_restore(dip
);
448 mutex_exit(&pcmu_p
->pcmu_mutex
);
452 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
, "unsupported attach op\n");
453 return (DDI_FAILURE
);
456 return (DDI_SUCCESS
);
460 * detach entry point:
463 pcmu_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
465 int instance
= ddi_get_instance(dip
);
466 pcmu_t
*pcmu_p
= get_pcmu_soft_state(instance
);
470 * Make sure we are currently attached
472 if (pcmu_p
->pcmu_state
!= PCMU_ATTACHED
) {
473 PCMU_DBG0(PCMU_DBG_ATTACH
, dip
,
474 "failed - instance not attached\n");
475 return (DDI_FAILURE
);
478 mutex_enter(&pcmu_p
->pcmu_mutex
);
482 PCMU_DBG0(PCMU_DBG_DETACH
, dip
, "DDI_DETACH\n");
483 pcmu_obj_destroy(pcmu_p
);
486 * Free the pci soft state structure and the rest of the
487 * resources it's using.
489 free_pcmu_properties(pcmu_p
);
490 unmap_pcmu_registers(pcmu_p
);
491 mutex_exit(&pcmu_p
->pcmu_mutex
);
492 mutex_destroy(&pcmu_p
->pcmu_mutex
);
493 free_pcmu_soft_state(instance
);
495 /* Free the interrupt-priorities prop if we created it. */
496 if (ddi_getproplen(DDI_DEV_T_ANY
, dip
,
497 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
,
498 "interrupt-priorities", &len
) == DDI_PROP_SUCCESS
) {
499 (void) ddi_prop_remove(DDI_DEV_T_NONE
, dip
,
500 "interrupt-priorities");
502 return (DDI_SUCCESS
);
505 pcmu_child_cfg_save(dip
);
506 pcmu_obj_suspend(pcmu_p
);
507 pcmu_p
->pcmu_state
= PCMU_SUSPENDED
;
509 mutex_exit(&pcmu_p
->pcmu_mutex
);
510 return (DDI_SUCCESS
);
513 PCMU_DBG0(PCMU_DBG_DETACH
, dip
, "unsupported detach op\n");
514 mutex_exit(&pcmu_p
->pcmu_mutex
);
515 return (DDI_FAILURE
);
521 pcmu_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
525 if (otyp
!= OTYP_CHR
) {
530 * Get the soft state structure for the device.
532 pcmu_p
= DEV_TO_SOFTSTATE(*devp
);
533 if (pcmu_p
== NULL
) {
538 * Handle the open by tracking the device state.
540 PCMU_DBG2(PCMU_DBG_OPEN
, pcmu_p
->pcmu_dip
,
541 "devp=%x: flags=%x\n", devp
, flags
);
542 mutex_enter(&pcmu_p
->pcmu_mutex
);
544 if (pcmu_p
->pcmu_soft_state
!= PCMU_SOFT_STATE_CLOSED
) {
545 mutex_exit(&pcmu_p
->pcmu_mutex
);
546 PCMU_DBG0(PCMU_DBG_OPEN
, pcmu_p
->pcmu_dip
, "busy\n");
549 pcmu_p
->pcmu_soft_state
= PCMU_SOFT_STATE_OPEN_EXCL
;
551 if (pcmu_p
->pcmu_soft_state
== PCMU_SOFT_STATE_OPEN_EXCL
) {
552 mutex_exit(&pcmu_p
->pcmu_mutex
);
553 PCMU_DBG0(PCMU_DBG_OPEN
, pcmu_p
->pcmu_dip
, "busy\n");
556 pcmu_p
->pcmu_soft_state
= PCMU_SOFT_STATE_OPEN
;
558 pcmu_p
->pcmu_open_count
++;
559 mutex_exit(&pcmu_p
->pcmu_mutex
);
566 pcmu_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
)
570 if (otyp
!= OTYP_CHR
) {
574 pcmu_p
= DEV_TO_SOFTSTATE(dev
);
575 if (pcmu_p
== NULL
) {
579 PCMU_DBG2(PCMU_DBG_CLOSE
, pcmu_p
->pcmu_dip
,
580 "dev=%x: flags=%x\n", dev
, flags
);
581 mutex_enter(&pcmu_p
->pcmu_mutex
);
582 pcmu_p
->pcmu_soft_state
= PCMU_SOFT_STATE_CLOSED
;
583 pcmu_p
->pcmu_open_count
= 0;
584 mutex_exit(&pcmu_p
->pcmu_mutex
);
590 pcmu_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
,
591 cred_t
*credp
, int *rvalp
)
595 struct devctl_iocdata
*dcp
;
599 pcmu_p
= DEV_TO_SOFTSTATE(dev
);
600 if (pcmu_p
== NULL
) {
604 dip
= pcmu_p
->pcmu_dip
;
605 PCMU_DBG2(PCMU_DBG_IOCTL
, dip
, "dev=%x: cmd=%x\n", dev
, cmd
);
608 * We can use the generic implementation for these ioctls
611 case DEVCTL_DEVICE_GETSTATE
:
612 case DEVCTL_DEVICE_ONLINE
:
613 case DEVCTL_DEVICE_OFFLINE
:
614 case DEVCTL_BUS_GETSTATE
:
615 return (ndi_devctl_ioctl(dip
, cmd
, arg
, mode
, 0));
619 * read devctl ioctl data
621 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
)
626 case DEVCTL_DEVICE_RESET
:
627 PCMU_DBG0(PCMU_DBG_IOCTL
, dip
, "DEVCTL_DEVICE_RESET\n");
632 case DEVCTL_BUS_QUIESCE
:
633 PCMU_DBG0(PCMU_DBG_IOCTL
, dip
, "DEVCTL_BUS_QUIESCE\n");
634 if (ndi_get_bus_state(dip
, &bus_state
) == NDI_SUCCESS
) {
635 if (bus_state
== BUS_QUIESCED
) {
639 (void) ndi_set_bus_state(dip
, BUS_QUIESCED
);
642 case DEVCTL_BUS_UNQUIESCE
:
643 PCMU_DBG0(PCMU_DBG_IOCTL
, dip
, "DEVCTL_BUS_UNQUIESCE\n");
644 if (ndi_get_bus_state(dip
, &bus_state
) == NDI_SUCCESS
) {
645 if (bus_state
== BUS_ACTIVE
) {
649 (void) ndi_set_bus_state(dip
, BUS_ACTIVE
);
652 case DEVCTL_BUS_RESET
:
653 PCMU_DBG0(PCMU_DBG_IOCTL
, dip
, "DEVCTL_BUS_RESET\n");
657 case DEVCTL_BUS_RESETALL
:
658 PCMU_DBG0(PCMU_DBG_IOCTL
, dip
, "DEVCTL_BUS_RESETALL\n");
670 static int pcmu_prop_op(dev_t dev
, dev_info_t
*dip
, ddi_prop_op_t prop_op
,
671 int flags
, char *name
, caddr_t valuep
, int *lengthp
)
673 return (ddi_prop_op(dev
, dip
, prop_op
, flags
, name
, valuep
, lengthp
));
675 /* bus driver entry points */
678 * bus map entry point:
680 * if map request is for an rnumber
681 * get the corresponding regspec from device node
682 * build a new regspec in our parent's format
683 * build a new map_req with the new regspec
684 * call up the tree to complete the mapping
687 pcmu_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
688 off_t off
, off_t len
, caddr_t
*addrp
)
690 pcmu_t
*pcmu_p
= get_pcmu_soft_state(ddi_get_instance(dip
));
691 struct regspec p_regspec
;
692 ddi_map_req_t p_mapreq
;
693 int reglen
, rval
, r_no
;
694 pci_regspec_t reloc_reg
, *rp
= &reloc_reg
;
696 PCMU_DBG2(PCMU_DBG_MAP
, dip
, "rdip=%s%d:",
697 ddi_driver_name(rdip
), ddi_get_instance(rdip
));
699 if (mp
->map_flags
& DDI_MF_USER_MAPPING
) {
700 return (DDI_ME_UNIMPLEMENTED
);
703 switch (mp
->map_type
) {
705 reloc_reg
= *(pci_regspec_t
*)mp
->map_obj
.rp
; /* dup whole */
709 r_no
= mp
->map_obj
.rnumber
;
710 PCMU_DBG1(PCMU_DBG_MAP
| PCMU_DBG_CONT
, dip
, " r#=%x", r_no
);
712 if (ddi_getlongprop(DDI_DEV_T_NONE
, rdip
, DDI_PROP_DONTPASS
,
713 "reg", (caddr_t
)&rp
, ®len
) != DDI_SUCCESS
) {
714 return (DDI_ME_RNUMBER_RANGE
);
717 if (r_no
< 0 || r_no
>= reglen
/ sizeof (pci_regspec_t
)) {
718 kmem_free(rp
, reglen
);
719 return (DDI_ME_RNUMBER_RANGE
);
725 return (DDI_ME_INVAL
);
727 PCMU_DBG0(PCMU_DBG_MAP
| PCMU_DBG_CONT
, dip
, "\n");
729 /* use "assigned-addresses" to relocate regspec within pci space */
730 if (rval
= pcmu_reloc_reg(dip
, rdip
, pcmu_p
, rp
)) {
734 /* adjust regspec according to mapping request */
736 rp
->pci_size_low
= (uint_t
)len
;
738 rp
->pci_phys_low
+= off
;
740 /* use "ranges" to translate relocated pci regspec into parent space */
741 if (rval
= pcmu_xlate_reg(pcmu_p
, rp
, &p_regspec
)) {
745 p_mapreq
= *mp
; /* dup the whole structure */
746 p_mapreq
.map_type
= DDI_MT_REGSPEC
;
747 p_mapreq
.map_obj
.rp
= &p_regspec
;
748 rval
= ddi_map(dip
, &p_mapreq
, 0, 0, addrp
);
751 if (mp
->map_type
== DDI_MT_RNUMBER
) {
752 kmem_free(rp
- r_no
, reglen
);
758 int pcmu_peekfault_cnt
= 0;
759 int pcmu_pokefault_cnt
= 0;
763 pcmu_do_poke(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
)
765 pcmu_pbm_t
*pcbm_p
= pcmu_p
->pcmu_pcbm_p
;
766 int err
= DDI_SUCCESS
;
769 mutex_enter(&pcbm_p
->pcbm_pokeflt_mutex
);
770 pcbm_p
->pcbm_ontrap_data
= &otd
;
772 /* Set up protected environment. */
773 if (!on_trap(&otd
, OT_DATA_ACCESS
)) {
774 uintptr_t tramp
= otd
.ot_trampoline
;
776 otd
.ot_trampoline
= (uintptr_t)&poke_fault
;
777 err
= do_poke(in_args
->size
, (void *)in_args
->dev_addr
,
778 (void *)in_args
->host_addr
);
779 otd
.ot_trampoline
= tramp
;
785 * Read the async fault register for the PBM to see it sees
788 pcmu_pbm_clear_error(pcbm_p
);
790 if (otd
.ot_trap
& OT_DATA_ACCESS
) {
794 /* Take down protected environment. */
797 pcbm_p
->pcbm_ontrap_data
= NULL
;
798 mutex_exit(&pcbm_p
->pcbm_pokeflt_mutex
);
801 if (err
== DDI_FAILURE
)
802 pcmu_pokefault_cnt
++;
809 pcmu_ctlops_poke(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
)
811 return (pcmu_do_poke(pcmu_p
, in_args
));
816 pcmu_do_peek(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
)
818 int err
= DDI_SUCCESS
;
821 if (!on_trap(&otd
, OT_DATA_ACCESS
)) {
822 uintptr_t tramp
= otd
.ot_trampoline
;
824 otd
.ot_trampoline
= (uintptr_t)&peek_fault
;
825 err
= do_peek(in_args
->size
, (void *)in_args
->dev_addr
,
826 (void *)in_args
->host_addr
);
827 otd
.ot_trampoline
= tramp
;
834 if (err
== DDI_FAILURE
)
835 pcmu_peekfault_cnt
++;
842 pcmu_ctlops_peek(pcmu_t
*pcmu_p
, peekpoke_ctlops_t
*in_args
, void *result
)
844 result
= (void *)in_args
->host_addr
;
845 return (pcmu_do_peek(pcmu_p
, in_args
));
849 * control ops entry point:
851 * Requests handled completely:
852 * DDI_CTLOPS_INITCHILD see pcmu_init_child() for details
853 * DDI_CTLOPS_UNINITCHILD
854 * DDI_CTLOPS_REPORTDEV see report_dev() for details
855 * DDI_CTLOPS_XLATE_INTRS nothing to do
856 * DDI_CTLOPS_IOMIN cache line size if streaming otherwise 1
860 * DDI_CTLOPS_DVMAPAGESIZE
864 * DDI_CTLOPS_UNQUIESCE
866 * All others passed to parent.
869 pcmu_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
870 ddi_ctl_enum_t op
, void *arg
, void *result
)
872 pcmu_t
*pcmu_p
= get_pcmu_soft_state(ddi_get_instance(dip
));
875 case DDI_CTLOPS_INITCHILD
:
876 return (pcmu_init_child(pcmu_p
, (dev_info_t
*)arg
));
878 case DDI_CTLOPS_UNINITCHILD
:
879 return (pcmu_uninit_child(pcmu_p
, (dev_info_t
*)arg
));
881 case DDI_CTLOPS_REPORTDEV
:
882 return (pcmu_report_dev(rdip
));
884 case DDI_CTLOPS_IOMIN
:
886 * If we are using the streaming cache, align at
887 * least on a cache line boundary. Otherwise use
888 * whatever alignment is passed in.
890 return (DDI_SUCCESS
);
892 case DDI_CTLOPS_REGSIZE
:
893 *((off_t
*)result
) = pcmu_get_reg_set_size(rdip
, *((int *)arg
));
894 return (DDI_SUCCESS
);
896 case DDI_CTLOPS_NREGS
:
897 *((uint_t
*)result
) = pcmu_get_nreg_set(rdip
);
898 return (DDI_SUCCESS
);
900 case DDI_CTLOPS_DVMAPAGESIZE
:
901 *((ulong_t
*)result
) = 0;
902 return (DDI_SUCCESS
);
904 case DDI_CTLOPS_POKE
:
905 return (pcmu_ctlops_poke(pcmu_p
, (peekpoke_ctlops_t
*)arg
));
907 case DDI_CTLOPS_PEEK
:
908 return (pcmu_ctlops_peek(pcmu_p
, (peekpoke_ctlops_t
*)arg
,
911 case DDI_CTLOPS_AFFINITY
:
914 case DDI_CTLOPS_QUIESCE
:
915 return (DDI_FAILURE
);
917 case DDI_CTLOPS_UNQUIESCE
:
918 return (DDI_FAILURE
);
925 * Now pass the request up to our parent.
927 PCMU_DBG2(PCMU_DBG_CTLOPS
, dip
,
928 "passing request to parent: rdip=%s%d\n",
929 ddi_driver_name(rdip
), ddi_get_instance(rdip
));
930 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
936 pcmu_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
937 ddi_intr_handle_impl_t
*hdlp
, void *result
)
939 pcmu_t
*pcmu_p
= get_pcmu_soft_state(ddi_get_instance(dip
));
940 int ret
= DDI_SUCCESS
;
943 case DDI_INTROP_GETCAP
:
944 /* GetCap will always fail for all non PCI devices */
945 (void) pci_intx_get_cap(rdip
, (int *)result
);
947 case DDI_INTROP_SETCAP
:
950 case DDI_INTROP_ALLOC
:
951 *(int *)result
= hdlp
->ih_scratch1
;
953 case DDI_INTROP_FREE
:
955 case DDI_INTROP_GETPRI
:
956 *(int *)result
= hdlp
->ih_pri
? hdlp
->ih_pri
: 0;
958 case DDI_INTROP_SETPRI
:
960 case DDI_INTROP_ADDISR
:
961 ret
= pcmu_add_intr(dip
, rdip
, hdlp
);
963 case DDI_INTROP_REMISR
:
964 ret
= pcmu_remove_intr(dip
, rdip
, hdlp
);
966 case DDI_INTROP_ENABLE
:
967 ret
= pcmu_ib_update_intr_state(pcmu_p
, rdip
, hdlp
,
968 PCMU_INTR_STATE_ENABLE
);
970 case DDI_INTROP_DISABLE
:
971 ret
= pcmu_ib_update_intr_state(pcmu_p
, rdip
, hdlp
,
972 PCMU_INTR_STATE_DISABLE
);
974 case DDI_INTROP_SETMASK
:
975 ret
= pci_intx_set_mask(rdip
);
977 case DDI_INTROP_CLRMASK
:
978 ret
= pci_intx_clr_mask(rdip
);
980 case DDI_INTROP_GETPENDING
:
981 ret
= pci_intx_get_pending(rdip
, (int *)result
);
983 case DDI_INTROP_NINTRS
:
984 case DDI_INTROP_NAVAIL
:
985 *(int *)result
= i_ddi_get_intx_nintrs(rdip
);
987 case DDI_INTROP_SUPPORTED_TYPES
:
988 /* PCI nexus driver supports only fixed interrupts */
989 *(int *)result
= i_ddi_get_intx_nintrs(rdip
) ?
990 DDI_INTR_TYPE_FIXED
: 0;
1001 * CMU-CH specifics implementation:
1002 * interrupt mapping register
1004 * ECC and PBM error handling
1007 /* called by pcmu_attach() DDI_ATTACH to initialize pci objects */
1009 pcmu_obj_setup(pcmu_t
*pcmu_p
)
1013 mutex_enter(&pcmu_global_mutex
);
1014 pcmu_p
->pcmu_rev
= ddi_prop_get_int(DDI_DEV_T_ANY
, pcmu_p
->pcmu_dip
,
1015 DDI_PROP_DONTPASS
, "module-revision#", 0);
1017 pcmu_ib_create(pcmu_p
);
1018 pcmu_cb_create(pcmu_p
);
1019 pcmu_ecc_create(pcmu_p
);
1020 pcmu_pbm_create(pcmu_p
);
1021 pcmu_err_create(pcmu_p
);
1022 if ((ret
= pcmu_intr_setup(pcmu_p
)) != DDI_SUCCESS
)
1026 * Due to a hardware bug, do not create kstat for DC systems
1027 * with PCI hw revision less than 5.
1029 if ((strncmp(ddi_binding_name(pcmu_p
->pcmu_dip
),
1030 PCICMU_OPL_DC_BINDING_NAME
, strlen(PCICMU_OPL_DC_BINDING_NAME
))
1031 != 0) || (pcmu_p
->pcmu_rev
> 4)) {
1032 pcmu_kstat_create(pcmu_p
);
1035 mutex_exit(&pcmu_global_mutex
);
1036 if (ret
!= DDI_SUCCESS
) {
1037 cmn_err(CE_NOTE
, "Interrupt register failure, returning 0x%x\n",
1043 /* called by pcmu_detach() DDI_DETACH to destroy pci objects */
1045 pcmu_obj_destroy(pcmu_t
*pcmu_p
)
1047 mutex_enter(&pcmu_global_mutex
);
1049 pcmu_kstat_destroy(pcmu_p
);
1050 pcmu_pbm_destroy(pcmu_p
);
1051 pcmu_err_destroy(pcmu_p
);
1052 pcmu_ecc_destroy(pcmu_p
);
1053 pcmu_cb_destroy(pcmu_p
);
1054 pcmu_ib_destroy(pcmu_p
);
1055 pcmu_intr_teardown(pcmu_p
);
1057 mutex_exit(&pcmu_global_mutex
);
1060 /* called by pcmu_attach() DDI_RESUME to (re)initialize pci objects */
1062 pcmu_obj_resume(pcmu_t
*pcmu_p
)
1064 mutex_enter(&pcmu_global_mutex
);
1066 pcmu_ib_configure(pcmu_p
->pcmu_ib_p
);
1067 pcmu_ecc_configure(pcmu_p
);
1068 pcmu_ib_resume(pcmu_p
->pcmu_ib_p
);
1069 u2u_ittrans_resume((u2u_ittrans_data_t
**)
1070 &(pcmu_p
->pcmu_cb_p
->pcb_ittrans_cookie
));
1072 pcmu_pbm_configure(pcmu_p
->pcmu_pcbm_p
);
1074 pcmu_cb_resume(pcmu_p
->pcmu_cb_p
);
1076 pcmu_pbm_resume(pcmu_p
->pcmu_pcbm_p
);
1078 mutex_exit(&pcmu_global_mutex
);
1081 /* called by pcmu_detach() DDI_SUSPEND to suspend pci objects */
1083 pcmu_obj_suspend(pcmu_t
*pcmu_p
)
1085 mutex_enter(&pcmu_global_mutex
);
1087 pcmu_pbm_suspend(pcmu_p
->pcmu_pcbm_p
);
1088 pcmu_ib_suspend(pcmu_p
->pcmu_ib_p
);
1089 pcmu_cb_suspend(pcmu_p
->pcmu_cb_p
);
1091 mutex_exit(&pcmu_global_mutex
);
1095 pcmu_intr_setup(pcmu_t
*pcmu_p
)
1097 dev_info_t
*dip
= pcmu_p
->pcmu_dip
;
1098 pcmu_pbm_t
*pcbm_p
= pcmu_p
->pcmu_pcbm_p
;
1099 pcmu_cb_t
*pcb_p
= pcmu_p
->pcmu_cb_p
;
1103 * Get the interrupts property.
1105 if (ddi_getlongprop(DDI_DEV_T_NONE
, dip
, DDI_PROP_DONTPASS
,
1106 "interrupts", (caddr_t
)&pcmu_p
->pcmu_inos
,
1107 &pcmu_p
->pcmu_inos_len
) != DDI_SUCCESS
) {
1108 cmn_err(CE_PANIC
, "%s%d: no interrupts property\n",
1109 ddi_driver_name(dip
), ddi_get_instance(dip
));
1113 * figure out number of interrupts in the "interrupts" property
1114 * and convert them all into ino.
1116 i
= ddi_getprop(DDI_DEV_T_ANY
, dip
, 0, "#interrupt-cells", 1);
1117 i
= CELLS_1275_TO_BYTES(i
);
1118 no_of_intrs
= pcmu_p
->pcmu_inos_len
/ i
;
1119 for (i
= 0; i
< no_of_intrs
; i
++) {
1120 pcmu_p
->pcmu_inos
[i
] =
1121 PCMU_IB_MONDO_TO_INO(pcmu_p
->pcmu_inos
[i
]);
1124 pcb_p
->pcb_no_of_inos
= no_of_intrs
;
1125 if (i
= pcmu_ecc_register_intr(pcmu_p
)) {
1129 intr_dist_add(pcmu_cb_intr_dist
, pcb_p
);
1130 pcmu_ecc_enable_intr(pcmu_p
);
1132 if (i
= pcmu_pbm_register_intr(pcbm_p
)) {
1133 intr_dist_rem(pcmu_cb_intr_dist
, pcb_p
);
1136 intr_dist_add(pcmu_pbm_intr_dist
, pcbm_p
);
1137 pcmu_ib_intr_enable(pcmu_p
, pcmu_p
->pcmu_inos
[CBNINTR_PBM
]);
1139 intr_dist_add_weighted(pcmu_ib_intr_dist_all
, pcmu_p
->pcmu_ib_p
);
1140 return (DDI_SUCCESS
);
1142 pcmu_intr_teardown(pcmu_p
);
1147 * pcmu_fix_ranges - fixes the config space entry of the "ranges"
1148 * property on CMU-CH platforms
1151 pcmu_fix_ranges(pcmu_ranges_t
*rng_p
, int rng_entries
)
1154 for (i
= 0; i
< rng_entries
; i
++, rng_p
++) {
1155 if ((rng_p
->child_high
& PCI_REG_ADDR_M
) == PCI_ADDR_CONFIG
)
1156 rng_p
->parent_low
|= rng_p
->child_high
;
1161 * map_pcmu_registers
1163 * This function is called from the attach routine to map the registers
1164 * accessed by this driver.
1166 * used by: pcmu_attach()
1168 * return value: DDI_FAILURE on failure
1171 map_pcmu_registers(pcmu_t
*pcmu_p
, dev_info_t
*dip
)
1173 ddi_device_acc_attr_t attr
;
1175 attr
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
1176 attr
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
1178 attr
.devacc_attr_endian_flags
= DDI_NEVERSWAP_ACC
;
1179 if (ddi_regs_map_setup(dip
, 0, &pcmu_p
->pcmu_address
[0], 0, 0,
1180 &attr
, &pcmu_p
->pcmu_ac
[0]) != DDI_SUCCESS
) {
1181 cmn_err(CE_WARN
, "%s%d: unable to map reg entry 0\n",
1182 ddi_driver_name(dip
), ddi_get_instance(dip
));
1183 return (DDI_FAILURE
);
1187 * We still use pcmu_address[2]
1189 if (ddi_regs_map_setup(dip
, 2, &pcmu_p
->pcmu_address
[2], 0, 0,
1190 &attr
, &pcmu_p
->pcmu_ac
[2]) != DDI_SUCCESS
) {
1191 cmn_err(CE_WARN
, "%s%d: unable to map reg entry 2\n",
1192 ddi_driver_name(dip
), ddi_get_instance(dip
));
1193 ddi_regs_map_free(&pcmu_p
->pcmu_ac
[0]);
1194 return (DDI_FAILURE
);
1198 * The second register set contains the bridge's configuration
1199 * header. This header is at the very beginning of the bridge's
1200 * configuration space. This space has litte-endian byte order.
1202 attr
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
1203 if (ddi_regs_map_setup(dip
, 1, &pcmu_p
->pcmu_address
[1], 0,
1204 PCI_CONF_HDR_SIZE
, &attr
, &pcmu_p
->pcmu_ac
[1]) != DDI_SUCCESS
) {
1206 cmn_err(CE_WARN
, "%s%d: unable to map reg entry 1\n",
1207 ddi_driver_name(dip
), ddi_get_instance(dip
));
1208 ddi_regs_map_free(&pcmu_p
->pcmu_ac
[0]);
1209 return (DDI_FAILURE
);
1211 PCMU_DBG2(PCMU_DBG_ATTACH
, dip
, "address (%p,%p)\n",
1212 pcmu_p
->pcmu_address
[0], pcmu_p
->pcmu_address
[1]);
1213 return (DDI_SUCCESS
);
1217 * unmap_pcmu_registers:
1219 * This routine unmap the registers mapped by map_pcmu_registers.
1221 * used by: pcmu_detach()
1223 * return value: none
1226 unmap_pcmu_registers(pcmu_t
*pcmu_p
)
1228 ddi_regs_map_free(&pcmu_p
->pcmu_ac
[0]);
1229 ddi_regs_map_free(&pcmu_p
->pcmu_ac
[1]);
1230 ddi_regs_map_free(&pcmu_p
->pcmu_ac
[2]);
1234 * These convenience wrappers relies on map_pcmu_registers() to setup
1235 * pcmu_address[0-2] correctly at first.
1238 get_reg_base(pcmu_t
*pcmu_p
)
1240 return ((uintptr_t)pcmu_p
->pcmu_address
[2]);
1243 /* The CMU-CH config reg base is always the 2nd reg entry */
1245 get_config_reg_base(pcmu_t
*pcmu_p
)
1247 return ((uintptr_t)(pcmu_p
->pcmu_address
[1]));
1251 ib_get_map_reg(pcmu_ib_mondo_t mondo
, uint32_t cpu_id
)
1253 return ((mondo
) | (cpu_id
<< PCMU_INTR_MAP_REG_TID_SHIFT
) |
1254 PCMU_INTR_MAP_REG_VALID
);
1259 ib_map_reg_get_cpu(volatile uint64_t reg
)
1261 return ((reg
& PCMU_INTR_MAP_REG_TID
) >>
1262 PCMU_INTR_MAP_REG_TID_SHIFT
);
1266 ib_intr_map_reg_addr(pcmu_ib_t
*pib_p
, pcmu_ib_ino_t ino
)
1271 addr
= (uint64_t *)(pib_p
->pib_obio_intr_map_regs
+
1272 (((uint_t
)ino
& 0x1f) << 3));
1277 ib_clear_intr_reg_addr(pcmu_ib_t
*pib_p
, pcmu_ib_ino_t ino
)
1282 addr
= (uint64_t *)(pib_p
->pib_obio_clear_intr_regs
+
1283 (((uint_t
)ino
& 0x1f) << 3));
1288 pcmu_ib_setup(pcmu_ib_t
*pib_p
)
1290 pcmu_t
*pcmu_p
= pib_p
->pib_pcmu_p
;
1291 uintptr_t a
= get_reg_base(pcmu_p
);
1293 pib_p
->pib_ign
= PCMU_ID_TO_IGN(pcmu_p
->pcmu_id
);
1294 pib_p
->pib_max_ino
= PCMU_MAX_INO
;
1295 pib_p
->pib_obio_intr_map_regs
= a
+ PCMU_IB_OBIO_INTR_MAP_REG_OFFSET
;
1296 pib_p
->pib_obio_clear_intr_regs
=
1297 a
+ PCMU_IB_OBIO_CLEAR_INTR_REG_OFFSET
;
1302 * Return the cpuid to to be used for an ino.
1304 * On multi-function pci devices, functions have separate devinfo nodes and
1307 * This function determines if there is already an established slot-oriented
1308 * interrupt-to-cpu binding established, if there is then it returns that
1309 * cpu. Otherwise a new cpu is selected by intr_dist_cpuid().
1311 * The devinfo node we are trying to associate a cpu with is
1312 * ino_p->pino_ih_head->ih_dip.
1315 pcmu_intr_dist_cpuid(pcmu_ib_t
*pib_p
, pcmu_ib_ino_info_t
*ino_p
)
1317 dev_info_t
*rdip
= ino_p
->pino_ih_head
->ih_dip
;
1318 dev_info_t
*prdip
= ddi_get_parent(rdip
);
1319 pcmu_ib_ino_info_t
*sino_p
;
1322 char *buf1
= NULL
, *buf2
= NULL
;
1327 /* must be CMU-CH driver parent (not ebus) */
1328 if (strcmp(ddi_driver_name(prdip
), "pcicmu") != 0)
1332 * From PCI 1275 binding: 2.2.1.3 Unit Address representation:
1333 * Since the "unit-number" is the address that appears in on Open
1334 * Firmware 'device path', it follows that only the DD and DD,FF
1335 * forms of the text representation can appear in a 'device path'.
1337 * The rdip unit address is of the form "DD[,FF]". Define two
1338 * unit address strings that represent same-slot use: "DD" and "DD,".
1339 * The first compare uses strcmp, the second uses strncmp.
1341 s1
= ddi_get_name_addr(rdip
);
1346 buf1
= kmem_alloc(MAXNAMELEN
, KM_SLEEP
); /* strcmp */
1347 buf2
= kmem_alloc(MAXNAMELEN
, KM_SLEEP
); /* strncmp */
1348 s1
= strcpy(buf1
, s1
);
1349 s2
= strcpy(buf2
, s1
);
1351 s1
= strrchr(s1
, ',');
1353 *s1
= '\0'; /* have "DD,FF" */
1354 s1
= buf1
; /* search via strcmp "DD" */
1356 s2
= strrchr(s2
, ',');
1359 l2
= strlen(s2
); /* search via strncmp "DD," */
1361 (void) strcat(s2
, ","); /* have "DD" */
1362 l2
= strlen(s2
); /* search via strncmp "DD," */
1366 * Search the established ino list for devinfo nodes bound
1367 * to an ino that matches one of the slot use strings.
1369 ASSERT(MUTEX_HELD(&pib_p
->pib_ino_lst_mutex
));
1370 for (sino_p
= pib_p
->pib_ino_lst
; sino_p
; sino_p
= sino_p
->pino_next
) {
1371 /* skip self and non-established */
1372 if ((sino_p
== ino_p
) || (sino_p
->pino_established
== 0))
1375 /* skip non-siblings */
1376 sdip
= sino_p
->pino_ih_head
->ih_dip
;
1377 psdip
= ddi_get_parent(sdip
);
1381 /* must be CMU-CH driver parent (not ebus) */
1382 if (strcmp(ddi_driver_name(psdip
), "pcicmu") != 0)
1385 s3
= ddi_get_name_addr(sdip
);
1386 if ((s1
&& (strcmp(s1
, s3
) == 0)) ||
1387 (strncmp(s2
, s3
, l2
) == 0)) {
1388 extern int intr_dist_debug
;
1390 if (intr_dist_debug
) {
1391 cmn_err(CE_CONT
, "intr_dist: "
1392 "pcicmu`pcmu_intr_dist_cpuid "
1393 "%s#%d %s: cpu %d established "
1394 "by %s#%d %s\n", ddi_driver_name(rdip
),
1395 ddi_get_instance(rdip
),
1396 ddi_deviname(rdip
, buf1
),
1398 ddi_driver_name(sdip
),
1399 ddi_get_instance(sdip
),
1400 ddi_deviname(sdip
, buf2
));
1406 /* If a slot use match is found then use established cpu */
1408 cpu_id
= sino_p
->pino_cpuid
; /* target established cpu */
1412 newcpu
: cpu_id
= intr_dist_cpuid(); /* target new cpu */
1415 kmem_free(buf1
, MAXNAMELEN
);
1417 kmem_free(buf2
, MAXNAMELEN
);
1422 pcmu_cb_teardown(pcmu_t
*pcmu_p
)
1424 pcmu_cb_t
*pcb_p
= pcmu_p
->pcmu_cb_p
;
1426 u2u_ittrans_uninit((u2u_ittrans_data_t
*)pcb_p
->pcb_ittrans_cookie
);
1430 pcmu_ecc_add_intr(pcmu_t
*pcmu_p
, int inum
, pcmu_ecc_intr_info_t
*eii_p
)
1434 mondo
= ((pcmu_p
->pcmu_cb_p
->pcb_ign
<< PCMU_INO_BITS
) |
1435 pcmu_p
->pcmu_inos
[inum
]);
1437 VERIFY(add_ivintr(mondo
, pcmu_pil
[inum
], (intrfunc
)pcmu_ecc_intr
,
1438 (caddr_t
)eii_p
, NULL
, NULL
) == 0);
1440 return (PCMU_ATTACH_RETCODE(PCMU_ECC_OBJ
,
1441 PCMU_OBJ_INTR_ADD
, DDI_SUCCESS
));
1446 pcmu_ecc_rem_intr(pcmu_t
*pcmu_p
, int inum
, pcmu_ecc_intr_info_t
*eii_p
)
1450 mondo
= ((pcmu_p
->pcmu_cb_p
->pcb_ign
<< PCMU_INO_BITS
) |
1451 pcmu_p
->pcmu_inos
[inum
]);
1453 VERIFY(rem_ivintr(mondo
, pcmu_pil
[inum
]) == 0);
1457 pcmu_pbm_configure(pcmu_pbm_t
*pcbm_p
)
1459 pcmu_t
*pcmu_p
= pcbm_p
->pcbm_pcmu_p
;
1460 dev_info_t
*dip
= pcmu_p
->pcmu_dip
;
1462 #define pbm_err ((PCMU_PCI_AFSR_E_MASK << PCMU_PCI_AFSR_PE_SHIFT) | \
1463 (PCMU_PCI_AFSR_E_MASK << PCMU_PCI_AFSR_SE_SHIFT))
1464 #define csr_err (PCI_STAT_PERROR | PCI_STAT_S_PERROR | \
1465 PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB | \
1466 PCI_STAT_S_TARG_AB | PCI_STAT_S_PERROR)
1469 * Clear any PBM errors.
1471 *pcbm_p
->pcbm_async_flt_status_reg
= pbm_err
;
1474 * Clear error bits in configuration status register.
1476 PCMU_DBG1(PCMU_DBG_ATTACH
, dip
,
1477 "pcmu_pbm_configure: conf status reg=%x\n", csr_err
);
1479 pcbm_p
->pcbm_config_header
->ch_status_reg
= csr_err
;
1481 PCMU_DBG1(PCMU_DBG_ATTACH
, dip
,
1482 "pcmu_pbm_configure: conf status reg==%x\n",
1483 pcbm_p
->pcbm_config_header
->ch_status_reg
);
1485 (void) ndi_prop_update_int(DDI_DEV_T_ANY
, dip
, "latency-timer",
1486 (int)pcbm_p
->pcbm_config_header
->ch_latency_timer_reg
);
1492 pcmu_pbm_disable_errors(pcmu_pbm_t
*pcbm_p
)
1494 pcmu_t
*pcmu_p
= pcbm_p
->pcbm_pcmu_p
;
1495 pcmu_ib_t
*pib_p
= pcmu_p
->pcmu_ib_p
;
1498 * Disable error and streaming byte hole interrupts via the
1499 * PBM control register.
1501 *pcbm_p
->pcbm_ctrl_reg
&= ~PCMU_PCI_CTRL_ERR_INT_EN
;
1504 * Disable error interrupts via the interrupt mapping register.
1506 pcmu_ib_intr_disable(pib_p
,
1507 pcmu_p
->pcmu_inos
[CBNINTR_PBM
], PCMU_IB_INTR_NOWAIT
);
1512 pcmu_cb_setup(pcmu_t
*pcmu_p
)
1514 uint64_t csr
, csr_pa
, pa
;
1515 pcmu_cb_t
*pcb_p
= pcmu_p
->pcmu_cb_p
;
1517 pcb_p
->pcb_ign
= PCMU_ID_TO_IGN(pcmu_p
->pcmu_id
);
1518 pa
= (uint64_t)hat_getpfnum(kas
.a_hat
, pcmu_p
->pcmu_address
[0]);
1519 pcb_p
->pcb_base_pa
= pa
= pa
>> (32 - MMU_PAGESHIFT
) << 32;
1520 pcb_p
->pcb_map_pa
= pa
+ PCMU_IB_OBIO_INTR_MAP_REG_OFFSET
;
1521 pcb_p
->pcb_clr_pa
= pa
+ PCMU_IB_OBIO_CLEAR_INTR_REG_OFFSET
;
1522 pcb_p
->pcb_obsta_pa
= pa
+ PCMU_IB_OBIO_INTR_STATE_DIAG_REG
;
1524 csr_pa
= pa
+ PCMU_CB_CONTROL_STATUS_REG_OFFSET
;
1525 csr
= lddphysio(csr_pa
);
1528 * Clear any pending address parity errors.
1530 if (csr
& PCMU_CB_CONTROL_STATUS_APERR
) {
1531 csr
|= PCMU_CB_CONTROL_STATUS_APERR
;
1532 cmn_err(CE_WARN
, "clearing UPA address parity error\n");
1534 csr
|= PCMU_CB_CONTROL_STATUS_APCKEN
;
1535 csr
&= ~PCMU_CB_CONTROL_STATUS_IAP
;
1536 stdphysio(csr_pa
, csr
);
1538 u2u_ittrans_init(pcmu_p
,
1539 (u2u_ittrans_data_t
**)&pcb_p
->pcb_ittrans_cookie
);
1543 pcmu_ecc_setup(pcmu_ecc_t
*pecc_p
)
1545 pecc_p
->pecc_ue
.pecc_errpndg_mask
= 0;
1546 pecc_p
->pecc_ue
.pecc_offset_mask
= PCMU_ECC_UE_AFSR_DW_OFFSET
;
1547 pecc_p
->pecc_ue
.pecc_offset_shift
= PCMU_ECC_UE_AFSR_DW_OFFSET_SHIFT
;
1548 pecc_p
->pecc_ue
.pecc_size_log2
= 3;
1552 get_pbm_reg_base(pcmu_t
*pcmu_p
)
1554 return ((uintptr_t)(pcmu_p
->pcmu_address
[0]));
1558 pcmu_pbm_setup(pcmu_pbm_t
*pcbm_p
)
1560 pcmu_t
*pcmu_p
= pcbm_p
->pcbm_pcmu_p
;
1563 * Get the base virtual address for the PBM control block.
1565 uintptr_t a
= get_pbm_reg_base(pcmu_p
);
1568 * Get the virtual address of the PCI configuration header.
1569 * This should be mapped little-endian.
1571 pcbm_p
->pcbm_config_header
=
1572 (config_header_t
*)get_config_reg_base(pcmu_p
);
1575 * Get the virtual addresses for control, error and diag
1578 pcbm_p
->pcbm_ctrl_reg
= (uint64_t *)(a
+ PCMU_PCI_CTRL_REG_OFFSET
);
1579 pcbm_p
->pcbm_diag_reg
= (uint64_t *)(a
+ PCMU_PCI_DIAG_REG_OFFSET
);
1580 pcbm_p
->pcbm_async_flt_status_reg
=
1581 (uint64_t *)(a
+ PCMU_PCI_ASYNC_FLT_STATUS_REG_OFFSET
);
1582 pcbm_p
->pcbm_async_flt_addr_reg
=
1583 (uint64_t *)(a
+ PCMU_PCI_ASYNC_FLT_ADDR_REG_OFFSET
);
1588 pcmu_pbm_teardown(pcmu_pbm_t
*pcbm_p
)
1593 pcmu_get_numproxy(dev_info_t
*dip
)
1595 return (ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1596 "#upa-interrupt-proxies", 1));
1600 pcmu_get_portid(dev_info_t
*dip
)
1602 return (ddi_getprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1607 * CMU-CH Performance Events.
1609 static pcmu_kev_mask_t
1610 pcicmu_pcmu_events
[] = {
1611 {"pio_cycles_b", 0xf}, {"interrupts", 0x11},
1612 {"upa_inter_nack", 0x12}, {"pio_reads", 0x13},
1613 {"pio_writes", 0x14},
1618 * Create the picN kstat's.
1623 pcmu_name_kstat
= (pcmu_ksinfo_t
*)kmem_alloc(sizeof (pcmu_ksinfo_t
),
1626 if (pcmu_name_kstat
== NULL
) {
1627 cmn_err(CE_WARN
, "pcicmu : no space for kstat\n");
1629 pcmu_name_kstat
->pic_no_evs
=
1630 sizeof (pcicmu_pcmu_events
) / sizeof (pcmu_kev_mask_t
);
1631 pcmu_name_kstat
->pic_shift
[0] = PCMU_SHIFT_PIC0
;
1632 pcmu_name_kstat
->pic_shift
[1] = PCMU_SHIFT_PIC1
;
1633 pcmu_create_name_kstat("pcmup",
1634 pcmu_name_kstat
, pcicmu_pcmu_events
);
1639 * Called from _fini()
1644 if (pcmu_name_kstat
!= NULL
) {
1645 pcmu_delete_name_kstat(pcmu_name_kstat
);
1646 kmem_free(pcmu_name_kstat
, sizeof (pcmu_ksinfo_t
));
1647 pcmu_name_kstat
= NULL
;
1652 * Create the performance 'counters' kstat.
1655 pcmu_add_upstream_kstat(pcmu_t
*pcmu_p
)
1657 pcmu_cntr_pa_t
*cntr_pa_p
= &pcmu_p
->pcmu_uks_pa
;
1658 uint64_t regbase
= va_to_pa((void *)get_reg_base(pcmu_p
));
1660 cntr_pa_p
->pcr_pa
= regbase
+ PCMU_PERF_PCR_OFFSET
;
1661 cntr_pa_p
->pic_pa
= regbase
+ PCMU_PERF_PIC_OFFSET
;
1662 pcmu_p
->pcmu_uksp
= pcmu_create_cntr_kstat(pcmu_p
, "pcmup",
1663 NUM_OF_PICS
, pcmu_cntr_kstat_pa_update
, cntr_pa_p
);
1667 * u2u_ittrans_init() is caled from in pci.c's pcmu_cb_setup() per CMU.
1668 * Second argument "ittrans_cookie" is address of pcb_ittrans_cookie in
1669 * pcb_p member. allocated interrupt block is returned in it.
1672 u2u_ittrans_init(pcmu_t
*pcmu_p
, u2u_ittrans_data_t
**ittrans_cookie
)
1675 u2u_ittrans_data_t
*u2u_trans_p
;
1676 ddi_device_acc_attr_t attr
;
1681 * Allocate the data structure to support U2U's
1682 * interrupt target translations.
1684 u2u_trans_p
= (u2u_ittrans_data_t
*)
1685 kmem_zalloc(sizeof (u2u_ittrans_data_t
), KM_SLEEP
);
1688 * Get other properties, "board#"
1690 board
= ddi_getprop(DDI_DEV_T_ANY
, pcmu_p
->pcmu_dip
,
1691 DDI_PROP_DONTPASS
, "board#", -1);
1693 u2u_trans_p
->u2u_board
= board
;
1696 /* this cannot happen on production systems */
1697 cmn_err(CE_PANIC
, "u2u:Invalid property;board = %d", board
);
1701 * Initialize interrupt target translations mutex.
1703 mutex_init(&(u2u_trans_p
->u2u_ittrans_lock
), "u2u_ittrans_lock",
1704 MUTEX_DEFAULT
, NULL
);
1707 * Get U2U's registers space by ddi_regs_map_setup(9F)
1709 attr
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
1710 attr
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
1711 attr
.devacc_attr_endian_flags
= DDI_NEVERSWAP_ACC
;
1713 ret
= ddi_regs_map_setup(pcmu_p
->pcmu_dip
,
1714 REGS_INDEX_OF_U2U
, (caddr_t
*)(&(u2u_trans_p
->u2u_regs_base
)),
1715 0, 0, &attr
, &(u2u_trans_p
->u2u_acc
));
1718 * check result of ddi_regs_map_setup().
1720 if (ret
!= DDI_SUCCESS
) {
1721 cmn_err(CE_PANIC
, "u2u%d: registers map setup failed", board
);
1725 * Read Port-id(1 byte) in u2u
1727 u2u_trans_p
->u2u_port_id
= *(volatile int32_t *)
1728 (u2u_trans_p
->u2u_regs_base
+ U2U_PID_REGISTER_OFFSET
);
1730 if (pcmu_p
->pcmu_id
!= u2u_trans_p
->u2u_port_id
) {
1731 cmn_err(CE_PANIC
, "u2u%d: Invalid Port-ID", board
);
1734 *ittrans_cookie
= u2u_trans_p
;
1738 * u2u_ittras_resume() is called from pcmu_obj_resume() at DDI_RESUME entry.
1741 u2u_ittrans_resume(u2u_ittrans_data_t
**ittrans_cookie
)
1744 u2u_ittrans_data_t
*u2u_trans_p
;
1745 u2u_ittrans_id_t
*ittrans_id_p
;
1746 uintptr_t data_reg_addr
;
1749 u2u_trans_p
= *ittrans_cookie
;
1752 * Set U2U Data Register
1754 for (ix
= 0; ix
< U2U_DATA_NUM
; ix
++) {
1755 ittrans_id_p
= &(u2u_trans_p
->u2u_ittrans_id
[ix
]);
1756 data_reg_addr
= u2u_trans_p
->u2u_regs_base
+
1757 U2U_DATA_REGISTER_OFFSET
+ (ix
* sizeof (uint64_t));
1758 if (ittrans_id_p
->u2u_ino_map_reg
== NULL
) {
1759 /* This index was not set */
1762 *(volatile uint32_t *) (data_reg_addr
) =
1763 (uint32_t)ittrans_id_p
->u2u_tgt_cpu_id
;
1769 * u2u_ittras_uninit() is called from ib_destroy() at detach,
1770 * or occuring error in attach.
1773 u2u_ittrans_uninit(u2u_ittrans_data_t
*ittrans_cookie
)
1776 if (ittrans_cookie
== NULL
) {
1777 return; /* not support */
1780 if (ittrans_cookie
== (u2u_ittrans_data_t
*)(-1)) {
1781 return; /* illeagal case */
1784 ddi_regs_map_free(&(ittrans_cookie
->u2u_acc
));
1785 mutex_destroy(&(ittrans_cookie
->u2u_ittrans_lock
));
1786 kmem_free((void *)ittrans_cookie
, sizeof (u2u_ittrans_data_t
));
1790 * This routine,u2u_translate_tgtid(, , cpu_id, pino_map_reg),
1791 * searches index having same value of pino_map_reg, or empty.
1792 * Then, stores cpu_id in a U2U Data Register as this index,
1793 * and return this index.
1796 u2u_translate_tgtid(pcmu_t
*pcmu_p
, uint_t cpu_id
,
1797 volatile uint64_t *pino_map_reg
)
1802 int err_level
; /* severity level for cmn_err */
1803 u2u_ittrans_id_t
*ittrans_id_p
;
1804 uintptr_t data_reg_addr
;
1805 u2u_ittrans_data_t
*ittrans_cookie
;
1808 (u2u_ittrans_data_t
*)(pcmu_p
->pcmu_cb_p
->pcb_ittrans_cookie
);
1810 if (ittrans_cookie
== NULL
) {
1814 if (ittrans_cookie
== (u2u_ittrans_data_t
*)(-1)) {
1815 return (-1); /* illeagal case */
1818 mutex_enter(&(ittrans_cookie
->u2u_ittrans_lock
));
1821 * Decide index No. of U2U Data registers in either
1822 * already used by same pino_map_reg, or empty.
1824 for (ix
= 0; ix
< U2U_DATA_NUM
; ix
++) {
1825 ittrans_id_p
= &(ittrans_cookie
->u2u_ittrans_id
[ix
]);
1826 if (ittrans_id_p
->u2u_ino_map_reg
== pino_map_reg
) {
1827 /* already used this pino_map_reg */
1832 ittrans_id_p
->u2u_ino_map_reg
== NULL
) {
1839 err_level
= CE_WARN
;
1841 err_level
= CE_PANIC
;
1843 cmn_err(err_level
, "u2u%d:No more U2U-Data regs!!",
1844 ittrans_cookie
->u2u_board
);
1850 * set cpu_id into u2u_data_reg by index.
1851 * ((uint64_t)(u2u_regs_base
1852 * + U2U_DATA_REGISTER_OFFSET))[index] = cpu_id;
1855 data_reg_addr
= ittrans_cookie
->u2u_regs_base
1856 + U2U_DATA_REGISTER_OFFSET
1857 + (index
* sizeof (uint64_t));
1860 * Set cpu_id into U2U Data register[index]
1862 *(volatile uint32_t *) (data_reg_addr
) = (uint32_t)cpu_id
;
1865 * Setup for software, excepting at panicing.
1866 * and rebooting, etc...?
1869 ittrans_id_p
= &(ittrans_cookie
->u2u_ittrans_id
[index
]);
1870 ittrans_id_p
->u2u_tgt_cpu_id
= cpu_id
;
1871 ittrans_id_p
->u2u_ino_map_reg
= pino_map_reg
;
1874 mutex_exit(&(ittrans_cookie
->u2u_ittrans_lock
));
1880 * u2u_ittrans_cleanup() is called from common_pcmu_ib_intr_disable()
1881 * after called intr_rem_cpu(mondo).
1884 u2u_ittrans_cleanup(u2u_ittrans_data_t
*ittrans_cookie
,
1885 volatile uint64_t *pino_map_reg
)
1889 u2u_ittrans_id_t
*ittrans_id_p
;
1891 if (ittrans_cookie
== NULL
) {
1895 if (ittrans_cookie
== (u2u_ittrans_data_t
*)(-1)) {
1896 return; /* illeagal case */
1899 mutex_enter(&(ittrans_cookie
->u2u_ittrans_lock
));
1901 for (ix
= 0; ix
< U2U_DATA_NUM
; ix
++) {
1902 ittrans_id_p
= &(ittrans_cookie
->u2u_ittrans_id
[ix
]);
1903 if (ittrans_id_p
->u2u_ino_map_reg
== pino_map_reg
) {
1904 ittrans_id_p
->u2u_ino_map_reg
= NULL
;
1909 mutex_exit(&(ittrans_cookie
->u2u_ittrans_lock
));
1913 * pcmu_ecc_classify, called by ecc_handler to classify ecc errors
1914 * and determine if we should panic or not.
1917 pcmu_ecc_classify(uint64_t err
, pcmu_ecc_errstate_t
*ecc_err_p
)
1919 struct async_flt
*ecc
= &ecc_err_p
->ecc_aflt
;
1921 pcmu_t
*pcmu_p
= ecc_err_p
->ecc_ii_p
.pecc_p
->pecc_pcmu_p
;
1923 ASSERT(MUTEX_HELD(&pcmu_p
->pcmu_err_mutex
));
1925 ecc_err_p
->ecc_bridge_type
= PCI_OPLCMU
; /* RAGS */
1927 * Get the parent bus id that caused the error.
1929 ecc_err_p
->ecc_dev_id
= (ecc_err_p
->ecc_afsr
& PCMU_ECC_UE_AFSR_ID
)
1930 >> PCMU_ECC_UE_AFSR_ID_SHIFT
;
1932 * Determine the doubleword offset of the error.
1934 ecc_err_p
->ecc_dw_offset
= (ecc_err_p
->ecc_afsr
&
1935 PCMU_ECC_UE_AFSR_DW_OFFSET
) >> PCMU_ECC_UE_AFSR_DW_OFFSET_SHIFT
;
1937 * Determine the primary error type.
1940 case PCMU_ECC_UE_AFSR_E_PIO
:
1941 if (ecc_err_p
->pecc_pri
) {
1942 ecc
->flt_erpt_class
= PCI_ECC_PIO_UE
;
1944 ecc
->flt_erpt_class
= PCI_ECC_SEC_PIO_UE
;
1946 /* For CMU-CH, a UE is always fatal. */
1956 * pcmu_pbm_classify, called by pcmu_pbm_afsr_report to classify piow afsr.
1959 pcmu_pbm_classify(pcmu_pbm_errstate_t
*pbm_err_p
)
1965 if (pbm_err_p
->pcbm_pri
) {
1966 tmp_class
= &pbm_err_p
->pcbm_pci
.pcmu_err_class
;
1967 e
= PBM_AFSR_TO_PRIERR(pbm_err_p
->pbm_afsr
);
1968 pbm_err_p
->pbm_log
= FM_LOG_PCI
;
1970 tmp_class
= &pbm_err_p
->pbm_err_class
;
1971 e
= PBM_AFSR_TO_SECERR(pbm_err_p
->pbm_afsr
);
1972 pbm_err_p
->pbm_log
= FM_LOG_PBM
;
1975 if (e
& PCMU_PCI_AFSR_E_MA
) {
1976 *tmp_class
= pbm_err_p
->pcbm_pri
? PCI_MA
: PCI_SEC_MA
;
1983 * Function used to clear PBM/PCI/IOMMU error state after error handling
1984 * is complete. Only clearing error bits which have been logged. Called by
1985 * pcmu_pbm_err_handler and pcmu_bus_exit.
1988 pcmu_clear_error(pcmu_t
*pcmu_p
, pcmu_pbm_errstate_t
*pbm_err_p
)
1990 pcmu_pbm_t
*pcbm_p
= pcmu_p
->pcmu_pcbm_p
;
1992 ASSERT(MUTEX_HELD(&pcbm_p
->pcbm_pcmu_p
->pcmu_err_mutex
));
1994 *pcbm_p
->pcbm_ctrl_reg
= pbm_err_p
->pbm_ctl_stat
;
1995 *pcbm_p
->pcbm_async_flt_status_reg
= pbm_err_p
->pbm_afsr
;
1996 pcbm_p
->pcbm_config_header
->ch_status_reg
=
1997 pbm_err_p
->pcbm_pci
.pcmu_cfg_stat
;
2002 pcmu_pbm_err_handler(dev_info_t
*dip
, ddi_fm_error_t
*derr
,
2003 const void *impl_data
, int caller
)
2008 uint32_t prierr
, secerr
;
2009 pcmu_pbm_errstate_t pbm_err
;
2010 pcmu_t
*pcmu_p
= (pcmu_t
*)impl_data
;
2013 ASSERT(MUTEX_HELD(&pcmu_p
->pcmu_err_mutex
));
2014 pcmu_pbm_errstate_get(pcmu_p
, &pbm_err
);
2016 derr
->fme_ena
= derr
->fme_ena
? derr
->fme_ena
:
2017 fm_ena_generate(0, FM_ENA_FMT1
);
2019 prierr
= PBM_AFSR_TO_PRIERR(pbm_err
.pbm_afsr
);
2020 secerr
= PBM_AFSR_TO_SECERR(pbm_err
.pbm_afsr
);
2022 if (derr
->fme_flag
== DDI_FM_ERR_PEEK
) {
2024 * For ddi_peek treat all events as nonfatal. We only
2025 * really call this function so that pcmu_clear_error()
2026 * and ndi_fm_handler_dispatch() will get called.
2030 } else if (derr
->fme_flag
== DDI_FM_ERR_POKE
) {
2032 * For ddi_poke we can treat as nonfatal if the
2033 * following conditions are met :
2034 * 1. Make sure only primary error is MA/TA
2035 * 2. Make sure no secondary error
2036 * 3. check pci config header stat reg to see MA/TA is
2037 * logged. We cannot verify only MA/TA is recorded
2038 * since it gets much more complicated when a
2039 * PCI-to-PCI bridge is present.
2041 if ((prierr
== PCMU_PCI_AFSR_E_MA
) && !secerr
&&
2042 (pbm_err
.pcbm_pci
.pcmu_cfg_stat
& PCI_STAT_R_MAST_AB
)) {
2048 if (prierr
|| secerr
) {
2049 ret
= pcmu_pbm_afsr_report(dip
, derr
->fme_ena
, &pbm_err
);
2050 if (ret
== DDI_FM_FATAL
) {
2057 ret
= pcmu_cfg_report(dip
, derr
, &pbm_err
.pcbm_pci
, caller
, prierr
);
2058 if (ret
== DDI_FM_FATAL
) {
2060 } else if (ret
== DDI_FM_NONFATAL
) {
2065 if (ret
== DDI_FM_FATAL
) {
2067 } else if (ret
== DDI_FM_NONFATAL
) {
2069 } else if (ret
== DDI_FM_UNKNOWN
) {
2073 /* Cleanup and reset error bits */
2074 pcmu_clear_error(pcmu_p
, &pbm_err
);
2076 return (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
2077 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
2081 pcmu_check_error(pcmu_t
*pcmu_p
)
2083 pcmu_pbm_t
*pcbm_p
= pcmu_p
->pcmu_pcbm_p
;
2084 uint16_t pcmu_cfg_stat
;
2087 ASSERT(MUTEX_HELD(&pcmu_p
->pcmu_err_mutex
));
2089 pcmu_cfg_stat
= pcbm_p
->pcbm_config_header
->ch_status_reg
;
2090 pbm_afsr
= *pcbm_p
->pcbm_async_flt_status_reg
;
2092 if ((pcmu_cfg_stat
& (PCI_STAT_S_PERROR
| PCI_STAT_S_TARG_AB
|
2093 PCI_STAT_R_TARG_AB
| PCI_STAT_R_MAST_AB
|
2094 PCI_STAT_S_SYSERR
| PCI_STAT_PERROR
)) ||
2095 (PBM_AFSR_TO_PRIERR(pbm_afsr
))) {
2103 * Function used to gather PBM/PCI error state for the
2104 * pcmu_pbm_err_handler. This function must be called while pcmu_err_mutex
2108 pcmu_pbm_errstate_get(pcmu_t
*pcmu_p
, pcmu_pbm_errstate_t
*pbm_err_p
)
2110 pcmu_pbm_t
*pcbm_p
= pcmu_p
->pcmu_pcbm_p
;
2112 ASSERT(MUTEX_HELD(&pcmu_p
->pcmu_err_mutex
));
2113 bzero(pbm_err_p
, sizeof (pcmu_pbm_errstate_t
));
2116 * Capture all pbm error state for later logging
2118 pbm_err_p
->pbm_bridge_type
= PCI_OPLCMU
; /* RAGS */
2119 pbm_err_p
->pcbm_pci
.pcmu_cfg_stat
=
2120 pcbm_p
->pcbm_config_header
->ch_status_reg
;
2121 pbm_err_p
->pbm_ctl_stat
= *pcbm_p
->pcbm_ctrl_reg
;
2122 pbm_err_p
->pcbm_pci
.pcmu_cfg_comm
=
2123 pcbm_p
->pcbm_config_header
->ch_command_reg
;
2124 pbm_err_p
->pbm_afsr
= *pcbm_p
->pcbm_async_flt_status_reg
;
2125 pbm_err_p
->pbm_afar
= *pcbm_p
->pcbm_async_flt_addr_reg
;
2126 pbm_err_p
->pcbm_pci
.pcmu_pa
= *pcbm_p
->pcbm_async_flt_addr_reg
;
2130 pcmu_pbm_clear_error(pcmu_pbm_t
*pcbm_p
)
2135 * for poke() support - called from POKE_FLUSH. Spin waiting
2136 * for MA, TA or SERR to be cleared by a pcmu_pbm_error_intr().
2137 * We have to wait for SERR too in case the device is beyond
2140 pbm_afsr
= *pcbm_p
->pcbm_async_flt_status_reg
;
2141 while (((pbm_afsr
>> PCMU_PCI_AFSR_PE_SHIFT
) &
2142 (PCMU_PCI_AFSR_E_MA
| PCMU_PCI_AFSR_E_TA
))) {
2143 pbm_afsr
= *pcbm_p
->pcbm_async_flt_status_reg
;
2148 pcmu_err_create(pcmu_t
*pcmu_p
)
2151 * PCI detected ECC errorq, to schedule async handling
2152 * of ECC errors and logging.
2153 * The errorq is created here but destroyed when _fini is called
2154 * for the pci module.
2156 if (pcmu_ecc_queue
== NULL
) {
2157 pcmu_ecc_queue
= errorq_create("pcmu_ecc_queue",
2158 (errorq_func_t
)pcmu_ecc_err_drain
,
2160 ECC_MAX_ERRS
, sizeof (pcmu_ecc_errstate_t
),
2161 PIL_2
, ERRORQ_VITAL
);
2162 if (pcmu_ecc_queue
== NULL
)
2163 panic("failed to create required system error queue");
2167 * Initialize error handling mutex.
2169 mutex_init(&pcmu_p
->pcmu_err_mutex
, NULL
, MUTEX_DRIVER
,
2170 (void *)pcmu_p
->pcmu_fm_ibc
);
2174 pcmu_err_destroy(pcmu_t
*pcmu_p
)
2176 mutex_destroy(&pcmu_p
->pcmu_err_mutex
);
2180 * Function used to post PCI block module specific ereports.
2183 pcmu_pbm_ereport_post(dev_info_t
*dip
, uint64_t ena
,
2184 pcmu_pbm_errstate_t
*pbm_err
)
2187 uint32_t prierr
, secerr
;
2189 int instance
= ddi_get_instance(dip
);
2191 ena
= ena
? ena
: fm_ena_generate(0, FM_ENA_FMT1
);
2193 pcmu_p
= get_pcmu_soft_state(instance
);
2194 prierr
= PBM_AFSR_TO_PRIERR(pbm_err
->pbm_afsr
);
2195 secerr
= PBM_AFSR_TO_SECERR(pbm_err
->pbm_afsr
);
2197 aux_msg
= "PCI primary error: Master Abort";
2199 aux_msg
= "PCI secondary error: Master Abort";
2202 cmn_err(CE_WARN
, "%s %s: %s %s=0x%lx, %s=0x%lx, %s=0x%lx %s=0x%x",
2203 (pcmu_p
->pcmu_pcbm_p
)->pcbm_nameinst_str
,
2204 (pcmu_p
->pcmu_pcbm_p
)->pcbm_nameaddr_str
,
2206 PCI_PBM_AFAR
, pbm_err
->pbm_afar
,
2207 PCI_PBM_AFSR
, pbm_err
->pbm_afsr
,
2208 PCI_PBM_CSR
, pbm_err
->pbm_ctl_stat
,
2209 "portid", pcmu_p
->pcmu_id
);