xref: /titanic_41/usr/src/uts/sun4u/opl/io/mc-opl.c (revision 724365f7556fc4201fdb11766ebc6bd918523130)
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  * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
23  */
24 
25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 #include <sys/types.h>
28 #include <sys/sysmacros.h>
29 #include <sys/conf.h>
30 #include <sys/modctl.h>
31 #include <sys/stat.h>
32 #include <sys/async.h>
33 #include <sys/machsystm.h>
34 #include <sys/ksynch.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/ddifm.h>
38 #include <sys/fm/protocol.h>
39 #include <sys/fm/util.h>
40 #include <sys/kmem.h>
41 #include <sys/fm/io/opl_mc_fm.h>
42 #include <sys/memlist.h>
43 #include <sys/param.h>
44 #include <sys/ontrap.h>
45 #include <vm/page.h>
46 #include <sys/mc-opl.h>
47 
48 /*
49  * Function prototypes
50  */
51 static int mc_open(dev_t *, int, int, cred_t *);
52 static int mc_close(dev_t, int, int, cred_t *);
53 static int mc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
54 static int mc_attach(dev_info_t *, ddi_attach_cmd_t);
55 static int mc_detach(dev_info_t *, ddi_detach_cmd_t);
56 
57 static int mc_board_add(mc_opl_t *mcp);
58 static int mc_board_del(mc_opl_t *mcp);
59 static int mc_suspend(mc_opl_t *mcp, uint32_t flag);
60 static int mc_resume(mc_opl_t *mcp, uint32_t flag);
61 
62 static void insert_mcp(mc_opl_t *mcp);
63 static void delete_mcp(mc_opl_t *mcp);
64 
65 static int pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr);
66 
67 static int mc_valid_pa(mc_opl_t *mcp, uint64_t pa);
68 
69 int mc_get_mem_unum(int, uint64_t, char *, int, int *);
70 extern int plat_max_boards(void);
71 
72 static void mc_get_mlist(mc_opl_t *);
73 
74 #pragma weak opl_get_physical_board
75 extern int opl_get_physical_board(int);
76 static int mc_opl_get_physical_board(int);
77 
78 /*
79  * Configuration data structures
80  */
81 static struct cb_ops mc_cb_ops = {
82 	mc_open,			/* open */
83 	mc_close,			/* close */
84 	nulldev,			/* strategy */
85 	nulldev,			/* print */
86 	nodev,				/* dump */
87 	nulldev,			/* read */
88 	nulldev,			/* write */
89 	mc_ioctl,			/* ioctl */
90 	nodev,				/* devmap */
91 	nodev,				/* mmap */
92 	nodev,				/* segmap */
93 	nochpoll,			/* poll */
94 	ddi_prop_op,			/* cb_prop_op */
95 	0,				/* streamtab */
96 	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
97 	CB_REV,				/* rev */
98 	nodev,				/* cb_aread */
99 	nodev				/* cb_awrite */
100 };
101 
102 static struct dev_ops mc_ops = {
103 	DEVO_REV,			/* rev */
104 	0,				/* refcnt  */
105 	ddi_getinfo_1to1,		/* getinfo */
106 	nulldev,			/* identify */
107 	nulldev,			/* probe */
108 	mc_attach,			/* attach */
109 	mc_detach,			/* detach */
110 	nulldev,			/* reset */
111 	&mc_cb_ops,			/* cb_ops */
112 	(struct bus_ops *)0,		/* bus_ops */
113 	nulldev				/* power */
114 };
115 
116 /*
117  * Driver globals
118  */
119 int mc_patrol_interval_sec = 10;
120 
121 int inject_op_delay = 5;
122 
123 mc_inst_list_t *mc_instances;
124 static kmutex_t mcmutex;
125 
126 void *mc_statep;
127 
128 #ifdef	DEBUG
129 int oplmc_debug = 0;
130 #endif
131 
132 static int mc_debug_show_all;
133 
134 extern struct mod_ops mod_driverops;
135 
136 static struct modldrv modldrv = {
137 	&mod_driverops,			/* module type, this one is a driver */
138 	"OPL Memory-controller 1.1",	/* module name */
139 	&mc_ops,			/* driver ops */
140 };
141 
142 static struct modlinkage modlinkage = {
143 	MODREV_1,		/* rev */
144 	(void *)&modldrv,
145 	NULL
146 };
147 
148 #pragma weak opl_get_mem_unum
149 extern int (*opl_get_mem_unum)(int, uint64_t, char *, int, int *);
150 
151 /*
152  * pseudo-mc node portid format
153  *
154  *		[10]   = 0
155  *		[9]    = 1
156  *		[8]    = LSB_ID[4] = 0
157  *		[7:4]  = LSB_ID[3:0]
158  *		[3:0]  = 0
159  *
160  */
161 
162 /*
163  * These are the module initialization routines.
164  */
165 int
166 _init(void)
167 {
168 	int error;
169 
170 
171 	if ((error = ddi_soft_state_init(&mc_statep,
172 	    sizeof (mc_opl_t), 1)) != 0)
173 		return (error);
174 
175 	mutex_init(&mcmutex, NULL, MUTEX_DRIVER, NULL);
176 	if (&opl_get_mem_unum)
177 		opl_get_mem_unum = mc_get_mem_unum;
178 
179 	error =  mod_install(&modlinkage);
180 	if (error != 0) {
181 		if (&opl_get_mem_unum)
182 			opl_get_mem_unum = NULL;
183 		mutex_destroy(&mcmutex);
184 		ddi_soft_state_fini(&mc_statep);
185 	}
186 
187 	return (error);
188 }
189 
190 int
191 _fini(void)
192 {
193 	int error;
194 
195 	if ((error = mod_remove(&modlinkage)) != 0)
196 		return (error);
197 
198 	mutex_destroy(&mcmutex);
199 
200 	if (&opl_get_mem_unum)
201 		opl_get_mem_unum = NULL;
202 
203 	ddi_soft_state_fini(&mc_statep);
204 
205 	return (0);
206 }
207 
208 int
209 _info(struct modinfo *modinfop)
210 {
211 	return (mod_info(&modlinkage, modinfop));
212 }
213 
214 static int
215 mc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
216 {
217 	mc_opl_t *mcp;
218 	int instance;
219 
220 	/* get the instance of this devi */
221 	instance = ddi_get_instance(devi);
222 
223 	switch (cmd) {
224 	case DDI_ATTACH:
225 		break;
226 	case DDI_RESUME:
227 		mcp = ddi_get_soft_state(mc_statep, instance);
228 		return (mc_resume(mcp, MC_DRIVER_SUSPENDED));
229 	default:
230 		return (DDI_FAILURE);
231 	}
232 
233 
234 	if (ddi_soft_state_zalloc(mc_statep, instance) != DDI_SUCCESS)
235 		return (DDI_FAILURE);
236 
237 	if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
238 		goto bad;
239 	}
240 
241 	/* set informations in mc state */
242 	mcp->mc_dip = devi;
243 
244 	if (mc_board_add(mcp))
245 		goto bad;
246 
247 	insert_mcp(mcp);
248 	ddi_report_dev(devi);
249 
250 	return (DDI_SUCCESS);
251 
252 bad:
253 	ddi_soft_state_free(mc_statep, instance);
254 	return (DDI_FAILURE);
255 }
256 
257 /* ARGSUSED */
258 static int
259 mc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
260 {
261 	int instance;
262 	mc_opl_t *mcp;
263 
264 	/* get the instance of this devi */
265 	instance = ddi_get_instance(devi);
266 	if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
267 		return (DDI_FAILURE);
268 	}
269 
270 	switch (cmd) {
271 	case DDI_SUSPEND:
272 		return (mc_suspend(mcp, MC_DRIVER_SUSPENDED));
273 	case DDI_DETACH:
274 		break;
275 	default:
276 		return (DDI_FAILURE);
277 	}
278 
279 	mutex_enter(&mcmutex);
280 	if (mc_board_del(mcp) != DDI_SUCCESS) {
281 		mutex_exit(&mcmutex);
282 		return (DDI_FAILURE);
283 	}
284 
285 	delete_mcp(mcp);
286 	mutex_exit(&mcmutex);
287 
288 	/* free up the soft state */
289 	ddi_soft_state_free(mc_statep, instance);
290 
291 	return (DDI_SUCCESS);
292 }
293 
294 /* ARGSUSED */
295 static int
296 mc_open(dev_t *devp, int flag, int otyp, cred_t *credp)
297 {
298 	return (0);
299 }
300 
301 /* ARGSUSED */
302 static int
303 mc_close(dev_t devp, int flag, int otyp, cred_t *credp)
304 {
305 	return (0);
306 }
307 
308 /* ARGSUSED */
309 static int
310 mc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
311 	int *rvalp)
312 {
313 	return (ENXIO);
314 }
315 
316 /*
317  * PA validity check:
318  * This function return 1 if the PA is valid, otherwise
319  * return 0.
320  */
321 
322 /* ARGSUSED */
323 static int
324 pa_is_valid(mc_opl_t *mcp, uint64_t addr)
325 {
326 	/*
327 	 * Check if the addr is on the board.
328 	 */
329 	if ((addr < mcp->mc_start_address) ||
330 	    (mcp->mc_start_address + mcp->mc_size <= addr))
331 		return (0);
332 
333 	if (mcp->mlist == NULL)
334 		mc_get_mlist(mcp);
335 
336 	if (mcp->mlist && address_in_memlist(mcp->mlist, addr, 0)) {
337 		return (1);
338 	}
339 	return (0);
340 }
341 
342 /*
343  * mac-pa translation routines.
344  *
345  *    Input: mc driver state, (LSB#, Bank#, DIMM address)
346  *    Output: physical address
347  *
348  *    Valid   - return value:  0
349  *    Invalid - return value: -1
350  */
351 static int
352 mcaddr_to_pa(mc_opl_t *mcp, mc_addr_t *maddr, uint64_t *pa)
353 {
354 	int i;
355 	uint64_t pa_offset = 0;
356 	int cs = (maddr->ma_dimm_addr >> CS_SHIFT) & 1;
357 	int bank = maddr->ma_bank;
358 	mc_addr_t maddr1;
359 	int bank0, bank1;
360 
361 	MC_LOG("mcaddr /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
362 		maddr->ma_dimm_addr);
363 
364 	/* loc validity check */
365 	ASSERT(maddr->ma_bd >= 0 && OPL_BOARD_MAX > maddr->ma_bd);
366 	ASSERT(bank >= 0 && OPL_BANK_MAX > bank);
367 
368 	/* Do translation */
369 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
370 		int pa_bit = 0;
371 		int mc_bit = mcp->mc_trans_table[cs][i];
372 		if (mc_bit < MC_ADDRESS_BITS) {
373 			pa_bit = (maddr->ma_dimm_addr >> mc_bit) & 1;
374 		} else if (mc_bit == MP_NONE) {
375 			pa_bit = 0;
376 		} else if (mc_bit == MP_BANK_0) {
377 			pa_bit = bank & 1;
378 		} else if (mc_bit == MP_BANK_1) {
379 			pa_bit = (bank >> 1) & 1;
380 		} else if (mc_bit == MP_BANK_2) {
381 			pa_bit = (bank >> 2) & 1;
382 		}
383 		pa_offset |= ((uint64_t)pa_bit) << i;
384 	}
385 	*pa = mcp->mc_start_address + pa_offset;
386 	MC_LOG("pa = %lx\n", *pa);
387 
388 	if (pa_to_maddr(mcp, *pa, &maddr1) == -1) {
389 		return (-1);
390 	}
391 
392 
393 	if (IS_MIRROR(mcp, maddr->ma_bank)) {
394 		bank0 = maddr->ma_bank & ~(1);
395 		bank1 = maddr1.ma_bank & ~(1);
396 	} else {
397 		bank0 = maddr->ma_bank;
398 		bank1 = maddr1.ma_bank;
399 	}
400 	/*
401 	 * there is no need to check ma_bd because it is generated from
402 	 * mcp.  They are the same.
403 	 */
404 	if ((bank0 == bank1) &&
405 		(maddr->ma_dimm_addr == maddr1.ma_dimm_addr)) {
406 		return (0);
407 	} else {
408 		cmn_err(CE_WARN, "Translation error source /LSB%d/B%d/%x, "
409 			"PA %lx, target /LSB%d/B%d/%x\n",
410 			maddr->ma_bd, bank, maddr->ma_dimm_addr,
411 			*pa, maddr1.ma_bd, maddr1.ma_bank,
412 			maddr1.ma_dimm_addr);
413 		return (-1);
414 	}
415 }
416 
417 /*
418  * PA to CS (used by pa_to_maddr).
419  */
420 static int
421 pa_to_cs(mc_opl_t *mcp, uint64_t pa_offset)
422 {
423 	int i;
424 	int cs = 0;
425 
426 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
427 		/* MAC address bit<29> is arranged on the same PA bit */
428 		/* on both table. So we may use any table. */
429 		if (mcp->mc_trans_table[0][i] == CS_SHIFT) {
430 			cs = (pa_offset >> i) & 1;
431 			break;
432 		}
433 	}
434 	return (cs);
435 }
436 
437 /*
438  * PA to DIMM (used by pa_to_maddr).
439  */
440 /* ARGSUSED */
441 static uint32_t
442 pa_to_dimm(mc_opl_t *mcp, uint64_t pa_offset)
443 {
444 	int i;
445 	int cs = pa_to_cs(mcp, pa_offset);
446 	uint32_t dimm_addr = 0;
447 
448 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
449 		int pa_bit_value = (pa_offset >> i) & 1;
450 		int mc_bit = mcp->mc_trans_table[cs][i];
451 		if (mc_bit < MC_ADDRESS_BITS) {
452 			dimm_addr |= pa_bit_value << mc_bit;
453 		}
454 	}
455 	return (dimm_addr);
456 }
457 
458 /*
459  * PA to Bank (used by pa_to_maddr).
460  */
461 static int
462 pa_to_bank(mc_opl_t *mcp, uint64_t pa_offset)
463 {
464 	int i;
465 	int cs = pa_to_cs(mcp, pa_offset);
466 	int bankno = mcp->mc_trans_table[cs][INDEX_OF_BANK_SUPPLEMENT_BIT];
467 
468 
469 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
470 		int pa_bit_value = (pa_offset >> i) & 1;
471 		int mc_bit = mcp->mc_trans_table[cs][i];
472 		switch (mc_bit) {
473 		case MP_BANK_0:
474 			bankno |= pa_bit_value;
475 			break;
476 		case MP_BANK_1:
477 			bankno |= pa_bit_value << 1;
478 			break;
479 		case MP_BANK_2:
480 			bankno |= pa_bit_value << 2;
481 			break;
482 		}
483 	}
484 
485 	return (bankno);
486 }
487 
488 /*
489  * PA to MAC address translation
490  *
491  *   Input: MAC driver state, physicall adress
492  *   Output: LSB#, Bank id, mac address
493  *
494  *    Valid   - return value:  0
495  *    Invalid - return value: -1
496  */
497 
498 int
499 pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr)
500 {
501 	uint64_t pa_offset;
502 
503 	/* PA validity check */
504 	if (!pa_is_valid(mcp, pa))
505 		return (-1);
506 
507 
508 	/* Do translation */
509 	pa_offset = pa - mcp->mc_start_address;
510 
511 	maddr->ma_bd = mcp->mc_board_num;
512 	maddr->ma_bank = pa_to_bank(mcp, pa_offset);
513 	maddr->ma_dimm_addr = pa_to_dimm(mcp, pa_offset);
514 	MC_LOG("pa %lx -> mcaddr /LSB%d/B%d/%x\n",
515 		pa_offset, maddr->ma_bd, maddr->ma_bank, maddr->ma_dimm_addr);
516 	return (0);
517 }
518 
519 static void
520 mc_ereport_post(mc_aflt_t *mc_aflt)
521 {
522 	char buf[FM_MAX_CLASS];
523 	char device_path[MAXPATHLEN];
524 	nv_alloc_t *nva = NULL;
525 	nvlist_t *ereport, *detector, *resource;
526 	errorq_elem_t *eqep;
527 	int nflts;
528 	mc_flt_stat_t *flt_stat;
529 	int i, n, blen;
530 	char *p;
531 	uint32_t values[2], synd[2], dslot[2];
532 
533 	if (panicstr) {
534 		eqep = errorq_reserve(ereport_errorq);
535 		if (eqep == NULL)
536 			return;
537 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
538 		nva = errorq_elem_nva(ereport_errorq, eqep);
539 	} else {
540 		ereport = fm_nvlist_create(nva);
541 	}
542 
543 	/*
544 	 * Create the scheme "dev" FMRI.
545 	 */
546 	detector = fm_nvlist_create(nva);
547 	resource = fm_nvlist_create(nva);
548 
549 	nflts = mc_aflt->mflt_nflts;
550 
551 	ASSERT(nflts >= 1 && nflts <= 2);
552 
553 	flt_stat = mc_aflt->mflt_stat[0];
554 	(void) ddi_pathname(mc_aflt->mflt_mcp->mc_dip, device_path);
555 	(void) fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
556 	    device_path, NULL);
557 
558 	/*
559 	 * Encode all the common data into the ereport.
560 	 */
561 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
562 		MC_OPL_ERROR_CLASS,
563 		mc_aflt->mflt_is_ptrl ? MC_OPL_PTRL_SUBCLASS :
564 		MC_OPL_MI_SUBCLASS,
565 		mc_aflt->mflt_erpt_class);
566 
567 	MC_LOG("mc_ereport_post: ereport %s\n", buf);
568 
569 
570 	fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
571 		fm_ena_generate(mc_aflt->mflt_id, FM_ENA_FMT1),
572 		detector, NULL);
573 
574 	/*
575 	 * Set payload.
576 	 */
577 	fm_payload_set(ereport, MC_OPL_BOARD, DATA_TYPE_UINT32,
578 		flt_stat->mf_flt_maddr.ma_bd, NULL);
579 
580 	fm_payload_set(ereport, MC_OPL_PA, DATA_TYPE_UINT64,
581 		flt_stat->mf_flt_paddr, NULL);
582 
583 	if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
584 		fm_payload_set(ereport, MC_OPL_FLT_TYPE,
585 			DATA_TYPE_UINT8, ECC_STICKY, NULL);
586 	}
587 
588 	for (i = 0; i < nflts; i++)
589 		values[i] = mc_aflt->mflt_stat[i]->mf_flt_maddr.ma_bank;
590 
591 	fm_payload_set(ereport, MC_OPL_BANK, DATA_TYPE_UINT32_ARRAY,
592 		nflts, values, NULL);
593 
594 	for (i = 0; i < nflts; i++)
595 		values[i] = mc_aflt->mflt_stat[i]->mf_cntl;
596 
597 	fm_payload_set(ereport, MC_OPL_STATUS, DATA_TYPE_UINT32_ARRAY,
598 		nflts, values, NULL);
599 
600 	for (i = 0; i < nflts; i++)
601 		values[i] = mc_aflt->mflt_stat[i]->mf_err_add;
602 
603 	fm_payload_set(ereport, MC_OPL_ERR_ADD, DATA_TYPE_UINT32_ARRAY,
604 		nflts, values, NULL);
605 
606 	for (i = 0; i < nflts; i++)
607 		values[i] = mc_aflt->mflt_stat[i]->mf_err_log;
608 
609 	fm_payload_set(ereport, MC_OPL_ERR_LOG, DATA_TYPE_UINT32_ARRAY,
610 		nflts, values, NULL);
611 
612 	for (i = 0; i < nflts; i++) {
613 		flt_stat = mc_aflt->mflt_stat[i];
614 		if (flt_stat->mf_errlog_valid) {
615 			synd[i] = flt_stat->mf_synd;
616 			dslot[i] = flt_stat->mf_dimm_slot;
617 			values[i] = flt_stat->mf_dram_place;
618 		} else {
619 			synd[i] = 0;
620 			dslot[i] = 0;
621 			values[i] = 0;
622 		}
623 	}
624 
625 	fm_payload_set(ereport, MC_OPL_ERR_SYND,
626 		DATA_TYPE_UINT32_ARRAY, nflts, synd, NULL);
627 
628 	fm_payload_set(ereport, MC_OPL_ERR_DIMMSLOT,
629 		DATA_TYPE_UINT32_ARRAY, nflts, dslot, NULL);
630 
631 	fm_payload_set(ereport, MC_OPL_ERR_DRAM,
632 		DATA_TYPE_UINT32_ARRAY, nflts, values, NULL);
633 
634 	blen = MAXPATHLEN;
635 	device_path[0] = 0;
636 	p = &device_path[0];
637 
638 	for (i = 0; i < nflts; i++) {
639 		int bank = flt_stat->mf_flt_maddr.ma_bank;
640 		int psb = -1;
641 
642 		flt_stat = mc_aflt->mflt_stat[i];
643 		psb = mc_opl_get_physical_board(
644 		    flt_stat->mf_flt_maddr.ma_bd);
645 
646 		if (psb != -1) {
647 			snprintf(p, blen, "/CMU%d/B%d", psb, bank);
648 		} else {
649 			snprintf(p, blen, "/CMU/B%d", bank);
650 		}
651 
652 		if (flt_stat->mf_errlog_valid) {
653 			snprintf(p + strlen(p), blen, "/MEM%d%d%c",
654 			    bank/2, (bank & 0x1) * 2 + dslot[i] & 1,
655 			    (dslot[i] & 0x2) ? 'B' : 'A');
656 		}
657 
658 		n = strlen(&device_path[0]);
659 		blen = MAXPATHLEN - n;
660 		p = &device_path[n];
661 		if (i < (nflts - 1)) {
662 			snprintf(p, blen, " ");
663 			n += 1; blen -= 1; p += 1;
664 		}
665 	}
666 
667 	/*
668 	 * UNUM format /LSB#/B#/MEMxyZ
669 	 * where x is the MAC# = Bank#/2
670 	 * y is slot info = (Bank# & 0x1)*2 + {0, 1} 0 for DIMM-L, 1 for DIMM-H
671 	 * DIMM-L is 0 in bit 13, DIMM-H is 1 in bit 13.
672 	 * Z is A(CS0) or B(CS1) given by bit 14
673 	 */
674 	(void) fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION,
675 		NULL, device_path, NULL, 0);
676 
677 	fm_payload_set(ereport, MC_OPL_RESOURCE, DATA_TYPE_NVLIST,
678 		resource, NULL);
679 
680 	if (panicstr) {
681 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
682 	} else {
683 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
684 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
685 		fm_nvlist_destroy(detector, FM_NVA_FREE);
686 		fm_nvlist_destroy(resource, FM_NVA_FREE);
687 	}
688 }
689 
690 static void
691 mc_err_drain(mc_aflt_t *mc_aflt)
692 {
693 	int rv;
694 	page_t *pp;
695 	uint64_t errors;
696 	uint64_t pa = (uint64_t)(-1);
697 
698 	MC_LOG("mc_err_drain: %s\n",
699 		mc_aflt->mflt_erpt_class);
700 	/*
701 	 * we come here only when we have:
702 	 * In mirror mode: CMPE, MUE, SUE
703 	 * In normal mode: UE, Permanent CE
704 	 */
705 	rv = mcaddr_to_pa(mc_aflt->mflt_mcp,
706 		&(mc_aflt->mflt_stat[0]->mf_flt_maddr), &pa);
707 	if (rv == 0)
708 		mc_aflt->mflt_stat[0]->mf_flt_paddr = pa;
709 	else
710 		mc_aflt->mflt_stat[0]->mf_flt_paddr = (uint64_t)-1;
711 	if (rv == 0) {
712 		MC_LOG("mc_err_drain:pa = %lx\n", pa);
713 		pp = page_numtopp_nolock(pa >> PAGESHIFT);
714 
715 		if (pp) {
716 			/*
717 			 * Don't keep retiring and make ereports
718 			 * on bad pages in PTRL case
719 			 */
720 			MC_LOG("mc_err_drain:pp = %p\n", pp);
721 			if (mc_aflt->mflt_is_ptrl) {
722 				errors = 0;
723 				if (page_retire_check(pa, &errors) == 0) {
724 					MC_LOG("Page retired\n");
725 					return;
726 				}
727 				if (errors & mc_aflt->mflt_pr) {
728 					MC_LOG("errors %lx, mflt_pr %x\n",
729 						errors, mc_aflt->mflt_pr);
730 					return;
731 				}
732 			}
733 			MC_LOG("offline page %p error %x\n", pp,
734 				mc_aflt->mflt_pr);
735 			(void) page_retire(pa, mc_aflt->mflt_pr);
736 		}
737 	}
738 	mc_ereport_post(mc_aflt);
739 }
740 
741 #define	DIMM_SIZE 0x80000000
742 
743 #define	INC_DIMM_ADDR(p, n) \
744 	(p)->ma_dimm_addr += n; \
745 	(p)->ma_dimm_addr &= (DIMM_SIZE - 1)
746 
747 /*
748  * The restart address is actually defined in unit of PA[37:6]
749  * the mac patrol will convert that to dimm offset.  If the
750  * address is not in the bank, it will continue to search for
751  * the next PA that is within the bank.
752  *
753  * Also the mac patrol scans the dimms based on PA, not
754  * dimm offset.
755  */
756 
757 static int
758 restart_patrol(mc_opl_t *mcp, int bank, mc_addr_info_t *maddr_info)
759 {
760 	page_t *pp;
761 	uint32_t reg;
762 	uint64_t pa;
763 	int rv;
764 	int loop_count = 0;
765 
766 	reg = ldphysio(MAC_PTRL_CNTL(mcp, bank));
767 
768 	/* already running, so we just return */
769 	if (reg & MAC_CNTL_PTRL_START)
770 		return (0);
771 
772 	if (maddr_info == NULL || (maddr_info->mi_valid == 0)) {
773 		MAC_PTRL_START(mcp, bank);
774 		return (0);
775 	}
776 
777 
778 	rv = mcaddr_to_pa(mcp, &maddr_info->mi_maddr, &pa);
779 	if (rv != 0) {
780 		MC_LOG("cannot convert mcaddr to pa. use auto restart\n");
781 		MAC_PTRL_START(mcp, bank);
782 		return (0);
783 	}
784 
785 	/*
786 	 * pa is the last address scanned by the mac patrol
787 	 * we  calculate the next restart address as follows:
788 	 * first we always advance it by 64 byte. Then begin the loop.
789 	 * loop {
790 	 * if it is not in phys_install, we advance to next 64 MB boundary
791 	 * if it is not backed by a page structure, done
792 	 * if the page is bad, advance to the next page boundary.
793 	 * else done
794 	 * if the new address exceeds the board, wrap around.
795 	 * } <stop if we come back to the same page>
796 	 */
797 
798 	if (pa < mcp->mc_start_address || pa >= (mcp->mc_start_address
799 		+ mcp->mc_size)) {
800 		/* pa is not on this board, just retry */
801 		cmn_err(CE_WARN, "restart_patrol: invalid address %lx "
802 			"on board %d\n", pa, mcp->mc_board_num);
803 		MAC_PTRL_START(mcp, bank);
804 		return (0);
805 	}
806 
807 	MC_LOG("restart_patrol: pa = %lx\n", pa);
808 	if (maddr_info->mi_advance) {
809 		uint64_t new_pa;
810 
811 		if (IS_MIRROR(mcp, bank))
812 			new_pa = pa + 64 * 2;
813 		else
814 			new_pa = pa + 64;
815 
816 		if (!mc_valid_pa(mcp, new_pa)) {
817 			/* Isolation unit size is 64 MB */
818 #define	MC_ISOLATION_BSIZE	(64 * 1024 * 1024)
819 			MC_LOG("Invalid PA\n");
820 			pa = roundup(new_pa + 1, MC_ISOLATION_BSIZE);
821 		} else {
822 			pp = page_numtopp_nolock(new_pa >> PAGESHIFT);
823 			if (pp != NULL) {
824 				uint64_t errors = 0;
825 				if (page_retire_check(new_pa, &errors) &&
826 					(errors == 0)) {
827 					MC_LOG("Page has no error\n");
828 					MAC_PTRL_START(mcp, bank);
829 					return (0);
830 				}
831 				/*
832 				 * skip bad pages
833 				 * and let the following loop to take care
834 				 */
835 				pa = roundup(new_pa + 1, PAGESIZE);
836 				MC_LOG("Skipping bad page to %lx\n", pa);
837 			} else {
838 				MC_LOG("Page has no page structure\n");
839 				MAC_PTRL_START(mcp, bank);
840 				return (0);
841 			}
842 		}
843 	}
844 
845 	/*
846 	 * if we wrap around twice, we just give up and let
847 	 * mac patrol decide.
848 	 */
849 	MC_LOG("pa is now %lx\n", pa);
850 	while (loop_count <= 1) {
851 		if (!mc_valid_pa(mcp, pa)) {
852 			MC_LOG("pa is not valid. round up to 64 MB\n");
853 			pa = roundup(pa + 1, 64 * 1024 * 1024);
854 		} else {
855 			pp = page_numtopp_nolock(pa >> PAGESHIFT);
856 			if (pp != NULL) {
857 				uint64_t errors = 0;
858 				if (page_retire_check(pa, &errors) &&
859 					(errors == 0)) {
860 					MC_LOG("Page has no error\n");
861 					break;
862 				}
863 				/* skip bad pages */
864 				pa = roundup(pa + 1, PAGESIZE);
865 				MC_LOG("Skipping bad page to %lx\n", pa);
866 			} else {
867 				MC_LOG("Page has no page structure\n");
868 				break;
869 			}
870 		}
871 		if (pa >= (mcp->mc_start_address + mcp->mc_size)) {
872 			MC_LOG("Wrap around\n");
873 			pa = mcp->mc_start_address;
874 			loop_count++;
875 		}
876 	}
877 
878 	/* retstart MAC patrol: PA[37:6] */
879 	MC_LOG("restart at pa = %lx\n", pa);
880 	ST_MAC_REG(MAC_RESTART_ADD(mcp, bank), MAC_RESTART_PA(pa));
881 	MAC_PTRL_START_ADD(mcp, bank);
882 
883 	return (0);
884 }
885 
886 /*
887  * Rewriting is used for two purposes.
888  *  - to correct the error in memory.
889  *  - to determine whether the error is permanent or intermittent.
890  * It's done by writing the address in MAC_BANKm_REWRITE_ADD
891  * and issuing REW_REQ command in MAC_BANKm_PTRL_CNRL. After that,
892  * REW_END (and REW_CE/REW_UE if some error detected) is set when
893  * rewrite operation is done. See 4.7.3 and 4.7.11 in Columbus2 PRM.
894  *
895  * Note that rewrite operation doesn't change RAW_UE to Marked UE.
896  * Therefore, we use it only CE case.
897  */
898 static uint32_t
899 do_rewrite(mc_opl_t *mcp, int bank, uint32_t dimm_addr)
900 {
901 	uint32_t cntl;
902 	int count = 0;
903 
904 	/* first wait to make sure PTRL_STATUS is 0 */
905 	while (count++ < MAX_MC_LOOP_COUNT) {
906 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
907 		if (!(cntl & MAC_CNTL_PTRL_STATUS))
908 			break;
909 		delay(drv_usectohz(10 * 1000));	/* 10 m.s. */
910 	}
911 	if (count >= MAX_MC_LOOP_COUNT)
912 		goto bad;
913 
914 	count = 0;
915 
916 	ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), dimm_addr);
917 	MAC_REW_REQ(mcp, bank);
918 
919 	do {
920 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
921 		if (count++ >= MAX_MC_LOOP_COUNT) {
922 			goto bad;
923 		} else
924 			delay(drv_usectohz(10 * 1000));	/* 10 m.s. */
925 	/*
926 	 * If there are other MEMORY or PCI activities, this
927 	 * will be BUSY, else it should be set immediately
928 	 */
929 	} while (!(cntl & MAC_CNTL_REW_END));
930 
931 	MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
932 	return (cntl);
933 bad:
934 	/* This is bad.  Just reset the circuit */
935 	cmn_err(CE_WARN, "mc-opl rewrite timeout on /LSB%d/B%d\n",
936 		mcp->mc_board_num, bank);
937 	cntl = MAC_CNTL_REW_END;
938 	MAC_CMD(mcp, bank, MAC_CNTL_PTRL_RESET);
939 	MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
940 	return (cntl);
941 }
942 
943 void
944 mc_process_scf_log(mc_opl_t *mcp)
945 {
946 	int count = 0;
947 	scf_log_t *p;
948 	int bank;
949 
950 	while ((p = mcp->mc_scf_log) != NULL) {
951 		bank = p->sl_bank;
952 		while ((LD_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank))
953 			& MAC_STATIC_ERR_VLD)) {
954 			if (count++ >= (MAX_MC_LOOP_COUNT)) {
955 				break;
956 			}
957 			delay(drv_usectohz(10 * 1000));	/* 10 m.s. */
958 		}
959 
960 		if (count < MAX_MC_LOOP_COUNT) {
961 			ST_MAC_REG(MAC_STATIC_ERR_LOG(mcp, p->sl_bank),
962 				p->sl_err_log);
963 
964 			ST_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank),
965 				p->sl_err_add|MAC_STATIC_ERR_VLD);
966 			mcp->mc_scf_retry[bank] = 0;
967 		} else {
968 			/* if we try too many times, just drop the req */
969 			if (mcp->mc_scf_retry[bank]++ <= MAX_SCF_RETRY) {
970 				return;
971 			} else {
972 				cmn_err(CE_WARN, "SCF is not responding. "
973 					"Dropping the SCF LOG\n");
974 			}
975 		}
976 		mcp->mc_scf_log = p->sl_next;
977 		mcp->mc_scf_total--;
978 		ASSERT(mcp->mc_scf_total >= 0);
979 		kmem_free(p, sizeof (scf_log_t));
980 	}
981 }
982 
983 void
984 mc_queue_scf_log(mc_opl_t *mcp, mc_flt_stat_t *flt_stat, int bank)
985 {
986 	scf_log_t *p;
987 
988 	if (mcp->mc_scf_total >= MAX_SCF_LOGS) {
989 		cmn_err(CE_WARN,
990 			"Max# SCF logs excceded on /LSB%d/B%d\n",
991 			mcp->mc_board_num, bank);
992 		return;
993 	}
994 	p = kmem_zalloc(sizeof (scf_log_t), KM_SLEEP);
995 	p->sl_next = 0;
996 	p->sl_err_add = flt_stat->mf_err_add;
997 	p->sl_err_log = flt_stat->mf_err_log;
998 	p->sl_bank = bank;
999 
1000 	if (mcp->mc_scf_log == NULL) {
1001 		/*
1002 		 * we rely on mc_scf_log to detect NULL queue.
1003 		 * mc_scf_log_tail is irrelevant is such case.
1004 		 */
1005 		mcp->mc_scf_log_tail = mcp->mc_scf_log = p;
1006 	} else {
1007 		mcp->mc_scf_log_tail->sl_next = p;
1008 		mcp->mc_scf_log_tail = p;
1009 	}
1010 	mcp->mc_scf_total++;
1011 }
1012 
1013 /*
1014  * This routine determines what kind of CE happens, intermittent
1015  * or permanent as follows. (See 4.7.3 in Columbus2 PRM.)
1016  * - Do rewrite by issuing REW_REQ command to MAC_PTRL_CNTL register.
1017  * - If CE is still detected on the same address even after doing
1018  *   rewrite operation twice, it is determined as permanent error.
1019  * - If error is not detected anymore, it is determined as intermittent
1020  *   error.
1021  * - If UE is detected due to rewrite operation, it should be treated
1022  *   as UE.
1023  */
1024 
1025 /* ARGSUSED */
1026 static void
1027 mc_scrub_ce(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat, int ptrl_error)
1028 {
1029 	uint32_t cntl;
1030 	int i;
1031 
1032 	flt_stat->mf_type = FLT_TYPE_PERMANENT_CE;
1033 	/*
1034 	 * rewrite request 1st time reads and correct error data
1035 	 * and write to DIMM.  2nd rewrite request must be issued
1036 	 * after REW_CE/UE/END is 0.  When the 2nd request is completed,
1037 	 * if REW_CE = 1, then it is permanent CE.
1038 	 */
1039 	for (i = 0; i < 2; i++) {
1040 		cntl = do_rewrite(mcp, bank, flt_stat->mf_err_add);
1041 		/*
1042 		 * If the error becomes UE or CMPE
1043 		 * we return to the caller immediately.
1044 		 */
1045 		if (cntl & MAC_CNTL_REW_UE) {
1046 			if (ptrl_error)
1047 				flt_stat->mf_cntl |= MAC_CNTL_PTRL_UE;
1048 			else
1049 				flt_stat->mf_cntl |= MAC_CNTL_MI_UE;
1050 			flt_stat->mf_type = FLT_TYPE_UE;
1051 			return;
1052 		}
1053 		if (cntl & MAC_CNTL_REW_CMPE) {
1054 			if (ptrl_error)
1055 				flt_stat->mf_cntl |= MAC_CNTL_PTRL_CMPE;
1056 			else
1057 				flt_stat->mf_cntl |= MAC_CNTL_MI_CMPE;
1058 			flt_stat->mf_type = FLT_TYPE_CMPE;
1059 			return;
1060 		}
1061 	}
1062 	if (!(cntl & MAC_CNTL_REW_CE)) {
1063 		flt_stat->mf_type = FLT_TYPE_INTERMITTENT_CE;
1064 	}
1065 
1066 	if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
1067 		/* report PERMANENT_CE to SP via SCF */
1068 		if (!(flt_stat->mf_err_log & MAC_ERR_LOG_INVALID)) {
1069 			mc_queue_scf_log(mcp, flt_stat, bank);
1070 		}
1071 	}
1072 }
1073 
1074 #define	IS_CMPE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_CMPE :\
1075 				MAC_CNTL_MI_CMPE))
1076 #define	IS_UE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_UE : MAC_CNTL_MI_UE))
1077 #define	IS_CE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_CE : MAC_CNTL_MI_CE))
1078 #define	IS_OK(cntl, f)	(!((cntl) & ((f) ? MAC_CNTL_PTRL_ERRS : \
1079 			MAC_CNTL_MI_ERRS)))
1080 
1081 
1082 static int
1083 IS_CE_ONLY(uint32_t cntl, int ptrl_error)
1084 {
1085 	if (ptrl_error) {
1086 		return ((cntl & MAC_CNTL_PTRL_ERRS) == MAC_CNTL_PTRL_CE);
1087 	} else {
1088 		return ((cntl & MAC_CNTL_MI_ERRS) == MAC_CNTL_MI_CE);
1089 	}
1090 }
1091 
1092 void
1093 mc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
1094 {
1095 	value |= mcp->mc_bank[bank].mcb_ptrl_cntl;
1096 	ST_MAC_REG(MAC_PTRL_CNTL(mcp, bank), value);
1097 }
1098 
1099 static int
1100 mc_stop(mc_opl_t *mcp, int bank)
1101 {
1102 	uint32_t reg;
1103 	int count = 0;
1104 
1105 	reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1106 
1107 	if (reg & MAC_CNTL_PTRL_START)
1108 		MAC_PTRL_STOP(mcp, bank);
1109 
1110 	while (count++ <= MAX_MC_LOOP_COUNT) {
1111 		reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1112 		if ((reg & MAC_CNTL_PTRL_STATUS) == 0)
1113 			return (0);
1114 		delay(drv_usectohz(10 * 1000));	/* 10 m.s. */
1115 	}
1116 	return (-1);
1117 }
1118 
1119 static void
1120 mc_read_ptrl_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1121 {
1122 	flt_stat->mf_cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1123 		MAC_CNTL_PTRL_ERRS;
1124 	flt_stat->mf_err_add = LD_MAC_REG(MAC_PTRL_ERR_ADD(mcp, bank));
1125 	flt_stat->mf_err_log = LD_MAC_REG(MAC_PTRL_ERR_LOG(mcp, bank));
1126 	flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1127 	flt_stat->mf_flt_maddr.ma_bank = bank;
1128 	flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1129 }
1130 
1131 static void
1132 mc_read_mi_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1133 {
1134 	uint32_t status, old_status;
1135 
1136 	status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1137 		MAC_CNTL_MI_ERRS;
1138 	old_status = 0;
1139 
1140 	/* we keep reading until the status is stable */
1141 	while (old_status != status) {
1142 		old_status = status;
1143 		flt_stat->mf_err_add =
1144 			LD_MAC_REG(MAC_MI_ERR_ADD(mcp, bank));
1145 		flt_stat->mf_err_log =
1146 			LD_MAC_REG(MAC_MI_ERR_LOG(mcp, bank));
1147 		status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1148 			MAC_CNTL_MI_ERRS;
1149 		if (status == old_status) {
1150 			break;
1151 		}
1152 	}
1153 
1154 	flt_stat->mf_cntl = status;
1155 	flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1156 	flt_stat->mf_flt_maddr.ma_bank = bank;
1157 	flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1158 }
1159 
1160 
1161 /*
1162  * Error philosophy for mirror mode:
1163  *
1164  * PTRL (The error address for both banks are same, since ptrl stops if it
1165  * detects error.)
1166  * - Compaire error  Report CMPE.
1167  *
1168  * - UE-UE           Report MUE.  No rewrite.
1169  *
1170  * - UE-*	     UE-(CE/OK). Rewrite to scrub UE.  Report SUE.
1171  *
1172  * - CE-*            CE-(CE/OK). Scrub to determine if CE is permanent.
1173  *                   If CE is permanent, inform SCF.  Once for each
1174  *		     Dimm.  If CE becomes UE or CMPE, go back to above.
1175  *
1176  *
1177  * MI (The error addresses for each bank are the same or different.)
1178  * - Compair  error  If addresses are the same.  Just CMPE.
1179  *		     If addresses are different (this could happen
1180  *		     as a result of scrubbing.  Report each seperately.
1181  *		     Only report error info on each side.
1182  *
1183  * - UE-UE           Addresses are the same.  Report MUE.
1184  *		     Addresses are different.  Report SUE on each bank.
1185  *		     Rewrite to clear UE.
1186  *
1187  * - UE-*	     UE-(CE/OK)
1188  *		     Rewrite to clear UE.  Report SUE for the bank.
1189  *
1190  * - CE-*            CE-(CE/OK).  Scrub to determine if CE is permanent.
1191  *                   If CE becomes UE or CMPE, go back to above.
1192  *
1193  */
1194 
1195 static int
1196 mc_process_error_mir(mc_opl_t *mcp, mc_aflt_t *mc_aflt, mc_flt_stat_t *flt_stat)
1197 {
1198 	int ptrl_error = mc_aflt->mflt_is_ptrl;
1199 	int i;
1200 	int rv = 0;
1201 
1202 	MC_LOG("process mirror errors cntl[0] = %x, cntl[1] = %x\n",
1203 		flt_stat[0].mf_cntl, flt_stat[1].mf_cntl);
1204 
1205 	if (ptrl_error) {
1206 		if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
1207 			& MAC_CNTL_PTRL_ERRS) == 0)
1208 			return (0);
1209 	} else {
1210 		if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
1211 			& MAC_CNTL_MI_ERRS) == 0)
1212 			return (0);
1213 	}
1214 
1215 	/*
1216 	 * First we take care of the case of CE
1217 	 * because they can become UE or CMPE
1218 	 */
1219 	for (i = 0; i < 2; i++) {
1220 		if (IS_CE_ONLY(flt_stat[i].mf_cntl, ptrl_error)) {
1221 			MC_LOG("CE detected on bank %d\n",
1222 				flt_stat[i].mf_flt_maddr.ma_bank);
1223 			mc_scrub_ce(mcp, flt_stat[i].mf_flt_maddr.ma_bank,
1224 				&flt_stat[i], ptrl_error);
1225 			rv = 1;
1226 		}
1227 	}
1228 
1229 	/* The above scrubbing can turn CE into UE or CMPE */
1230 
1231 	/*
1232 	 * Now we distinguish two cases: same address or not
1233 	 * the same address.  It might seem more intuitive to
1234 	 * distinguish PTRL v.s. MI error but it is more
1235 	 * complicated that way.
1236 	 */
1237 
1238 	if (flt_stat[0].mf_err_add == flt_stat[1].mf_err_add) {
1239 
1240 		if (IS_CMPE(flt_stat[0].mf_cntl, ptrl_error) ||
1241 		    IS_CMPE(flt_stat[1].mf_cntl, ptrl_error)) {
1242 			flt_stat[0].mf_type = FLT_TYPE_CMPE;
1243 			flt_stat[1].mf_type = FLT_TYPE_CMPE;
1244 			mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1245 			MC_LOG("cmpe error detected\n");
1246 			mc_aflt->mflt_nflts = 2;
1247 			mc_aflt->mflt_stat[0] = &flt_stat[0];
1248 			mc_aflt->mflt_stat[1] = &flt_stat[1];
1249 			mc_aflt->mflt_pr = PR_UE;
1250 			mc_err_drain(mc_aflt);
1251 			return (1);
1252 		}
1253 
1254 		if (IS_UE(flt_stat[0].mf_cntl, ptrl_error) &&
1255 			IS_UE(flt_stat[1].mf_cntl, ptrl_error)) {
1256 			/* Both side are UE's */
1257 
1258 			MAC_SET_ERRLOG_INFO(&flt_stat[0]);
1259 			MAC_SET_ERRLOG_INFO(&flt_stat[1]);
1260 			MC_LOG("MUE detected\n");
1261 			flt_stat[0].mf_type = flt_stat[1].mf_type =
1262 				FLT_TYPE_MUE;
1263 			mc_aflt->mflt_erpt_class = MC_OPL_MUE;
1264 			mc_aflt->mflt_nflts = 2;
1265 			mc_aflt->mflt_stat[0] = &flt_stat[0];
1266 			mc_aflt->mflt_stat[1] = &flt_stat[1];
1267 			mc_aflt->mflt_pr = PR_UE;
1268 			mc_err_drain(mc_aflt);
1269 			return (1);
1270 		}
1271 
1272 		/* Now the only case is UE/CE, UE/OK, or don't care */
1273 		for (i = 0; i < 2; i++) {
1274 		    if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1275 			/* If we have CE, we would have done REW */
1276 			if (IS_OK(flt_stat[i^1].mf_cntl, ptrl_error)) {
1277 				(void) do_rewrite(mcp,
1278 				    flt_stat[i].mf_flt_maddr.ma_bank,
1279 				    flt_stat[i].mf_flt_maddr.ma_dimm_addr);
1280 			}
1281 			flt_stat[i].mf_type = FLT_TYPE_UE;
1282 			MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1283 			mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1284 			mc_aflt->mflt_stat[0] = &flt_stat[i];
1285 			mc_aflt->mflt_nflts = 1;
1286 			mc_aflt->mflt_pr = PR_MCE;
1287 			mc_err_drain(mc_aflt);
1288 			/* Once we hit a UE/CE or UE/OK case, done */
1289 			return (1);
1290 		    }
1291 		}
1292 
1293 	} else {
1294 		/*
1295 		 * addresses are different. That means errors
1296 		 * on the 2 banks are not related at all.
1297 		 */
1298 		for (i = 0; i < 2; i++) {
1299 		    if (IS_CMPE(flt_stat[i].mf_cntl, ptrl_error)) {
1300 			flt_stat[i].mf_type = FLT_TYPE_CMPE;
1301 			mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1302 			MC_LOG("cmpe error detected\n");
1303 			mc_aflt->mflt_nflts = 1;
1304 			mc_aflt->mflt_stat[0] = &flt_stat[i];
1305 			mc_aflt->mflt_pr = PR_UE;
1306 			mc_err_drain(mc_aflt);
1307 			/* no more report on this bank */
1308 			flt_stat[i].mf_cntl = 0;
1309 			rv = 1;
1310 		    }
1311 		}
1312 
1313 		for (i = 0; i < 2; i++) {
1314 		    if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1315 			(void) do_rewrite(mcp,
1316 				flt_stat[i].mf_flt_maddr.ma_bank,
1317 				flt_stat[i].mf_flt_maddr.ma_dimm_addr);
1318 			flt_stat[i].mf_type = FLT_TYPE_UE;
1319 			MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1320 			mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1321 			mc_aflt->mflt_stat[0] = &flt_stat[i];
1322 			mc_aflt->mflt_nflts = 1;
1323 			mc_aflt->mflt_pr = PR_MCE;
1324 			mc_err_drain(mc_aflt);
1325 			rv = 1;
1326 		    }
1327 		}
1328 	}
1329 	return (rv);
1330 }
1331 
1332 static void
1333 mc_error_handler_mir(mc_opl_t *mcp, int bank, mc_addr_info_t *maddr)
1334 {
1335 	mc_aflt_t mc_aflt;
1336 	mc_flt_stat_t flt_stat[2], mi_flt_stat[2];
1337 	int other_bank;
1338 
1339 	if (mc_stop(mcp, bank)) {
1340 		cmn_err(CE_WARN, "Cannot stop Memory Patrol at /LSB%d/B%d\n",
1341 			mcp->mc_board_num, bank);
1342 		return;
1343 	}
1344 	bzero(&mc_aflt, sizeof (mc_aflt_t));
1345 	bzero(&flt_stat, 2 * sizeof (mc_flt_stat_t));
1346 	bzero(&mi_flt_stat, 2 * sizeof (mc_flt_stat_t));
1347 
1348 	mc_aflt.mflt_mcp = mcp;
1349 	mc_aflt.mflt_id = gethrtime();
1350 
1351 	/* Now read all the registers into flt_stat */
1352 
1353 	MC_LOG("Reading registers of bank %d\n", bank);
1354 	/* patrol registers */
1355 	mc_read_ptrl_reg(mcp, bank, &flt_stat[0]);
1356 
1357 	ASSERT(maddr);
1358 	maddr->mi_maddr = flt_stat[0].mf_flt_maddr;
1359 
1360 	MC_LOG("ptrl registers cntl %x add %x log %x\n",
1361 		flt_stat[0].mf_cntl,
1362 		flt_stat[0].mf_err_add,
1363 		flt_stat[0].mf_err_log);
1364 
1365 	/* MI registers */
1366 	mc_read_mi_reg(mcp, bank, &mi_flt_stat[0]);
1367 
1368 	MC_LOG("MI registers cntl %x add %x log %x\n",
1369 		mi_flt_stat[0].mf_cntl,
1370 		mi_flt_stat[0].mf_err_add,
1371 		mi_flt_stat[0].mf_err_log);
1372 
1373 	other_bank = bank^1;
1374 
1375 	MC_LOG("Reading registers of bank %d\n", other_bank);
1376 
1377 	ASSERT(mcp->mc_bank[other_bank].mcb_status & BANK_INSTALLED);
1378 
1379 	mc_read_ptrl_reg(mcp, other_bank, &flt_stat[1]);
1380 	MC_LOG("ptrl registers cntl %x add %x log %x\n",
1381 		flt_stat[1].mf_cntl,
1382 		flt_stat[1].mf_err_add,
1383 		flt_stat[1].mf_err_log);
1384 
1385 	/* MI registers */
1386 	mc_read_mi_reg(mcp, other_bank, &mi_flt_stat[1]);
1387 	MC_LOG("MI registers cntl %x add %x log %x\n",
1388 		mi_flt_stat[1].mf_cntl,
1389 		mi_flt_stat[1].mf_err_add,
1390 		mi_flt_stat[1].mf_err_log);
1391 
1392 	/* clear errors once we read all the registers */
1393 	MAC_CLEAR_ERRS(mcp, other_bank,
1394 		(MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1395 
1396 	MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1397 
1398 	/* Process PTRL errors first */
1399 
1400 	/* if not error mode, cntl1 is 0 */
1401 	if ((flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
1402 		(flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
1403 		flt_stat[0].mf_cntl = 0;
1404 
1405 	if ((flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
1406 		(flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
1407 		flt_stat[1].mf_cntl = 0;
1408 
1409 	mc_aflt.mflt_is_ptrl = 1;
1410 	maddr->mi_valid = mc_process_error_mir(mcp, &mc_aflt, &flt_stat[0]);
1411 
1412 	mc_aflt.mflt_is_ptrl = 0;
1413 	mc_process_error_mir(mcp, &mc_aflt, &mi_flt_stat[0]);
1414 }
1415 
1416 static int
1417 mc_process_error(mc_opl_t *mcp, int bank, mc_aflt_t *mc_aflt,
1418 	mc_flt_stat_t *flt_stat)
1419 {
1420 	int ptrl_error = mc_aflt->mflt_is_ptrl;
1421 	int rv = 0;
1422 
1423 	mc_aflt->mflt_erpt_class = NULL;
1424 	if (IS_UE(flt_stat->mf_cntl, ptrl_error)) {
1425 		MC_LOG("UE deteceted\n");
1426 		flt_stat->mf_type = FLT_TYPE_UE;
1427 		mc_aflt->mflt_erpt_class = MC_OPL_UE;
1428 		mc_aflt->mflt_pr = PR_UE;
1429 		MAC_SET_ERRLOG_INFO(flt_stat);
1430 		rv = 1;
1431 	} else if (IS_CE(flt_stat->mf_cntl, ptrl_error)) {
1432 		MC_LOG("CE deteceted\n");
1433 		MAC_SET_ERRLOG_INFO(flt_stat);
1434 
1435 		/* Error type can change after scrubing */
1436 		mc_scrub_ce(mcp, bank, flt_stat, ptrl_error);
1437 
1438 		if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
1439 			mc_aflt->mflt_erpt_class = MC_OPL_CE;
1440 			mc_aflt->mflt_pr = PR_MCE;
1441 		} else if (flt_stat->mf_type == FLT_TYPE_UE) {
1442 			mc_aflt->mflt_erpt_class = MC_OPL_UE;
1443 			mc_aflt->mflt_pr = PR_UE;
1444 		}
1445 		rv = 1;
1446 	}
1447 	MC_LOG("mc_process_error: fault type %x erpt %s\n",
1448 		flt_stat->mf_type,
1449 		mc_aflt->mflt_erpt_class);
1450 	if (mc_aflt->mflt_erpt_class) {
1451 		mc_aflt->mflt_stat[0] = flt_stat;
1452 		mc_aflt->mflt_nflts = 1;
1453 		mc_err_drain(mc_aflt);
1454 	}
1455 	return (rv);
1456 }
1457 
1458 static void
1459 mc_error_handler(mc_opl_t *mcp, int bank, mc_addr_info_t *maddr)
1460 {
1461 	mc_aflt_t mc_aflt;
1462 	mc_flt_stat_t flt_stat, mi_flt_stat;
1463 
1464 	if (mc_stop(mcp, bank)) {
1465 		cmn_err(CE_WARN, "Cannot stop Memory Patrol at /LSB%d/B%d\n",
1466 			mcp->mc_board_num, bank);
1467 		return;
1468 	}
1469 
1470 	bzero(&mc_aflt, sizeof (mc_aflt_t));
1471 	bzero(&flt_stat, sizeof (mc_flt_stat_t));
1472 	bzero(&mi_flt_stat, sizeof (mc_flt_stat_t));
1473 
1474 	mc_aflt.mflt_mcp = mcp;
1475 	mc_aflt.mflt_id = gethrtime();
1476 
1477 	/* patrol registers */
1478 	mc_read_ptrl_reg(mcp, bank, &flt_stat);
1479 
1480 	ASSERT(maddr);
1481 	maddr->mi_maddr = flt_stat.mf_flt_maddr;
1482 
1483 	MC_LOG("ptrl registers cntl %x add %x log %x\n",
1484 		flt_stat.mf_cntl,
1485 		flt_stat.mf_err_add,
1486 		flt_stat.mf_err_log);
1487 
1488 	/* MI registers */
1489 	mc_read_mi_reg(mcp, bank, &mi_flt_stat);
1490 
1491 	MC_LOG("MI registers cntl %x add %x log %x\n",
1492 		mi_flt_stat.mf_cntl,
1493 		mi_flt_stat.mf_err_add,
1494 		mi_flt_stat.mf_err_log);
1495 
1496 	/* clear errors once we read all the registers */
1497 	MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1498 
1499 	mc_aflt.mflt_is_ptrl = 1;
1500 	if ((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) &&
1501 		((flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
1502 		((flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
1503 		maddr->mi_valid = mc_process_error(mcp, bank,
1504 			&mc_aflt, &flt_stat);
1505 	}
1506 	mc_aflt.mflt_is_ptrl = 0;
1507 	if ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) &&
1508 		((mi_flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
1509 		((mi_flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
1510 		mc_process_error(mcp, bank, &mc_aflt, &mi_flt_stat);
1511 	}
1512 }
1513 
1514 /*
1515  *	memory patrol error handling algorithm:
1516  *	timeout() is used to do periodic polling
1517  *	This is the flow chart.
1518  *	timeout ->
1519  *	mc_check_errors()
1520  *	    if memory bank is installed, read the status register
1521  *	    if any error bit is set,
1522  *	    -> mc_error_handler()
1523  *	        -> mc_stop()
1524  *		-> read all error regsiters
1525  *	        -> mc_process_error()
1526  *	            determine error type
1527  *	            rewrite to clear error or scrub to determine CE type
1528  *	            inform SCF on permanent CE
1529  *	        -> mc_err_drain
1530  *	            page offline processing
1531  *	            -> mc_ereport_post()
1532  */
1533 
1534 static void
1535 mc_check_errors_func(mc_opl_t *mcp)
1536 {
1537 	mc_addr_info_t maddr_info;
1538 	int i, error_count = 0;
1539 	uint32_t stat, cntl;
1540 
1541 	/*
1542 	 * scan errors.
1543 	 */
1544 	for (i = 0; i < BANKNUM_PER_SB; i++) {
1545 		if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
1546 			stat = ldphysio(MAC_PTRL_STAT(mcp, i));
1547 			cntl = ldphysio(MAC_PTRL_CNTL(mcp, i));
1548 			if (cntl & MAC_CNTL_PTRL_ADD_MAX) {
1549 				mcp->mc_period++;
1550 				MC_LOG("mc period %ld on "
1551 				    "/LSB%d/B%d\n", mcp->mc_period,
1552 				    mcp->mc_board_num, i);
1553 				MAC_CLEAR_MAX(mcp, i);
1554 			}
1555 			if (mc_debug_show_all) {
1556 				MC_LOG("/LSB%d/B%d stat %x cntl %x\n",
1557 					mcp->mc_board_num, i,
1558 					stat, cntl);
1559 			}
1560 			if (stat & (MAC_STAT_PTRL_ERRS|MAC_STAT_MI_ERRS)) {
1561 				maddr_info.mi_valid = 0;
1562 				maddr_info.mi_advance = 1;
1563 				if (IS_MIRROR(mcp, i))
1564 					mc_error_handler_mir(mcp, i,
1565 						&maddr_info);
1566 				else
1567 					mc_error_handler(mcp, i, &maddr_info);
1568 
1569 				error_count++;
1570 				restart_patrol(mcp, i, &maddr_info);
1571 			} else {
1572 				restart_patrol(mcp, i, NULL);
1573 			}
1574 		}
1575 	}
1576 	mc_process_scf_log(mcp);
1577 	if (error_count > 0)
1578 		mcp->mc_last_error += error_count;
1579 	else
1580 		mcp->mc_last_error = 0;
1581 }
1582 
1583 /* this is just a wrapper for the above func */
1584 
1585 static void
1586 mc_check_errors(void *arg)
1587 {
1588 	mc_opl_t *mcp = (mc_opl_t *)arg;
1589 	clock_t interval;
1590 
1591 	/*
1592 	 * scan errors.
1593 	 */
1594 	mutex_enter(&mcp->mc_lock);
1595 	mcp->mc_tid = 0;
1596 	if ((mcp->mc_status & MC_POLL_RUNNING) &&
1597 		!(mcp->mc_status & MC_SOFT_SUSPENDED)) {
1598 		mc_check_errors_func(mcp);
1599 
1600 		if (mcp->mc_last_error > 0) {
1601 			interval = (mcp->mc_interval_hz) >> mcp->mc_last_error;
1602 			if (interval < 1)
1603 				interval = 1;
1604 		} else
1605 			interval = mcp->mc_interval_hz;
1606 
1607 		mcp->mc_tid = timeout(mc_check_errors, mcp,
1608 		    interval);
1609 	}
1610 	mutex_exit(&mcp->mc_lock);
1611 }
1612 
1613 static void
1614 get_ptrl_start_address(mc_opl_t *mcp, int bank, mc_addr_t *maddr)
1615 {
1616 	maddr->ma_bd = mcp->mc_board_num;
1617 	maddr->ma_bank = bank;
1618 	maddr->ma_dimm_addr = 0;
1619 }
1620 
1621 typedef struct mc_mem_range {
1622 	uint64_t	addr;
1623 	uint64_t	size;
1624 } mc_mem_range_t;
1625 
1626 static int
1627 get_base_address(mc_opl_t *mcp)
1628 {
1629 	mc_mem_range_t *mem_range;
1630 	int len;
1631 
1632 	if (ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
1633 		"sb-mem-ranges", (caddr_t)&mem_range, &len) != DDI_SUCCESS) {
1634 		return (DDI_FAILURE);
1635 	}
1636 
1637 	mcp->mc_start_address = mem_range->addr;
1638 	mcp->mc_size = mem_range->size;
1639 
1640 	kmem_free(mem_range, len);
1641 	return (DDI_SUCCESS);
1642 }
1643 
1644 struct mc_addr_spec {
1645 	uint32_t bank;
1646 	uint32_t phys_hi;
1647 	uint32_t phys_lo;
1648 };
1649 
1650 #define	REGS_PA(m, i) ((((uint64_t)m[i].phys_hi)<<32) | m[i].phys_lo)
1651 
1652 static char *mc_tbl_name[] = {
1653 	"cs0-mc-pa-trans-table",
1654 	"cs1-mc-pa-trans-table"
1655 };
1656 
1657 static int
1658 mc_valid_pa(mc_opl_t *mcp, uint64_t pa)
1659 {
1660 	struct memlist *ml;
1661 
1662 	if (mcp->mlist == NULL)
1663 		mc_get_mlist(mcp);
1664 
1665 	for (ml = mcp->mlist; ml; ml = ml->next) {
1666 		if (ml->address <= pa && pa < (ml->address + ml->size))
1667 			return (1);
1668 	}
1669 	return (0);
1670 }
1671 
1672 static void
1673 mc_memlist_delete(struct memlist *mlist)
1674 {
1675 	struct memlist *ml;
1676 
1677 	for (ml = mlist; ml; ml = mlist) {
1678 		mlist = ml->next;
1679 		kmem_free(ml, sizeof (struct memlist));
1680 	}
1681 }
1682 
1683 static struct memlist *
1684 mc_memlist_dup(struct memlist *mlist)
1685 {
1686 	struct memlist *hl = NULL, *tl, **mlp;
1687 
1688 	if (mlist == NULL)
1689 		return (NULL);
1690 
1691 	mlp = &hl;
1692 	tl = *mlp;
1693 	for (; mlist; mlist = mlist->next) {
1694 		*mlp = kmem_alloc(sizeof (struct memlist), KM_SLEEP);
1695 		(*mlp)->address = mlist->address;
1696 		(*mlp)->size = mlist->size;
1697 		(*mlp)->prev = tl;
1698 		tl = *mlp;
1699 		mlp = &((*mlp)->next);
1700 	}
1701 	*mlp = NULL;
1702 
1703 	return (hl);
1704 }
1705 
1706 
1707 static struct memlist *
1708 mc_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
1709 {
1710 	uint64_t	end;
1711 	struct memlist	*ml, *tl, *nlp;
1712 
1713 	if (mlist == NULL)
1714 		return (NULL);
1715 
1716 	end = base + len;
1717 	if ((end <= mlist->address) || (base == end))
1718 		return (mlist);
1719 
1720 	for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
1721 		uint64_t	mend;
1722 
1723 		nlp = ml->next;
1724 
1725 		if (end <= ml->address)
1726 			break;
1727 
1728 		mend = ml->address + ml->size;
1729 		if (base < mend) {
1730 			if (base <= ml->address) {
1731 				ml->address = end;
1732 				if (end >= mend)
1733 					ml->size = 0ull;
1734 				else
1735 					ml->size = mend - ml->address;
1736 			} else {
1737 				ml->size = base - ml->address;
1738 				if (end < mend) {
1739 					struct memlist	*nl;
1740 					/*
1741 					 * splitting an memlist entry.
1742 					 */
1743 					nl = kmem_alloc(sizeof (struct memlist),
1744 						KM_SLEEP);
1745 					nl->address = end;
1746 					nl->size = mend - nl->address;
1747 					if ((nl->next = nlp) != NULL)
1748 						nlp->prev = nl;
1749 					nl->prev = ml;
1750 					ml->next = nl;
1751 					nlp = nl;
1752 				}
1753 			}
1754 			if (ml->size == 0ull) {
1755 				if (ml == mlist) {
1756 					if ((mlist = nlp) != NULL)
1757 						nlp->prev = NULL;
1758 					kmem_free(ml, sizeof (struct memlist));
1759 					if (mlist == NULL)
1760 						break;
1761 					ml = nlp;
1762 				} else {
1763 					if ((tl->next = nlp) != NULL)
1764 						nlp->prev = tl;
1765 					kmem_free(ml, sizeof (struct memlist));
1766 					ml = tl;
1767 				}
1768 			}
1769 		}
1770 	}
1771 
1772 	return (mlist);
1773 }
1774 
1775 static void
1776 mc_get_mlist(mc_opl_t *mcp)
1777 {
1778 	struct memlist *mlist;
1779 
1780 	memlist_read_lock();
1781 	mlist = mc_memlist_dup(phys_install);
1782 	memlist_read_unlock();
1783 
1784 	if (mlist) {
1785 		mlist = mc_memlist_del_span(mlist, 0ull, mcp->mc_start_address);
1786 	}
1787 
1788 	if (mlist) {
1789 		uint64_t startpa, endpa;
1790 
1791 		startpa = mcp->mc_start_address + mcp->mc_size;
1792 		endpa = ptob(physmax + 1);
1793 		if (endpa > startpa) {
1794 			mlist = mc_memlist_del_span(mlist,
1795 				startpa, endpa - startpa);
1796 		}
1797 	}
1798 
1799 	if (mlist) {
1800 		mcp->mlist = mlist;
1801 	}
1802 }
1803 
1804 int
1805 mc_board_add(mc_opl_t *mcp)
1806 {
1807 	struct mc_addr_spec *macaddr;
1808 	int len, i, bk, cc;
1809 	mc_addr_info_t maddr;
1810 	uint32_t mirr;
1811 
1812 	mutex_init(&mcp->mc_lock, NULL, MUTEX_DRIVER, NULL);
1813 
1814 	/*
1815 	 * Get configurations from "pseudo-mc" node which includes:
1816 	 * board# : LSB number
1817 	 * mac-addr : physical base address of MAC registers
1818 	 * csX-mac-pa-trans-table: translation table from DIMM address
1819 	 *			to physical address or vice versa.
1820 	 */
1821 	mcp->mc_board_num = (int)ddi_getprop(DDI_DEV_T_ANY, mcp->mc_dip,
1822 		DDI_PROP_DONTPASS, "board#", -1);
1823 
1824 	/*
1825 	 * Get start address in this CAB. It can be gotten from
1826 	 * "sb-mem-ranges" property.
1827 	 */
1828 
1829 	if (get_base_address(mcp) == DDI_FAILURE) {
1830 		mutex_destroy(&mcp->mc_lock);
1831 		return (DDI_FAILURE);
1832 	}
1833 	/* get mac-pa trans tables */
1834 	for (i = 0; i < MC_TT_CS; i++) {
1835 		len = MC_TT_ENTRIES;
1836 		cc = ddi_getlongprop_buf(DDI_DEV_T_ANY, mcp->mc_dip,
1837 			DDI_PROP_DONTPASS, mc_tbl_name[i],
1838 			(caddr_t)mcp->mc_trans_table[i], &len);
1839 
1840 		if (cc != DDI_SUCCESS) {
1841 			bzero(mcp->mc_trans_table[i], MC_TT_ENTRIES);
1842 		}
1843 	}
1844 	mcp->mlist = NULL;
1845 
1846 	mc_get_mlist(mcp);
1847 
1848 	/* initialize bank informations */
1849 	cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
1850 		"mc-addr", (caddr_t)&macaddr, &len);
1851 	if (cc != DDI_SUCCESS) {
1852 		cmn_err(CE_WARN, "Cannot get mc-addr. err=%d\n", cc);
1853 		mutex_destroy(&mcp->mc_lock);
1854 		return (DDI_FAILURE);
1855 	}
1856 
1857 	for (i = 0; i < len / sizeof (struct mc_addr_spec); i++) {
1858 		struct mc_bank *bankp;
1859 		uint32_t reg;
1860 
1861 		/*
1862 		 * setup bank
1863 		 */
1864 		bk = macaddr[i].bank;
1865 		bankp = &(mcp->mc_bank[bk]);
1866 		bankp->mcb_status = BANK_INSTALLED;
1867 		bankp->mcb_reg_base = REGS_PA(macaddr, i);
1868 
1869 		reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bk));
1870 		bankp->mcb_ptrl_cntl = (reg & MAC_CNTL_PTRL_PRESERVE_BITS);
1871 
1872 		/*
1873 		 * check if mirror mode
1874 		 */
1875 		mirr = LD_MAC_REG(MAC_MIRR(mcp, bk));
1876 
1877 		if (mirr & MAC_MIRR_MIRROR_MODE) {
1878 			MC_LOG("Mirror -> /LSB%d/B%d\n",
1879 				mcp->mc_board_num, bk);
1880 			bankp->mcb_status |= BANK_MIRROR_MODE;
1881 			/*
1882 			 * The following bit is only used for
1883 			 * error injection.  We should clear it
1884 			 */
1885 			if (mirr & MAC_MIRR_BANK_EXCLUSIVE)
1886 				ST_MAC_REG(MAC_MIRR(mcp, bk),
1887 					0);
1888 		}
1889 
1890 		/*
1891 		 * restart if not mirror mode or the other bank
1892 		 * of the mirror is not running
1893 		 */
1894 		if (!(mirr & MAC_MIRR_MIRROR_MODE) ||
1895 			!(mcp->mc_bank[bk^1].mcb_status &
1896 			BANK_PTRL_RUNNING)) {
1897 			MC_LOG("Starting up /LSB%d/B%d\n",
1898 				mcp->mc_board_num, bk);
1899 			get_ptrl_start_address(mcp, bk, &maddr.mi_maddr);
1900 			maddr.mi_valid = 1;
1901 			maddr.mi_advance = 0;
1902 			restart_patrol(mcp, bk, &maddr);
1903 		} else {
1904 			MC_LOG("Not starting up /LSB%d/B%d\n",
1905 				mcp->mc_board_num, bk);
1906 		}
1907 		bankp->mcb_status |= BANK_PTRL_RUNNING;
1908 	}
1909 	kmem_free(macaddr, len);
1910 
1911 	/*
1912 	 * set interval in HZ.
1913 	 */
1914 	for (i = 0; i < BANKNUM_PER_SB; i++) {
1915 		mcp->mc_scf_retry[i] = 0;
1916 	}
1917 	mcp->mc_last_error = 0;
1918 	mcp->mc_period = 0;
1919 
1920 	mcp->mc_interval_hz = drv_usectohz(mc_patrol_interval_sec * 1000000);
1921 	/* restart memory patrol checking */
1922 	mcp->mc_status |= MC_POLL_RUNNING;
1923 	mcp->mc_tid = timeout(mc_check_errors, mcp, mcp->mc_interval_hz);
1924 
1925 	return (DDI_SUCCESS);
1926 }
1927 
1928 int
1929 mc_board_del(mc_opl_t *mcp)
1930 {
1931 	int i;
1932 	scf_log_t *p;
1933 	timeout_id_t tid = 0;
1934 
1935 	/*
1936 	 * cleanup mac state
1937 	 */
1938 	mutex_enter(&mcp->mc_lock);
1939 	for (i = 0; i < BANKNUM_PER_SB; i++) {
1940 		if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
1941 			if (mc_stop(mcp, i)) {
1942 				mutex_exit(&mcp->mc_lock);
1943 				return (-1);
1944 			}
1945 			mcp->mc_bank[i].mcb_status &= ~BANK_INSTALLED;
1946 		}
1947 	}
1948 
1949 	/* stop memory patrol checking */
1950 	if (mcp->mc_status & MC_POLL_RUNNING) {
1951 		mcp->mc_status &= ~MC_POLL_RUNNING;
1952 		tid = mcp->mc_tid;
1953 		mcp->mc_tid = 0;
1954 	}
1955 
1956 	/* just throw away all the scf logs */
1957 	while ((p = mcp->mc_scf_log) != NULL) {
1958 		mcp->mc_scf_log = p->sl_next;
1959 		mcp->mc_scf_total--;
1960 		kmem_free(p, sizeof (scf_log_t));
1961 	}
1962 
1963 	if (mcp->mlist)
1964 		mc_memlist_delete(mcp->mlist);
1965 
1966 	mutex_exit(&mcp->mc_lock);
1967 	if (tid)
1968 		(void) untimeout(tid);
1969 
1970 	mutex_destroy(&mcp->mc_lock);
1971 	return (DDI_SUCCESS);
1972 }
1973 
1974 int
1975 mc_suspend(mc_opl_t *mcp, uint32_t flag)
1976 {
1977 	timeout_id_t tid = 0;
1978 	int i;
1979 	/* stop memory patrol checking */
1980 	mutex_enter(&mcp->mc_lock);
1981 	if (mcp->mc_status & MC_POLL_RUNNING) {
1982 		for (i = 0; i < BANKNUM_PER_SB; i++) {
1983 			if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
1984 				if (mc_stop(mcp, i)) {
1985 					mutex_exit(&mcp->mc_lock);
1986 					return (-1);
1987 				}
1988 			}
1989 		}
1990 		mcp->mc_status &= ~MC_POLL_RUNNING;
1991 		tid = mcp->mc_tid;
1992 	}
1993 	mcp->mc_status |= flag;
1994 	mcp->mc_tid = 0;
1995 	mutex_exit(&mcp->mc_lock);
1996 	if (tid)
1997 		(void) untimeout(tid);
1998 
1999 	return (DDI_SUCCESS);
2000 }
2001 
2002 /* caller must clear the SUSPEND bits or this will do nothing */
2003 
2004 int
2005 mc_resume(mc_opl_t *mcp, uint32_t flag)
2006 {
2007 	int i;
2008 	uint64_t basepa;
2009 
2010 	mutex_enter(&mcp->mc_lock);
2011 	basepa = mcp->mc_start_address;
2012 	if (get_base_address(mcp) == DDI_FAILURE) {
2013 		mutex_exit(&mcp->mc_lock);
2014 		return (DDI_FAILURE);
2015 	}
2016 
2017 	if (basepa != mcp->mc_start_address) {
2018 		if (mcp->mlist)
2019 			mc_memlist_delete(mcp->mlist);
2020 		mcp->mlist = NULL;
2021 		mc_get_mlist(mcp);
2022 	}
2023 
2024 	mcp->mc_status &= ~flag;
2025 	mcp->mc_list->mc_start_address = mcp->mc_start_address;
2026 
2027 	if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
2028 		mutex_exit(&mcp->mc_lock);
2029 		return (DDI_SUCCESS);
2030 	}
2031 
2032 	if (!(mcp->mc_status & MC_POLL_RUNNING)) {
2033 		/* restart memory patrol checking */
2034 		mcp->mc_status |= MC_POLL_RUNNING;
2035 		for (i = 0; i < BANKNUM_PER_SB; i++) {
2036 			if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2037 				restart_patrol(mcp, i, NULL);
2038 			}
2039 		}
2040 		/* check error asap */
2041 		mcp->mc_tid = timeout(mc_check_errors, mcp, 1);
2042 	}
2043 	mutex_exit(&mcp->mc_lock);
2044 
2045 	return (DDI_SUCCESS);
2046 }
2047 
2048 static mc_opl_t *
2049 mc_pa_to_mcp(uint64_t pa)
2050 {
2051 	mc_inst_list_t *p;
2052 	ASSERT(MUTEX_HELD(&mcmutex));
2053 	for (p = mc_instances; p; p = p->next) {
2054 		/* if mac patrol is suspended, we cannot rely on it */
2055 		if (!(p->mc_opl->mc_status & MC_POLL_RUNNING) ||
2056 			(p->mc_opl->mc_status & MC_SOFT_SUSPENDED))
2057 			continue;
2058 		if ((p->mc_start_address <= pa) &&
2059 			(pa < (p->mc_start_address + p->mc_size))) {
2060 			return (p->mc_opl);
2061 		}
2062 	}
2063 	return (NULL);
2064 }
2065 
2066 /*
2067  * Get Physical Board number from Logical one.
2068  */
2069 static int
2070 mc_opl_get_physical_board(int sb)
2071 {
2072 	if (&opl_get_physical_board) {
2073 		return (opl_get_physical_board(sb));
2074 	}
2075 
2076 	cmn_err(CE_NOTE, "!opl_get_physical_board() not loaded\n");
2077 	return (-1);
2078 }
2079 
2080 /* ARGSUSED */
2081 int
2082 mc_get_mem_unum(int synd_code, uint64_t flt_addr, char *buf, int buflen,
2083 	int *lenp)
2084 {
2085 	mc_opl_t *mcp;
2086 	int bank;
2087 	int sb;
2088 
2089 	mutex_enter(&mcmutex);
2090 
2091 	if (((mcp = mc_pa_to_mcp(flt_addr)) == NULL) ||
2092 		(!pa_is_valid(mcp, flt_addr))) {
2093 		mutex_exit(&mcmutex);
2094 		if (snprintf(buf, buflen, "UNKNOWN") >= buflen) {
2095 			return (ENOSPC);
2096 		} else {
2097 			if (lenp)
2098 				*lenp = strlen(buf);
2099 		}
2100 		return (0);
2101 	}
2102 
2103 	bank = pa_to_bank(mcp, flt_addr - mcp->mc_start_address);
2104 	sb = mc_opl_get_physical_board(mcp->mc_board_num);
2105 
2106 	if (sb == -1) {
2107 		mutex_exit(&mcmutex);
2108 		return (ENXIO);
2109 	}
2110 
2111 	if (snprintf(buf, buflen, "/CMU%d/B%d", sb, bank) >= buflen) {
2112 		mutex_exit(&mcmutex);
2113 		return (ENOSPC);
2114 	} else {
2115 		if (lenp)
2116 			*lenp = strlen(buf);
2117 	}
2118 	mutex_exit(&mcmutex);
2119 	return (0);
2120 }
2121 
2122 int
2123 opl_mc_suspend()
2124 {
2125 	mc_opl_t *mcp;
2126 	mc_inst_list_t *p;
2127 
2128 	mutex_enter(&mcmutex);
2129 
2130 	for (p = mc_instances; p; p = p->next) {
2131 		mcp = p->mc_opl;
2132 		(void) mc_suspend(mcp, MC_SOFT_SUSPENDED);
2133 	}
2134 
2135 	mutex_exit(&mcmutex);
2136 	return (0);
2137 }
2138 
2139 int
2140 opl_mc_resume()
2141 {
2142 	mc_opl_t *mcp;
2143 	mc_inst_list_t *p;
2144 
2145 	mutex_enter(&mcmutex);
2146 
2147 	for (p = mc_instances; p; p = p->next) {
2148 		mcp = p->mc_opl;
2149 		(void) mc_resume(mcp, MC_SOFT_SUSPENDED);
2150 	}
2151 
2152 	mutex_exit(&mcmutex);
2153 	return (0);
2154 }
2155 
2156 static void
2157 insert_mcp(mc_opl_t *mcp)
2158 {
2159 	mc_inst_list_t	*p;
2160 
2161 	p = kmem_zalloc(sizeof (mc_inst_list_t), KM_SLEEP);
2162 	p->mc_opl = mcp;
2163 	p->mc_board_num = mcp->mc_board_num;
2164 	p->mc_start_address = mcp->mc_start_address;
2165 	p->mc_size = mcp->mc_size;
2166 	mcp->mc_list = p;
2167 
2168 	mutex_enter(&mcmutex);
2169 
2170 	p->next = mc_instances;
2171 	mc_instances = p;
2172 
2173 	mutex_exit(&mcmutex);
2174 }
2175 
2176 static void
2177 delete_mcp(mc_opl_t *mcp)
2178 {
2179 	mc_inst_list_t *prev, *current;
2180 	mc_inst_list_t *p;
2181 
2182 	p = mcp->mc_list;
2183 
2184 	if (mc_instances == p) {
2185 		mc_instances = p->next;
2186 		kmem_free(p, sizeof (mc_inst_list_t));
2187 		return;
2188 	}
2189 	prev = mc_instances;
2190 	for (current = mc_instances; current != NULL; current = current->next) {
2191 		if (current == p) {
2192 			prev->next = p->next;
2193 			kmem_free(p, sizeof (mc_inst_list_t));
2194 			return;
2195 		}
2196 		prev = current;
2197 	}
2198 }
2199 
2200 /* Error injection interface */
2201 
2202 /* ARGSUSED */
2203 int
2204 mc_inject_error(int error_type, uint64_t pa, uint32_t flags)
2205 {
2206 	mc_opl_t *mcp;
2207 	int bank;
2208 	uint32_t dimm_addr;
2209 	uint32_t cntl;
2210 	mc_addr_info_t maddr;
2211 	uint32_t data, stat;
2212 	int both_sides = 0;
2213 	uint64_t pa0;
2214 	on_trap_data_t otd;
2215 	extern void cpu_flush_ecache(void);
2216 
2217 	MC_LOG("HW mc_inject_error(%x, %lx, %x)\n", error_type, pa, flags);
2218 
2219 	mutex_enter(&mcmutex);
2220 
2221 	if ((mcp = mc_pa_to_mcp(pa)) == NULL) {
2222 		mutex_exit(&mcmutex);
2223 		MC_LOG("mc_inject_error: invalid pa\n");
2224 		return (ENOTSUP);
2225 	}
2226 
2227 	mutex_enter(&mcp->mc_lock);
2228 	mutex_exit(&mcmutex);
2229 
2230 	if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
2231 		mutex_exit(&mcp->mc_lock);
2232 		MC_LOG("mc-opl has been suspended.  No error injection.\n");
2233 		return (EBUSY);
2234 	}
2235 
2236 	/* convert pa to offset within the board */
2237 	MC_LOG("pa %lx, offset %lx\n", pa, pa - mcp->mc_start_address);
2238 
2239 	if (!pa_is_valid(mcp, pa)) {
2240 		mutex_exit(&mcp->mc_lock);
2241 		return (EINVAL);
2242 	}
2243 
2244 	pa0 = pa - mcp->mc_start_address;
2245 
2246 	bank = pa_to_bank(mcp, pa0);
2247 
2248 	if (flags & MC_INJECT_FLAG_OTHER)
2249 		bank = bank ^ 1;
2250 
2251 	if (MC_INJECT_MIRROR(error_type) && !IS_MIRROR(mcp, bank)) {
2252 		mutex_exit(&mcp->mc_lock);
2253 		MC_LOG("Not mirror mode\n");
2254 		return (EINVAL);
2255 	}
2256 
2257 	dimm_addr = pa_to_dimm(mcp, pa0);
2258 
2259 	MC_LOG("injecting error to /LSB%d/B%d/D%x\n",
2260 		mcp->mc_board_num, bank, dimm_addr);
2261 
2262 
2263 	switch (error_type) {
2264 	case MC_INJECT_INTERMITTENT_MCE:
2265 	case MC_INJECT_PERMANENT_MCE:
2266 	case MC_INJECT_MUE:
2267 		both_sides = 1;
2268 	}
2269 
2270 	if (flags & MC_INJECT_FLAG_RESET)
2271 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), 0);
2272 
2273 	ST_MAC_REG(MAC_EG_ADD(mcp, bank), dimm_addr & MAC_EG_ADD_MASK);
2274 
2275 	if (both_sides) {
2276 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), 0);
2277 		ST_MAC_REG(MAC_EG_ADD(mcp, bank^1),
2278 			dimm_addr & MAC_EG_ADD_MASK);
2279 	}
2280 
2281 	switch (error_type) {
2282 	case MC_INJECT_UE:
2283 	case MC_INJECT_SUE:
2284 	case MC_INJECT_MUE:
2285 		if (flags & MC_INJECT_FLAG_PATH) {
2286 			cntl = MAC_EG_ADD_FIX
2287 				|MAC_EG_FORCE_READ00|MAC_EG_FORCE_READ16
2288 				|MAC_EG_DERR_ONCE;
2289 		} else {
2290 			cntl = MAC_EG_ADD_FIX|MAC_EG_FORCE_DERR00
2291 				|MAC_EG_FORCE_DERR16|MAC_EG_DERR_ONCE;
2292 		}
2293 		flags |= MC_INJECT_FLAG_ST;
2294 		break;
2295 	case MC_INJECT_INTERMITTENT_CE:
2296 	case MC_INJECT_INTERMITTENT_MCE:
2297 		if (flags & MC_INJECT_FLAG_PATH) {
2298 			cntl = MAC_EG_ADD_FIX
2299 				|MAC_EG_FORCE_READ00
2300 				|MAC_EG_DERR_ONCE;
2301 		} else {
2302 			cntl = MAC_EG_ADD_FIX
2303 				|MAC_EG_FORCE_DERR16
2304 				|MAC_EG_DERR_ONCE;
2305 		}
2306 		flags |= MC_INJECT_FLAG_ST;
2307 		break;
2308 	case MC_INJECT_PERMANENT_CE:
2309 	case MC_INJECT_PERMANENT_MCE:
2310 		if (flags & MC_INJECT_FLAG_PATH) {
2311 			cntl = MAC_EG_ADD_FIX
2312 				|MAC_EG_FORCE_READ00
2313 				|MAC_EG_DERR_ALWAYS;
2314 		} else {
2315 			cntl = MAC_EG_ADD_FIX
2316 				|MAC_EG_FORCE_DERR16
2317 				|MAC_EG_DERR_ALWAYS;
2318 		}
2319 		flags |= MC_INJECT_FLAG_ST;
2320 		break;
2321 	case MC_INJECT_CMPE:
2322 		data = 0xabcdefab;
2323 		stphys(pa, data);
2324 		cpu_flush_ecache();
2325 		MC_LOG("CMPE: writing data %x to %lx\n", data, pa);
2326 		ST_MAC_REG(MAC_MIRR(mcp, bank), MAC_MIRR_BANK_EXCLUSIVE);
2327 		stphys(pa, data ^ 0xffffffff);
2328 		cpu_flush_ecache();
2329 		ST_MAC_REG(MAC_MIRR(mcp, bank), 0);
2330 		MC_LOG("CMPE: write new data %xto %lx\n", data, pa);
2331 		cntl = 0;
2332 		break;
2333 	case MC_INJECT_NOP:
2334 		cntl = 0;
2335 		break;
2336 	default:
2337 		MC_LOG("mc_inject_error: invalid option\n");
2338 		cntl = 0;
2339 	}
2340 
2341 	if (cntl) {
2342 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl & MAC_EG_SETUP_MASK);
2343 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
2344 
2345 		if (both_sides) {
2346 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
2347 				MAC_EG_SETUP_MASK);
2348 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
2349 		}
2350 	}
2351 
2352 	/*
2353 	 * For all injection cases except compare error, we
2354 	 * must write to the PA to trigger the error.
2355 	 */
2356 
2357 	if (flags & MC_INJECT_FLAG_ST) {
2358 		data = 0xf0e0d0c0;
2359 		MC_LOG("Writing %x to %lx\n", data, pa);
2360 		stphys(pa, data);
2361 		cpu_flush_ecache();
2362 	}
2363 
2364 	delay(inject_op_delay * drv_usectohz(1000 * 1000));
2365 
2366 
2367 	if (flags & MC_INJECT_FLAG_LD) {
2368 		if (flags & MC_INJECT_FLAG_NO_TRAP) {
2369 			if (on_trap(&otd, OT_DATA_EC)) {
2370 				no_trap();
2371 				MC_LOG("Trap occurred\n");
2372 			} else {
2373 				MC_LOG("On-trap Reading from %lx\n", pa);
2374 				data = ldphys(pa);
2375 				no_trap();
2376 				MC_LOG("data = %x\n", data);
2377 			}
2378 		} else {
2379 			MC_LOG("Reading from %lx\n", pa);
2380 			data = ldphys(pa);
2381 			MC_LOG("data = %x\n", data);
2382 		}
2383 	}
2384 
2385 	if (flags & MC_INJECT_FLAG_RESTART) {
2386 		delay(inject_op_delay * drv_usectohz(1000 * 1000));
2387 
2388 		MC_LOG("Restart patrol\n");
2389 		if (mc_stop(mcp, bank)) {
2390 			cmn_err(CE_WARN, "Cannot stop Memory Patrol at "
2391 				"/LSB%d/B%d\n", mcp->mc_board_num, bank);
2392 			mutex_exit(&mcp->mc_lock);
2393 			return (EIO);
2394 		}
2395 		maddr.mi_maddr.ma_bd = mcp->mc_board_num;
2396 		maddr.mi_maddr.ma_bank = bank;
2397 		maddr.mi_maddr.ma_dimm_addr = dimm_addr;
2398 		maddr.mi_valid = 1;
2399 		maddr.mi_advance = 0;
2400 		restart_patrol(mcp, bank, &maddr);
2401 	}
2402 
2403 	if (flags & MC_INJECT_FLAG_POLL) {
2404 		delay(inject_op_delay * drv_usectohz(1000 * 1000));
2405 
2406 		MC_LOG("Poll patrol error\n");
2407 		stat = LD_MAC_REG(MAC_PTRL_STAT(mcp, bank));
2408 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
2409 		if (stat & (MAC_STAT_PTRL_ERRS|MAC_STAT_MI_ERRS)) {
2410 			maddr.mi_valid = 0;
2411 			maddr.mi_advance = 1;
2412 			if (IS_MIRROR(mcp, bank))
2413 				mc_error_handler_mir(mcp, bank,
2414 					&maddr);
2415 			else
2416 				mc_error_handler(mcp, bank, &maddr);
2417 
2418 			restart_patrol(mcp, bank, &maddr);
2419 		} else
2420 			restart_patrol(mcp, bank, NULL);
2421 	}
2422 
2423 	mutex_exit(&mcp->mc_lock);
2424 	return (0);
2425 }
2426 
2427 void
2428 mc_stphysio(uint64_t pa, uint32_t data)
2429 {
2430 	MC_LOG("0x%x -> pa(%lx)\n", data, pa);
2431 	stphysio(pa, data);
2432 }
2433 
2434 uint32_t
2435 mc_ldphysio(uint64_t pa)
2436 {
2437 	uint32_t rv;
2438 
2439 	rv = ldphysio(pa);
2440 	MC_LOG("pa(%lx) = 0x%x\n", pa, rv);
2441 	return (rv);
2442 }
2443