1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24 /*
25 * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2008
26 */
27
28 #include <sys/types.h>
29 #include <sys/sysmacros.h>
30 #include <sys/conf.h>
31 #include <sys/modctl.h>
32 #include <sys/stat.h>
33 #include <sys/async.h>
34 #include <sys/machcpuvar.h>
35 #include <sys/machsystm.h>
36 #include <sys/promif.h>
37 #include <sys/ksynch.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/sunndi.h>
41 #include <sys/ddifm.h>
42 #include <sys/fm/protocol.h>
43 #include <sys/fm/util.h>
44 #include <sys/kmem.h>
45 #include <sys/fm/io/opl_mc_fm.h>
46 #include <sys/memlist.h>
47 #include <sys/param.h>
48 #include <sys/disp.h>
49 #include <vm/page.h>
50 #include <sys/mc-opl.h>
51 #include <sys/opl.h>
52 #include <sys/opl_dimm.h>
53 #include <sys/scfd/scfostoescf.h>
54 #include <sys/cpu_module.h>
55 #include <vm/seg_kmem.h>
56 #include <sys/vmem.h>
57 #include <vm/hat_sfmmu.h>
58 #include <sys/vmsystm.h>
59 #include <sys/membar.h>
60 #include <sys/mem.h>
61
62 /*
63 * Function prototypes
64 */
65 static int mc_open(dev_t *, int, int, cred_t *);
66 static int mc_close(dev_t, int, int, cred_t *);
67 static int mc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
68 static int mc_attach(dev_info_t *, ddi_attach_cmd_t);
69 static int mc_detach(dev_info_t *, ddi_detach_cmd_t);
70
71 static int mc_poll_init(void);
72 static void mc_poll_fini(void);
73 static int mc_board_add(mc_opl_t *mcp);
74 static int mc_board_del(mc_opl_t *mcp);
75 static int mc_suspend(mc_opl_t *mcp, uint32_t flag);
76 static int mc_resume(mc_opl_t *mcp, uint32_t flag);
77 int opl_mc_suspend(void);
78 int opl_mc_resume(void);
79
80 static void insert_mcp(mc_opl_t *mcp);
81 static void delete_mcp(mc_opl_t *mcp);
82
83 static int pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr);
84
85 static int mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa);
86
87 int mc_get_mem_unum(int, uint64_t, char *, int, int *);
88 int mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr);
89 int mc_get_mem_offset(uint64_t paddr, uint64_t *offp);
90 int mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp);
91 int mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
92 int buflen, int *lenp);
93 mc_dimm_info_t *mc_get_dimm_list(mc_opl_t *mcp);
94 mc_dimm_info_t *mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp);
95 int mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int lsb, int bank,
96 uint32_t mf_type, uint32_t d_slot);
97 static void mc_free_dimm_list(mc_dimm_info_t *d);
98 static void mc_get_mlist(mc_opl_t *);
99 static void mc_polling(void);
100 static int mc_opl_get_physical_board(int);
101
102 static void mc_clear_rewrite(mc_opl_t *mcp, int i);
103 static void mc_set_rewrite(mc_opl_t *mcp, int bank, uint32_t addr, int state);
104 static int mc_scf_log_event(mc_flt_page_t *flt_pag);
105
106 #ifdef DEBUG
107 static int mc_ioctl_debug(dev_t, int, intptr_t, int, cred_t *, int *);
108 void mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz);
109 void mc_dump_dimm_info(board_dimm_info_t *bd_dimmp);
110 #endif
111
112 #pragma weak opl_get_physical_board
113 extern int opl_get_physical_board(int);
114 extern int plat_max_boards(void);
115
116 /*
117 * Configuration data structures
118 */
119 static struct cb_ops mc_cb_ops = {
120 mc_open, /* open */
121 mc_close, /* close */
122 nulldev, /* strategy */
123 nulldev, /* print */
124 nodev, /* dump */
125 nulldev, /* read */
126 nulldev, /* write */
127 mc_ioctl, /* ioctl */
128 nodev, /* devmap */
129 nodev, /* mmap */
130 nodev, /* segmap */
131 nochpoll, /* poll */
132 ddi_prop_op, /* cb_prop_op */
133 0, /* streamtab */
134 D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
135 CB_REV, /* rev */
136 nodev, /* cb_aread */
137 nodev /* cb_awrite */
138 };
139
140 static struct dev_ops mc_ops = {
141 DEVO_REV, /* rev */
142 0, /* refcnt */
143 ddi_getinfo_1to1, /* getinfo */
144 nulldev, /* identify */
145 nulldev, /* probe */
146 mc_attach, /* attach */
147 mc_detach, /* detach */
148 nulldev, /* reset */
149 &mc_cb_ops, /* cb_ops */
150 (struct bus_ops *)0, /* bus_ops */
151 nulldev, /* power */
152 ddi_quiesce_not_needed, /* quiesce */
153 };
154
155 /*
156 * Driver globals
157 */
158
159 static enum {
160 MODEL_FF1,
161 MODEL_FF2,
162 MODEL_DC,
163 MODEL_IKKAKU
164 } plat_model = MODEL_DC; /* The default behaviour is DC */
165
166 static struct plat_model_names {
167 const char *unit_name;
168 const char *mem_name;
169 } model_names[] = {
170 { "MBU_A", "MEMB" },
171 { "MBU_B", "MEMB" },
172 { "CMU", "" },
173 { "MBU_A", "" }
174 };
175
176 /*
177 * The DIMM Names for DC platform.
178 * The index into this table is made up of (bank, dslot),
179 * Where dslot occupies bits 0-1 and bank occupies 2-4.
180 */
181 static char *mc_dc_dimm_unum_table[OPL_MAX_DIMMS] = {
182 /* --------CMUnn----------- */
183 /* --CS0-----|--CS1------ */
184 /* -H-|--L-- | -H- | -L-- */
185 "03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
186 "13A", "12A", "13B", "12B", /* Bank 1 (MAC 0 bank 1) */
187 "23A", "22A", "23B", "22B", /* Bank 2 (MAC 1 bank 0) */
188 "33A", "32A", "33B", "32B", /* Bank 3 (MAC 1 bank 1) */
189 "01A", "00A", "01B", "00B", /* Bank 4 (MAC 2 bank 0) */
190 "11A", "10A", "11B", "10B", /* Bank 5 (MAC 2 bank 1) */
191 "21A", "20A", "21B", "20B", /* Bank 6 (MAC 3 bank 0) */
192 "31A", "30A", "31B", "30B" /* Bank 7 (MAC 3 bank 1) */
193 };
194
195 /*
196 * The DIMM Names for FF1/FF2/IKKAKU platforms.
197 * The index into this table is made up of (board, bank, dslot),
198 * Where dslot occupies bits 0-1, bank occupies 2-4 and
199 * board occupies the bit 5.
200 */
201 static char *mc_ff_dimm_unum_table[2 * OPL_MAX_DIMMS] = {
202 /* --------CMU0---------- */
203 /* --CS0-----|--CS1------ */
204 /* -H-|--L-- | -H- | -L-- */
205 "03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
206 "01A", "00A", "01B", "00B", /* Bank 1 (MAC 0 bank 1) */
207 "13A", "12A", "13B", "12B", /* Bank 2 (MAC 1 bank 0) */
208 "11A", "10A", "11B", "10B", /* Bank 3 (MAC 1 bank 1) */
209 "23A", "22A", "23B", "22B", /* Bank 4 (MAC 2 bank 0) */
210 "21A", "20A", "21B", "20B", /* Bank 5 (MAC 2 bank 1) */
211 "33A", "32A", "33B", "32B", /* Bank 6 (MAC 3 bank 0) */
212 "31A", "30A", "31B", "30B", /* Bank 7 (MAC 3 bank 1) */
213 /* --------CMU1---------- */
214 /* --CS0-----|--CS1------ */
215 /* -H-|--L-- | -H- | -L-- */
216 "43A", "42A", "43B", "42B", /* Bank 0 (MAC 0 bank 0) */
217 "41A", "40A", "41B", "40B", /* Bank 1 (MAC 0 bank 1) */
218 "53A", "52A", "53B", "52B", /* Bank 2 (MAC 1 bank 0) */
219 "51A", "50A", "51B", "50B", /* Bank 3 (MAC 1 bank 1) */
220 "63A", "62A", "63B", "62B", /* Bank 4 (MAC 2 bank 0) */
221 "61A", "60A", "61B", "60B", /* Bank 5 (MAC 2 bank 1) */
222 "73A", "72A", "73B", "72B", /* Bank 6 (MAC 3 bank 0) */
223 "71A", "70A", "71B", "70B" /* Bank 7 (MAC 3 bank 1) */
224 };
225
226 #define BD_BK_SLOT_TO_INDEX(bd, bk, s) \
227 (((bd & 0x01) << 5) | ((bk & 0x07) << 2) | (s & 0x03))
228
229 #define INDEX_TO_BANK(i) (((i) & 0x1C) >> 2)
230 #define INDEX_TO_SLOT(i) ((i) & 0x03)
231
232 #define SLOT_TO_CS(slot) ((slot & 0x3) >> 1)
233
234 /* Isolation unit size is 64 MB */
235 #define MC_ISOLATION_BSIZE (64 * 1024 * 1024)
236
237 #define MC_MAX_SPEEDS 7
238
239 typedef struct {
240 uint32_t mc_speeds;
241 uint32_t mc_period;
242 } mc_scan_speed_t;
243
244 #define MC_CNTL_SPEED_SHIFT 26
245
246 /*
247 * In mirror mode, we normalized the bank idx to "even" since
248 * the HW treats them as one unit w.r.t programming.
249 * This bank index will be the "effective" bank index.
250 * All mirrored bank state info on mc_period, mc_speedup_period
251 * will be stored in the even bank structure to avoid code duplication.
252 */
253 #define MIRROR_IDX(bankidx) (bankidx & ~1)
254
255 static mc_scan_speed_t mc_scan_speeds[MC_MAX_SPEEDS] = {
256 {0x6 << MC_CNTL_SPEED_SHIFT, 0},
257 {0x5 << MC_CNTL_SPEED_SHIFT, 32},
258 {0x4 << MC_CNTL_SPEED_SHIFT, 64},
259 {0x3 << MC_CNTL_SPEED_SHIFT, 128},
260 {0x2 << MC_CNTL_SPEED_SHIFT, 256},
261 {0x1 << MC_CNTL_SPEED_SHIFT, 512},
262 {0x0 << MC_CNTL_SPEED_SHIFT, 1024}
263 };
264
265 static uint32_t mc_max_speed = (0x6 << 26);
266
267 int mc_isolation_bsize = MC_ISOLATION_BSIZE;
268 int mc_patrol_interval_sec = MC_PATROL_INTERVAL_SEC;
269 int mc_max_scf_retry = 16;
270 int mc_max_scf_logs = 64;
271 int mc_max_errlog_processed = BANKNUM_PER_SB*2;
272 int mc_scan_period = 12 * 60 * 60; /* 12 hours period */
273 int mc_max_rewrite_loop = 100;
274 int mc_rewrite_delay = 10;
275 /*
276 * it takes SCF about 300 m.s. to process a requst. We can bail out
277 * if it is busy. It does not pay to wait for it too long.
278 */
279 int mc_max_scf_loop = 2;
280 int mc_scf_delay = 100;
281 int mc_pce_dropped = 0;
282 int mc_poll_priority = MINCLSYSPRI;
283 int mc_max_rewrite_retry = 6 * 60;
284
285
286 /*
287 * Mutex hierarchy in mc-opl
288 * If both mcmutex and mc_lock must be held,
289 * mcmutex must be acquired first, and then mc_lock.
290 */
291
292 static kmutex_t mcmutex;
293 mc_opl_t *mc_instances[OPL_MAX_BOARDS];
294
295 static kmutex_t mc_polling_lock;
296 static kcondvar_t mc_polling_cv;
297 static kcondvar_t mc_poll_exit_cv;
298 static int mc_poll_cmd = 0;
299 static int mc_pollthr_running = 0;
300 int mc_timeout_period = 0; /* this is in m.s. */
301 void *mc_statep;
302
303 #ifdef DEBUG
304 int oplmc_debug = 0;
305 #endif
306
307 static int mc_debug_show_all = 0;
308
309 extern struct mod_ops mod_driverops;
310
311 static struct modldrv modldrv = {
312 &mod_driverops, /* module type, this one is a driver */
313 "OPL Memory-controller", /* module name */
314 &mc_ops, /* driver ops */
315 };
316
317 static struct modlinkage modlinkage = {
318 MODREV_1, /* rev */
319 (void *)&modldrv,
320 NULL
321 };
322
323 #pragma weak opl_get_mem_unum
324 #pragma weak opl_get_mem_sid
325 #pragma weak opl_get_mem_offset
326 #pragma weak opl_get_mem_addr
327
328 extern int (*opl_get_mem_unum)(int, uint64_t, char *, int, int *);
329 extern int (*opl_get_mem_sid)(char *unum, char *buf, int buflen, int *lenp);
330 extern int (*opl_get_mem_offset)(uint64_t paddr, uint64_t *offp);
331 extern int (*opl_get_mem_addr)(char *unum, char *sid, uint64_t offset,
332 uint64_t *paddr);
333
334
335 /*
336 * pseudo-mc node portid format
337 *
338 * [10] = 0
339 * [9] = 1
340 * [8] = LSB_ID[4] = 0
341 * [7:4] = LSB_ID[3:0]
342 * [3:0] = 0
343 *
344 */
345
346 /*
347 * These are the module initialization routines.
348 */
349 int
_init(void)350 _init(void)
351 {
352 int error;
353 int plen;
354 char model[20];
355 pnode_t node;
356
357
358 if ((error = ddi_soft_state_init(&mc_statep,
359 sizeof (mc_opl_t), 1)) != 0)
360 return (error);
361
362 if ((error = mc_poll_init()) != 0) {
363 ddi_soft_state_fini(&mc_statep);
364 return (error);
365 }
366
367 mutex_init(&mcmutex, NULL, MUTEX_DRIVER, NULL);
368 if (&opl_get_mem_unum)
369 opl_get_mem_unum = mc_get_mem_unum;
370 if (&opl_get_mem_sid)
371 opl_get_mem_sid = mc_get_mem_sid;
372 if (&opl_get_mem_offset)
373 opl_get_mem_offset = mc_get_mem_offset;
374 if (&opl_get_mem_addr)
375 opl_get_mem_addr = mc_get_mem_addr;
376
377 node = prom_rootnode();
378 plen = prom_getproplen(node, "model");
379
380 if (plen > 0 && plen < sizeof (model)) {
381 (void) prom_getprop(node, "model", model);
382 model[plen] = '\0';
383 if (strcmp(model, "FF1") == 0)
384 plat_model = MODEL_FF1;
385 else if (strcmp(model, "FF2") == 0)
386 plat_model = MODEL_FF2;
387 else if (strncmp(model, "DC", 2) == 0)
388 plat_model = MODEL_DC;
389 else if (strcmp(model, "IKKAKU") == 0)
390 plat_model = MODEL_IKKAKU;
391 }
392
393 error = mod_install(&modlinkage);
394 if (error != 0) {
395 if (&opl_get_mem_unum)
396 opl_get_mem_unum = NULL;
397 if (&opl_get_mem_sid)
398 opl_get_mem_sid = NULL;
399 if (&opl_get_mem_offset)
400 opl_get_mem_offset = NULL;
401 if (&opl_get_mem_addr)
402 opl_get_mem_addr = NULL;
403 mutex_destroy(&mcmutex);
404 mc_poll_fini();
405 ddi_soft_state_fini(&mc_statep);
406 }
407 return (error);
408 }
409
410 int
_fini(void)411 _fini(void)
412 {
413 int error;
414
415 if ((error = mod_remove(&modlinkage)) != 0)
416 return (error);
417
418 if (&opl_get_mem_unum)
419 opl_get_mem_unum = NULL;
420 if (&opl_get_mem_sid)
421 opl_get_mem_sid = NULL;
422 if (&opl_get_mem_offset)
423 opl_get_mem_offset = NULL;
424 if (&opl_get_mem_addr)
425 opl_get_mem_addr = NULL;
426
427 mutex_destroy(&mcmutex);
428 mc_poll_fini();
429 ddi_soft_state_fini(&mc_statep);
430
431 return (0);
432 }
433
434 int
_info(struct modinfo * modinfop)435 _info(struct modinfo *modinfop)
436 {
437 return (mod_info(&modlinkage, modinfop));
438 }
439
440 static void
mc_polling_thread()441 mc_polling_thread()
442 {
443 mutex_enter(&mc_polling_lock);
444 mc_pollthr_running = 1;
445 while (!(mc_poll_cmd & MC_POLL_EXIT)) {
446 mc_polling();
447 (void) cv_reltimedwait(&mc_polling_cv, &mc_polling_lock,
448 mc_timeout_period, TR_CLOCK_TICK);
449 }
450 mc_pollthr_running = 0;
451
452 /*
453 * signal if any one is waiting for this thread to exit.
454 */
455 cv_signal(&mc_poll_exit_cv);
456 mutex_exit(&mc_polling_lock);
457 thread_exit();
458 /* NOTREACHED */
459 }
460
461 static int
mc_poll_init()462 mc_poll_init()
463 {
464 mutex_init(&mc_polling_lock, NULL, MUTEX_DRIVER, NULL);
465 cv_init(&mc_polling_cv, NULL, CV_DRIVER, NULL);
466 cv_init(&mc_poll_exit_cv, NULL, CV_DRIVER, NULL);
467 return (0);
468 }
469
470 static void
mc_poll_fini()471 mc_poll_fini()
472 {
473 mutex_enter(&mc_polling_lock);
474 if (mc_pollthr_running) {
475 mc_poll_cmd = MC_POLL_EXIT;
476 cv_signal(&mc_polling_cv);
477 while (mc_pollthr_running) {
478 cv_wait(&mc_poll_exit_cv, &mc_polling_lock);
479 }
480 }
481 mutex_exit(&mc_polling_lock);
482 mutex_destroy(&mc_polling_lock);
483 cv_destroy(&mc_polling_cv);
484 cv_destroy(&mc_poll_exit_cv);
485 }
486
487 static int
mc_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)488 mc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
489 {
490 mc_opl_t *mcp;
491 int instance;
492 int rv;
493
494 /* get the instance of this devi */
495 instance = ddi_get_instance(devi);
496
497 switch (cmd) {
498 case DDI_ATTACH:
499 break;
500 case DDI_RESUME:
501 mcp = ddi_get_soft_state(mc_statep, instance);
502 rv = mc_resume(mcp, MC_DRIVER_SUSPENDED);
503 return (rv);
504 default:
505 return (DDI_FAILURE);
506 }
507
508 if (ddi_soft_state_zalloc(mc_statep, instance) != DDI_SUCCESS)
509 return (DDI_FAILURE);
510
511 if (ddi_create_minor_node(devi, "mc-opl", S_IFCHR, instance,
512 "ddi_mem_ctrl", 0) != DDI_SUCCESS) {
513 MC_LOG("mc_attach: create_minor_node failed\n");
514 return (DDI_FAILURE);
515 }
516
517 if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
518 goto bad;
519 }
520
521 if (mc_timeout_period == 0) {
522 mc_patrol_interval_sec = (int)ddi_getprop(DDI_DEV_T_ANY, devi,
523 DDI_PROP_DONTPASS, "mc-timeout-interval-sec",
524 mc_patrol_interval_sec);
525 mc_timeout_period = drv_usectohz(1000000 *
526 mc_patrol_interval_sec / OPL_MAX_BOARDS);
527 }
528
529 /* set informations in mc state */
530 mcp->mc_dip = devi;
531
532 if (mc_board_add(mcp))
533 goto bad;
534
535 insert_mcp(mcp);
536
537 /*
538 * Start the polling thread if it is not running already.
539 */
540 mutex_enter(&mc_polling_lock);
541 if (!mc_pollthr_running) {
542 (void) thread_create(NULL, 0, (void (*)())mc_polling_thread,
543 NULL, 0, &p0, TS_RUN, mc_poll_priority);
544 }
545 mutex_exit(&mc_polling_lock);
546 ddi_report_dev(devi);
547
548 return (DDI_SUCCESS);
549
550 bad:
551 ddi_remove_minor_node(devi, NULL);
552 ddi_soft_state_free(mc_statep, instance);
553 return (DDI_FAILURE);
554 }
555
556 /* ARGSUSED */
557 static int
mc_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)558 mc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
559 {
560 int rv;
561 int instance;
562 mc_opl_t *mcp;
563
564 /* get the instance of this devi */
565 instance = ddi_get_instance(devi);
566 if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
567 return (DDI_FAILURE);
568 }
569
570 switch (cmd) {
571 case DDI_SUSPEND:
572 rv = mc_suspend(mcp, MC_DRIVER_SUSPENDED);
573 return (rv);
574 case DDI_DETACH:
575 break;
576 default:
577 return (DDI_FAILURE);
578 }
579
580 delete_mcp(mcp);
581 if (mc_board_del(mcp) != DDI_SUCCESS) {
582 return (DDI_FAILURE);
583 }
584
585 ddi_remove_minor_node(devi, NULL);
586
587 /* free up the soft state */
588 ddi_soft_state_free(mc_statep, instance);
589
590 return (DDI_SUCCESS);
591 }
592
593 /* ARGSUSED */
594 static int
mc_open(dev_t * devp,int flag,int otyp,cred_t * credp)595 mc_open(dev_t *devp, int flag, int otyp, cred_t *credp)
596 {
597 return (0);
598 }
599
600 /* ARGSUSED */
601 static int
mc_close(dev_t devp,int flag,int otyp,cred_t * credp)602 mc_close(dev_t devp, int flag, int otyp, cred_t *credp)
603 {
604 return (0);
605 }
606
607 /* ARGSUSED */
608 static int
mc_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)609 mc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
610 int *rvalp)
611 {
612 mc_flt_page_t flt_page;
613
614 if (cmd == MCIOC_FAULT_PAGE) {
615 if (arg == NULL)
616 return (EINVAL);
617
618 if (ddi_copyin((const void *)arg, (void *)&flt_page,
619 sizeof (mc_flt_page_t), 0) < 0)
620 return (EFAULT);
621
622 return (mc_scf_log_event(&flt_page));
623 }
624 #ifdef DEBUG
625 return (mc_ioctl_debug(dev, cmd, arg, mode, credp, rvalp));
626 #else
627 return (ENOTTY);
628 #endif
629 }
630
631 /*
632 * PA validity check:
633 * This function return 1 if the PA is a valid PA
634 * in the running Solaris instance i.e. in physinstall
635 * Otherwise, return 0.
636 */
637
638 /* ARGSUSED */
639 static int
pa_is_valid(mc_opl_t * mcp,uint64_t addr)640 pa_is_valid(mc_opl_t *mcp, uint64_t addr)
641 {
642 if (mcp->mlist == NULL)
643 mc_get_mlist(mcp);
644
645 if (mcp->mlist && address_in_memlist(mcp->mlist, addr, 0)) {
646 return (1);
647 }
648 return (0);
649 }
650
651 /*
652 * mac-pa translation routines.
653 *
654 * Input: mc driver state, (LSB#, Bank#, DIMM address)
655 * Output: physical address
656 *
657 * Valid - return value: 0
658 * Invalid - return value: -1
659 */
660 static int
mcaddr_to_pa(mc_opl_t * mcp,mc_addr_t * maddr,uint64_t * pa)661 mcaddr_to_pa(mc_opl_t *mcp, mc_addr_t *maddr, uint64_t *pa)
662 {
663 int i;
664 uint64_t pa_offset = 0;
665 int cs = (maddr->ma_dimm_addr >> CS_SHIFT) & 1;
666 int bank = maddr->ma_bank;
667 mc_addr_t maddr1;
668 int bank0, bank1;
669
670 MC_LOG("mcaddr /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
671 maddr->ma_dimm_addr);
672
673 /* loc validity check */
674 ASSERT(maddr->ma_bd >= 0 && OPL_BOARD_MAX > maddr->ma_bd);
675 ASSERT(bank >= 0 && OPL_BANK_MAX > bank);
676
677 /* Do translation */
678 for (i = 0; i < PA_BITS_FOR_MAC; i++) {
679 int pa_bit = 0;
680 int mc_bit = mcp->mc_trans_table[cs][i];
681 if (mc_bit < MC_ADDRESS_BITS) {
682 pa_bit = (maddr->ma_dimm_addr >> mc_bit) & 1;
683 } else if (mc_bit == MP_NONE) {
684 pa_bit = 0;
685 } else if (mc_bit == MP_BANK_0) {
686 pa_bit = bank & 1;
687 } else if (mc_bit == MP_BANK_1) {
688 pa_bit = (bank >> 1) & 1;
689 } else if (mc_bit == MP_BANK_2) {
690 pa_bit = (bank >> 2) & 1;
691 }
692 pa_offset |= ((uint64_t)pa_bit) << i;
693 }
694 *pa = mcp->mc_start_address + pa_offset;
695 MC_LOG("pa = %lx\n", *pa);
696
697 if (pa_to_maddr(mcp, *pa, &maddr1) == -1) {
698 cmn_err(CE_WARN, "mcaddr_to_pa: /LSB%d/B%d/%x failed to "
699 "convert PA %lx\n", maddr->ma_bd, bank,
700 maddr->ma_dimm_addr, *pa);
701 return (-1);
702 }
703
704 /*
705 * In mirror mode, PA is always translated to the even bank.
706 */
707 if (IS_MIRROR(mcp, maddr->ma_bank)) {
708 bank0 = maddr->ma_bank & ~(1);
709 bank1 = maddr1.ma_bank & ~(1);
710 } else {
711 bank0 = maddr->ma_bank;
712 bank1 = maddr1.ma_bank;
713 }
714 /*
715 * there is no need to check ma_bd because it is generated from
716 * mcp. They are the same.
717 */
718 if ((bank0 == bank1) && (maddr->ma_dimm_addr ==
719 maddr1.ma_dimm_addr)) {
720 return (0);
721 } else {
722 MC_LOG("Translation error source /LSB%d/B%d/%x, "
723 "PA %lx, target /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
724 maddr->ma_dimm_addr, *pa, maddr1.ma_bd, maddr1.ma_bank,
725 maddr1.ma_dimm_addr);
726 return (-1);
727 }
728 }
729
730 /*
731 * PA to CS (used by pa_to_maddr).
732 */
733 static int
pa_to_cs(mc_opl_t * mcp,uint64_t pa_offset)734 pa_to_cs(mc_opl_t *mcp, uint64_t pa_offset)
735 {
736 int i;
737 int cs = 1;
738
739 for (i = 0; i < PA_BITS_FOR_MAC; i++) {
740 /* MAC address bit<29> is arranged on the same PA bit */
741 /* on both table. So we may use any table. */
742 if (mcp->mc_trans_table[0][i] == CS_SHIFT) {
743 cs = (pa_offset >> i) & 1;
744 break;
745 }
746 }
747 return (cs);
748 }
749
750 /*
751 * PA to DIMM (used by pa_to_maddr).
752 */
753 /* ARGSUSED */
754 static uint32_t
pa_to_dimm(mc_opl_t * mcp,uint64_t pa_offset)755 pa_to_dimm(mc_opl_t *mcp, uint64_t pa_offset)
756 {
757 int i;
758 int cs = pa_to_cs(mcp, pa_offset);
759 uint32_t dimm_addr = 0;
760
761 for (i = 0; i < PA_BITS_FOR_MAC; i++) {
762 int pa_bit_value = (pa_offset >> i) & 1;
763 int mc_bit = mcp->mc_trans_table[cs][i];
764 if (mc_bit < MC_ADDRESS_BITS) {
765 dimm_addr |= pa_bit_value << mc_bit;
766 }
767 }
768 dimm_addr |= cs << CS_SHIFT;
769 return (dimm_addr);
770 }
771
772 /*
773 * PA to Bank (used by pa_to_maddr).
774 */
775 static int
pa_to_bank(mc_opl_t * mcp,uint64_t pa_offset)776 pa_to_bank(mc_opl_t *mcp, uint64_t pa_offset)
777 {
778 int i;
779 int cs = pa_to_cs(mcp, pa_offset);
780 int bankno = mcp->mc_trans_table[cs][INDEX_OF_BANK_SUPPLEMENT_BIT];
781
782
783 for (i = 0; i < PA_BITS_FOR_MAC; i++) {
784 int pa_bit_value = (pa_offset >> i) & 1;
785 int mc_bit = mcp->mc_trans_table[cs][i];
786 switch (mc_bit) {
787 case MP_BANK_0:
788 bankno |= pa_bit_value;
789 break;
790 case MP_BANK_1:
791 bankno |= pa_bit_value << 1;
792 break;
793 case MP_BANK_2:
794 bankno |= pa_bit_value << 2;
795 break;
796 }
797 }
798
799 return (bankno);
800 }
801
802 /*
803 * PA to MAC address translation
804 *
805 * Input: MAC driver state, physicall adress
806 * Output: LSB#, Bank id, mac address
807 *
808 * Valid - return value: 0
809 * Invalid - return value: -1
810 */
811
812 int
pa_to_maddr(mc_opl_t * mcp,uint64_t pa,mc_addr_t * maddr)813 pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr)
814 {
815 uint64_t pa_offset;
816
817 if (!mc_rangecheck_pa(mcp, pa))
818 return (-1);
819
820 /* Do translation */
821 pa_offset = pa - mcp->mc_start_address;
822
823 maddr->ma_bd = mcp->mc_board_num;
824 maddr->ma_phys_bd = mcp->mc_phys_board_num;
825 maddr->ma_bank = pa_to_bank(mcp, pa_offset);
826 maddr->ma_dimm_addr = pa_to_dimm(mcp, pa_offset);
827 MC_LOG("pa %lx -> mcaddr /LSB%d/B%d/%x\n", pa_offset, maddr->ma_bd,
828 maddr->ma_bank, maddr->ma_dimm_addr);
829 return (0);
830 }
831
832 /*
833 * UNUM format for DC is "/CMUnn/MEMxyZ", where
834 * nn = 00..03 for DC1 and 00..07 for DC2 and 00..15 for DC3.
835 * x = MAC 0..3
836 * y = 0..3 (slot info).
837 * Z = 'A' or 'B'
838 *
839 * UNUM format for FF1 is "/MBU_A/MEMBx/MEMyZ", where
840 * x = 0..3 (MEMB number)
841 * y = 0..3 (slot info).
842 * Z = 'A' or 'B'
843 *
844 * UNUM format for FF2 is "/MBU_B/MEMBx/MEMyZ", where
845 * x = 0..7 (MEMB number)
846 * y = 0..3 (slot info).
847 * Z = 'A' or 'B'
848 *
849 * UNUM format for IKKAKU is "/MBU_A/MEMyZ", where
850 * y = 0..3 (slot info).
851 * Z = 'A' or 'B'
852 *
853 */
854 int
mc_set_mem_unum(char * buf,int buflen,int sb,int bank,uint32_t mf_type,uint32_t d_slot)855 mc_set_mem_unum(char *buf, int buflen, int sb, int bank,
856 uint32_t mf_type, uint32_t d_slot)
857 {
858 char *dimmnm;
859 char memb_num;
860 int cs;
861 int i;
862 int j;
863
864 cs = SLOT_TO_CS(d_slot);
865
866 switch (plat_model) {
867 case MODEL_DC:
868 if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
869 mf_type == FLT_TYPE_PERMANENT_CE) {
870 i = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
871 dimmnm = mc_dc_dimm_unum_table[i];
872 (void) snprintf(buf, buflen, "/%s%02d/MEM%s",
873 model_names[plat_model].unit_name, sb, dimmnm);
874 } else {
875 i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
876 j = (cs == 0) ? i : i + 2;
877 (void) snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
878 model_names[plat_model].unit_name, sb,
879 mc_dc_dimm_unum_table[j],
880 mc_dc_dimm_unum_table[j + 1]);
881 }
882 break;
883 case MODEL_FF1:
884 case MODEL_FF2:
885 if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
886 mf_type == FLT_TYPE_PERMANENT_CE) {
887 i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
888 dimmnm = mc_ff_dimm_unum_table[i];
889 memb_num = dimmnm[0];
890 (void) snprintf(buf, buflen, "/%s/%s%c/MEM%s",
891 model_names[plat_model].unit_name,
892 model_names[plat_model].mem_name,
893 memb_num, &dimmnm[1]);
894 } else {
895 i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
896 j = (cs == 0) ? i : i + 2;
897 memb_num = mc_ff_dimm_unum_table[i][0],
898 (void) snprintf(buf, buflen, "/%s/%s%c/MEM%s MEM%s",
899 model_names[plat_model].unit_name,
900 model_names[plat_model].mem_name, memb_num,
901 &mc_ff_dimm_unum_table[j][1],
902 &mc_ff_dimm_unum_table[j + 1][1]);
903 }
904 break;
905 case MODEL_IKKAKU:
906 if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
907 mf_type == FLT_TYPE_PERMANENT_CE) {
908 i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
909 dimmnm = mc_ff_dimm_unum_table[i];
910 (void) snprintf(buf, buflen, "/%s/MEM%s",
911 model_names[plat_model].unit_name, &dimmnm[1]);
912 } else {
913 i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
914 j = (cs == 0) ? i : i + 2;
915 memb_num = mc_ff_dimm_unum_table[i][0],
916 (void) snprintf(buf, buflen, "/%s/MEM%s MEM%s",
917 model_names[plat_model].unit_name,
918 &mc_ff_dimm_unum_table[j][1],
919 &mc_ff_dimm_unum_table[j + 1][1]);
920 }
921 break;
922 default:
923 return (-1);
924 }
925 return (0);
926 }
927
928 static void
mc_ereport_post(mc_aflt_t * mc_aflt)929 mc_ereport_post(mc_aflt_t *mc_aflt)
930 {
931 char buf[FM_MAX_CLASS];
932 char device_path[MAXPATHLEN];
933 char sid[MAXPATHLEN];
934 nv_alloc_t *nva = NULL;
935 nvlist_t *ereport, *detector, *resource;
936 errorq_elem_t *eqep;
937 int nflts;
938 mc_flt_stat_t *flt_stat;
939 int i, n;
940 int blen = MAXPATHLEN;
941 char *p, *s = NULL;
942 uint32_t values[2], synd[2], dslot[2];
943 uint64_t offset = (uint64_t)-1;
944 int ret = -1;
945
946 if (panicstr) {
947 eqep = errorq_reserve(ereport_errorq);
948 if (eqep == NULL)
949 return;
950 ereport = errorq_elem_nvl(ereport_errorq, eqep);
951 nva = errorq_elem_nva(ereport_errorq, eqep);
952 } else {
953 ereport = fm_nvlist_create(nva);
954 }
955
956 /*
957 * Create the scheme "dev" FMRI.
958 */
959 detector = fm_nvlist_create(nva);
960 resource = fm_nvlist_create(nva);
961
962 nflts = mc_aflt->mflt_nflts;
963
964 ASSERT(nflts >= 1 && nflts <= 2);
965
966 flt_stat = mc_aflt->mflt_stat[0];
967 (void) ddi_pathname(mc_aflt->mflt_mcp->mc_dip, device_path);
968 (void) fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
969 device_path, NULL, NULL);
970
971 /*
972 * Encode all the common data into the ereport.
973 */
974 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s", MC_OPL_ERROR_CLASS,
975 mc_aflt->mflt_is_ptrl ? MC_OPL_PTRL_SUBCLASS : MC_OPL_MI_SUBCLASS,
976 mc_aflt->mflt_erpt_class);
977
978 MC_LOG("mc_ereport_post: ereport %s\n", buf);
979
980
981 fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
982 fm_ena_generate(mc_aflt->mflt_id, FM_ENA_FMT1), detector, NULL);
983
984 /*
985 * Set payload.
986 */
987 fm_payload_set(ereport, MC_OPL_BOARD, DATA_TYPE_UINT32,
988 flt_stat->mf_flt_maddr.ma_bd, NULL);
989
990 fm_payload_set(ereport, MC_OPL_PA, DATA_TYPE_UINT64,
991 flt_stat->mf_flt_paddr, NULL);
992
993 if (flt_stat->mf_type == FLT_TYPE_INTERMITTENT_CE ||
994 flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
995 fm_payload_set(ereport, MC_OPL_FLT_TYPE, DATA_TYPE_UINT8,
996 ECC_STICKY, NULL);
997 }
998
999 for (i = 0; i < nflts; i++)
1000 values[i] = mc_aflt->mflt_stat[i]->mf_flt_maddr.ma_bank;
1001
1002 fm_payload_set(ereport, MC_OPL_BANK, DATA_TYPE_UINT32_ARRAY, nflts,
1003 values, NULL);
1004
1005 for (i = 0; i < nflts; i++)
1006 values[i] = mc_aflt->mflt_stat[i]->mf_cntl;
1007
1008 fm_payload_set(ereport, MC_OPL_STATUS, DATA_TYPE_UINT32_ARRAY, nflts,
1009 values, NULL);
1010
1011 for (i = 0; i < nflts; i++)
1012 values[i] = mc_aflt->mflt_stat[i]->mf_err_add;
1013
1014 /* offset is set only for PCE and ICE */
1015 if (mc_aflt->mflt_stat[0]->mf_type == FLT_TYPE_INTERMITTENT_CE ||
1016 mc_aflt->mflt_stat[0]->mf_type == FLT_TYPE_PERMANENT_CE) {
1017 offset = values[0];
1018
1019 }
1020 fm_payload_set(ereport, MC_OPL_ERR_ADD, DATA_TYPE_UINT32_ARRAY, nflts,
1021 values, NULL);
1022
1023 for (i = 0; i < nflts; i++)
1024 values[i] = mc_aflt->mflt_stat[i]->mf_err_log;
1025
1026 fm_payload_set(ereport, MC_OPL_ERR_LOG, DATA_TYPE_UINT32_ARRAY, nflts,
1027 values, NULL);
1028
1029 for (i = 0; i < nflts; i++) {
1030 flt_stat = mc_aflt->mflt_stat[i];
1031 if (flt_stat->mf_errlog_valid) {
1032 synd[i] = flt_stat->mf_synd;
1033 dslot[i] = flt_stat->mf_dimm_slot;
1034 values[i] = flt_stat->mf_dram_place;
1035 } else {
1036 synd[i] = 0;
1037 dslot[i] = 0;
1038 values[i] = 0;
1039 }
1040 }
1041
1042 fm_payload_set(ereport, MC_OPL_ERR_SYND, DATA_TYPE_UINT32_ARRAY, nflts,
1043 synd, NULL);
1044
1045 fm_payload_set(ereport, MC_OPL_ERR_DIMMSLOT, DATA_TYPE_UINT32_ARRAY,
1046 nflts, dslot, NULL);
1047
1048 fm_payload_set(ereport, MC_OPL_ERR_DRAM, DATA_TYPE_UINT32_ARRAY, nflts,
1049 values, NULL);
1050
1051 device_path[0] = 0;
1052 p = &device_path[0];
1053 sid[0] = 0;
1054 s = &sid[0];
1055 ret = 0;
1056
1057 for (i = 0; i < nflts; i++) {
1058 int bank;
1059
1060 flt_stat = mc_aflt->mflt_stat[i];
1061 bank = flt_stat->mf_flt_maddr.ma_bank;
1062 ret = mc_set_mem_unum(p + strlen(p), blen,
1063 flt_stat->mf_flt_maddr.ma_phys_bd, bank, flt_stat->mf_type,
1064 flt_stat->mf_dimm_slot);
1065
1066 if (ret != 0) {
1067 cmn_err(CE_WARN,
1068 "mc_ereport_post: Failed to determine the unum "
1069 "for board=%d bank=%d type=0x%x slot=0x%x",
1070 flt_stat->mf_flt_maddr.ma_bd, bank,
1071 flt_stat->mf_type, flt_stat->mf_dimm_slot);
1072 continue;
1073 }
1074 n = strlen(device_path);
1075 blen = MAXPATHLEN - n;
1076 p = &device_path[n];
1077 if (i < (nflts - 1)) {
1078 (void) snprintf(p, blen, " ");
1079 blen--;
1080 p++;
1081 }
1082
1083 if (ret == 0) {
1084 ret = mc_set_mem_sid(mc_aflt->mflt_mcp, s + strlen(s),
1085 blen, flt_stat->mf_flt_maddr.ma_phys_bd, bank,
1086 flt_stat->mf_type, flt_stat->mf_dimm_slot);
1087
1088 }
1089 }
1090
1091 (void) fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION, NULL,
1092 device_path, (ret == 0) ? sid : NULL, (ret == 0) ? offset :
1093 (uint64_t)-1);
1094
1095 fm_payload_set(ereport, MC_OPL_RESOURCE, DATA_TYPE_NVLIST, resource,
1096 NULL);
1097
1098 if (panicstr) {
1099 errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
1100 } else {
1101 (void) fm_ereport_post(ereport, EVCH_TRYHARD);
1102 fm_nvlist_destroy(ereport, FM_NVA_FREE);
1103 fm_nvlist_destroy(detector, FM_NVA_FREE);
1104 fm_nvlist_destroy(resource, FM_NVA_FREE);
1105 }
1106 }
1107
1108
1109 static void
mc_err_drain(mc_aflt_t * mc_aflt)1110 mc_err_drain(mc_aflt_t *mc_aflt)
1111 {
1112 int rv;
1113 uint64_t pa = (uint64_t)(-1);
1114 int i;
1115
1116 MC_LOG("mc_err_drain: %s\n", mc_aflt->mflt_erpt_class);
1117 /*
1118 * we come here only when we have:
1119 * In mirror mode: MUE, SUE
1120 * In normal mode: UE, Permanent CE, Intermittent CE
1121 */
1122 for (i = 0; i < mc_aflt->mflt_nflts; i++) {
1123 rv = mcaddr_to_pa(mc_aflt->mflt_mcp,
1124 &(mc_aflt->mflt_stat[i]->mf_flt_maddr), &pa);
1125
1126 /* Ensure the pa is valid (not in isolated memory block) */
1127 if (rv == 0 && pa_is_valid(mc_aflt->mflt_mcp, pa))
1128 mc_aflt->mflt_stat[i]->mf_flt_paddr = pa;
1129 else
1130 mc_aflt->mflt_stat[i]->mf_flt_paddr = (uint64_t)-1;
1131 }
1132
1133 MC_LOG("mc_err_drain:pa = %lx\n", pa);
1134
1135 switch (page_retire_check(pa, NULL)) {
1136 case 0:
1137 case EAGAIN:
1138 MC_LOG("Page retired or pending\n");
1139 return;
1140 case EIO:
1141 /*
1142 * Do page retirement except for the PCE and ICE cases.
1143 * This is taken care by the OPL DE
1144 */
1145 if (mc_aflt->mflt_stat[0]->mf_type !=
1146 FLT_TYPE_INTERMITTENT_CE &&
1147 mc_aflt->mflt_stat[0]->mf_type != FLT_TYPE_PERMANENT_CE) {
1148 MC_LOG("offline page at pa %lx error %x\n", pa,
1149 mc_aflt->mflt_pr);
1150 (void) page_retire(pa, mc_aflt->mflt_pr);
1151 }
1152 break;
1153 case EINVAL:
1154 default:
1155 /*
1156 * Some memory do not have page structure so
1157 * we keep going in case of EINVAL.
1158 */
1159 break;
1160 }
1161
1162 for (i = 0; i < mc_aflt->mflt_nflts; i++) {
1163 mc_aflt_t mc_aflt0;
1164 if (mc_aflt->mflt_stat[i]->mf_flt_paddr != (uint64_t)-1) {
1165 mc_aflt0 = *mc_aflt;
1166 mc_aflt0.mflt_nflts = 1;
1167 mc_aflt0.mflt_stat[0] = mc_aflt->mflt_stat[i];
1168 mc_ereport_post(&mc_aflt0);
1169 }
1170 }
1171 }
1172
1173 /*
1174 * The restart address is actually defined in unit of PA[37:6]
1175 * the mac patrol will convert that to dimm offset. If the
1176 * address is not in the bank, it will continue to search for
1177 * the next PA that is within the bank.
1178 *
1179 * Also the mac patrol scans the dimms based on PA, not
1180 * dimm offset.
1181 */
1182 static int
restart_patrol(mc_opl_t * mcp,int bank,mc_rsaddr_info_t * rsaddr_info)1183 restart_patrol(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr_info)
1184 {
1185 uint64_t pa;
1186 int rv;
1187
1188 if (MC_REWRITE_MODE(mcp, bank)) {
1189 return (0);
1190 }
1191 if (rsaddr_info == NULL || (rsaddr_info->mi_valid == 0)) {
1192 MAC_PTRL_START(mcp, bank);
1193 return (0);
1194 }
1195
1196 rv = mcaddr_to_pa(mcp, &rsaddr_info->mi_restartaddr, &pa);
1197 if (rv != 0) {
1198 MC_LOG("cannot convert mcaddr to pa. use auto restart\n");
1199 MAC_PTRL_START(mcp, bank);
1200 return (0);
1201 }
1202
1203 if (!mc_rangecheck_pa(mcp, pa)) {
1204 /* pa is not on this board, just retry */
1205 cmn_err(CE_WARN, "restart_patrol: invalid address %lx "
1206 "on board %d\n", pa, mcp->mc_board_num);
1207 MAC_PTRL_START(mcp, bank);
1208 return (0);
1209 }
1210
1211 MC_LOG("restart_patrol: pa = %lx\n", pa);
1212
1213 if (!rsaddr_info->mi_injectrestart) {
1214 /*
1215 * For non-error injection restart we need to
1216 * determine if the current restart pa/page is
1217 * a "good" page. A "good" page is a page that
1218 * has not been page retired. If the current
1219 * page that contains the pa is "good", we will
1220 * do a HW auto restart and let HW patrol continue
1221 * where it last stopped. Most desired scenario.
1222 *
1223 * If the current page is not "good", we will advance
1224 * to the next page to find the next "good" page and
1225 * restart the patrol from there.
1226 */
1227 int wrapcount = 0;
1228 uint64_t origpa = pa;
1229 while (wrapcount < 2) {
1230 if (!pa_is_valid(mcp, pa)) {
1231 /*
1232 * Not in physinstall - advance to the
1233 * next memory isolation blocksize
1234 */
1235 MC_LOG("Invalid PA\n");
1236 pa = roundup(pa + 1, mc_isolation_bsize);
1237 } else {
1238 int rv;
1239 if ((rv = page_retire_check(pa, NULL)) != 0 &&
1240 rv != EAGAIN) {
1241 /*
1242 * The page is "good" (not retired),
1243 * we will use automatic HW restart
1244 * algorithm if this is the original
1245 * current starting page.
1246 */
1247 if (pa == origpa) {
1248 MC_LOG("Page has no error. "
1249 "Auto restart\n");
1250 MAC_PTRL_START(mcp, bank);
1251 return (0);
1252 } else {
1253 /*
1254 * found a subsequent good page
1255 */
1256 break;
1257 }
1258 }
1259
1260 /*
1261 * Skip to the next page
1262 */
1263 pa = roundup(pa + 1, PAGESIZE);
1264 MC_LOG("Skipping bad page to %lx\n", pa);
1265 }
1266
1267 /* Check to see if we hit the end of the memory range */
1268 if (pa >= (mcp->mc_start_address + mcp->mc_size)) {
1269 MC_LOG("Wrap around\n");
1270 pa = mcp->mc_start_address;
1271 wrapcount++;
1272 }
1273 }
1274
1275 if (wrapcount > 1) {
1276 MC_LOG("Failed to find a good page. Just restart\n");
1277 MAC_PTRL_START(mcp, bank);
1278 return (0);
1279 }
1280 }
1281
1282 /*
1283 * We reached here either:
1284 * 1. We are doing an error injection restart that specify
1285 * the exact pa/page to restart. OR
1286 * 2. We found a subsequent good page different from the
1287 * original restart pa/page.
1288 * Restart MAC patrol: PA[37:6]
1289 */
1290 MC_LOG("restart at pa = %lx\n", pa);
1291 ST_MAC_REG(MAC_RESTART_ADD(mcp, bank), MAC_RESTART_PA(pa));
1292 MAC_PTRL_START_ADD(mcp, bank);
1293
1294 return (0);
1295 }
1296
1297 static void
mc_retry_info_put(mc_retry_info_t ** q,mc_retry_info_t * p)1298 mc_retry_info_put(mc_retry_info_t **q, mc_retry_info_t *p)
1299 {
1300 ASSERT(p != NULL);
1301 p->ri_next = *q;
1302 *q = p;
1303 }
1304
1305 static mc_retry_info_t *
mc_retry_info_get(mc_retry_info_t ** q)1306 mc_retry_info_get(mc_retry_info_t **q)
1307 {
1308 mc_retry_info_t *p;
1309
1310 if ((p = *q) != NULL) {
1311 *q = p->ri_next;
1312 return (p);
1313 } else {
1314 return (NULL);
1315 }
1316 }
1317
1318 /*
1319 * Rewriting is used for two purposes.
1320 * - to correct the error in memory.
1321 * - to determine whether the error is permanent or intermittent.
1322 * It's done by writing the address in MAC_BANKm_REWRITE_ADD
1323 * and issuing REW_REQ command in MAC_BANKm_PTRL_CNRL. After that,
1324 * REW_END (and REW_CE/REW_UE if some error detected) is set when
1325 * rewrite operation is done. See 4.7.3 and 4.7.11 in Columbus2 PRM.
1326 *
1327 * Note that rewrite operation doesn't change RAW_UE to Marked UE.
1328 * Therefore, we use it only CE case.
1329 */
1330
1331 static uint32_t
do_rewrite(mc_opl_t * mcp,int bank,uint32_t dimm_addr,int retrying)1332 do_rewrite(mc_opl_t *mcp, int bank, uint32_t dimm_addr, int retrying)
1333 {
1334 uint32_t cntl;
1335 int count = 0;
1336 int max_count;
1337 int retry_state;
1338
1339 if (retrying)
1340 max_count = 1;
1341 else
1342 max_count = mc_max_rewrite_loop;
1343
1344 retry_state = RETRY_STATE_PENDING;
1345
1346 if (!retrying && MC_REWRITE_MODE(mcp, bank)) {
1347 goto timeout;
1348 }
1349
1350 retry_state = RETRY_STATE_ACTIVE;
1351
1352 /* first wait to make sure PTRL_STATUS is 0 */
1353 while (count++ < max_count) {
1354 cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1355 if (!(cntl & MAC_CNTL_PTRL_STATUS)) {
1356 count = 0;
1357 break;
1358 }
1359 drv_usecwait(mc_rewrite_delay);
1360 }
1361 if (count >= max_count)
1362 goto timeout;
1363
1364 count = 0;
1365
1366 ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), dimm_addr);
1367 MAC_REW_REQ(mcp, bank);
1368
1369 retry_state = RETRY_STATE_REWRITE;
1370
1371 do {
1372 if (count++ > max_count) {
1373 goto timeout;
1374 } else {
1375 drv_usecwait(mc_rewrite_delay);
1376 }
1377 cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1378 /*
1379 * If there are other MEMORY or PCI activities, this
1380 * will be BUSY, else it should be set immediately
1381 */
1382 } while (!(cntl & MAC_CNTL_REW_END));
1383
1384 MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
1385 return (cntl);
1386 timeout:
1387 mc_set_rewrite(mcp, bank, dimm_addr, retry_state);
1388
1389 return (0);
1390 }
1391
1392 void
mc_clear_rewrite(mc_opl_t * mcp,int bank)1393 mc_clear_rewrite(mc_opl_t *mcp, int bank)
1394 {
1395 struct mc_bank *bankp;
1396 mc_retry_info_t *retry;
1397 uint32_t rew_addr;
1398
1399 bankp = &(mcp->mc_bank[bank]);
1400 retry = bankp->mcb_active;
1401 bankp->mcb_active = NULL;
1402 mc_retry_info_put(&bankp->mcb_retry_freelist, retry);
1403
1404 again:
1405 bankp->mcb_rewrite_count = 0;
1406
1407 while (retry = mc_retry_info_get(&bankp->mcb_retry_pending)) {
1408 rew_addr = retry->ri_addr;
1409 mc_retry_info_put(&bankp->mcb_retry_freelist, retry);
1410 if (do_rewrite(mcp, bank, rew_addr, 1) == 0)
1411 break;
1412 }
1413
1414 /* we break out if no more pending rewrite or we got timeout again */
1415
1416 if (!bankp->mcb_active && !bankp->mcb_retry_pending) {
1417 if (!IS_MIRROR(mcp, bank)) {
1418 MC_CLEAR_REWRITE_MODE(mcp, bank);
1419 } else {
1420 int mbank = bank ^ 1;
1421 bankp = &(mcp->mc_bank[mbank]);
1422 if (!bankp->mcb_active && !bankp->mcb_retry_pending) {
1423 MC_CLEAR_REWRITE_MODE(mcp, bank);
1424 MC_CLEAR_REWRITE_MODE(mcp, mbank);
1425 } else {
1426 bank = mbank;
1427 goto again;
1428 }
1429 }
1430 }
1431 }
1432
1433 void
mc_set_rewrite(mc_opl_t * mcp,int bank,uint32_t addr,int state)1434 mc_set_rewrite(mc_opl_t *mcp, int bank, uint32_t addr, int state)
1435 {
1436 mc_retry_info_t *retry;
1437 struct mc_bank *bankp;
1438
1439 bankp = &mcp->mc_bank[bank];
1440
1441 retry = mc_retry_info_get(&bankp->mcb_retry_freelist);
1442
1443 if (retry == NULL) {
1444 mc_addr_t maddr;
1445 uint64_t paddr;
1446 /*
1447 * previous rewrite request has not completed yet.
1448 * So we discard this rewrite request.
1449 */
1450 maddr.ma_bd = mcp->mc_board_num;
1451 maddr.ma_bank = bank;
1452 maddr.ma_dimm_addr = addr;
1453 if (mcaddr_to_pa(mcp, &maddr, &paddr) == 0) {
1454 cmn_err(CE_WARN, "Discard CE rewrite request"
1455 " for 0x%lx (/LSB%d/B%d/%x).\n",
1456 paddr, mcp->mc_board_num, bank, addr);
1457 } else {
1458 cmn_err(CE_WARN, "Discard CE rewrite request"
1459 " for /LSB%d/B%d/%x.\n",
1460 mcp->mc_board_num, bank, addr);
1461 }
1462 return;
1463 }
1464
1465 retry->ri_addr = addr;
1466 retry->ri_state = state;
1467
1468 MC_SET_REWRITE_MODE(mcp, bank);
1469
1470 if ((state > RETRY_STATE_PENDING)) {
1471 ASSERT(bankp->mcb_active == NULL);
1472 bankp->mcb_active = retry;
1473 } else {
1474 mc_retry_info_put(&bankp->mcb_retry_pending, retry);
1475 }
1476
1477 if (IS_MIRROR(mcp, bank)) {
1478 int mbank = bank ^1;
1479 MC_SET_REWRITE_MODE(mcp, mbank);
1480 }
1481 }
1482
1483 void
mc_process_scf_log(mc_opl_t * mcp)1484 mc_process_scf_log(mc_opl_t *mcp)
1485 {
1486 int count;
1487 int n = 0;
1488 scf_log_t *p;
1489 int bank;
1490
1491 for (bank = 0; bank < BANKNUM_PER_SB; bank++) {
1492 while ((p = mcp->mc_scf_log[bank]) != NULL &&
1493 (n < mc_max_errlog_processed)) {
1494 ASSERT(bank == p->sl_bank);
1495 count = 0;
1496 while ((LD_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank))
1497 & MAC_STATIC_ERR_VLD)) {
1498 if (count++ >= (mc_max_scf_loop)) {
1499 break;
1500 }
1501 drv_usecwait(mc_scf_delay);
1502 }
1503
1504 if (count < mc_max_scf_loop) {
1505 ST_MAC_REG(MAC_STATIC_ERR_LOG(mcp, p->sl_bank),
1506 p->sl_err_log);
1507
1508 ST_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank),
1509 p->sl_err_add|MAC_STATIC_ERR_VLD);
1510 mcp->mc_scf_retry[bank] = 0;
1511 } else {
1512 /*
1513 * if we try too many times, just drop the req
1514 */
1515 if (mcp->mc_scf_retry[bank]++ <=
1516 mc_max_scf_retry) {
1517 return;
1518 } else {
1519 if ((++mc_pce_dropped & 0xff) == 0) {
1520 cmn_err(CE_WARN, "Cannot "
1521 "report CE to SCF\n");
1522 }
1523 }
1524 }
1525 n++;
1526 mcp->mc_scf_log[bank] = p->sl_next;
1527 mcp->mc_scf_total[bank]--;
1528 ASSERT(mcp->mc_scf_total[bank] >= 0);
1529 kmem_free(p, sizeof (scf_log_t));
1530 }
1531 }
1532 }
1533 void
mc_queue_scf_log(mc_opl_t * mcp,mc_flt_stat_t * flt_stat,int bank)1534 mc_queue_scf_log(mc_opl_t *mcp, mc_flt_stat_t *flt_stat, int bank)
1535 {
1536 scf_log_t *p;
1537
1538 if (mcp->mc_scf_total[bank] >= mc_max_scf_logs) {
1539 if ((++mc_pce_dropped & 0xff) == 0) {
1540 cmn_err(CE_WARN, "Too many CE requests.\n");
1541 }
1542 return;
1543 }
1544 p = kmem_zalloc(sizeof (scf_log_t), KM_SLEEP);
1545 p->sl_next = 0;
1546 p->sl_err_add = flt_stat->mf_err_add;
1547 p->sl_err_log = flt_stat->mf_err_log;
1548 p->sl_bank = bank;
1549
1550 if (mcp->mc_scf_log[bank] == NULL) {
1551 /*
1552 * we rely on mc_scf_log to detect NULL queue.
1553 * mc_scf_log_tail is irrelevant is such case.
1554 */
1555 mcp->mc_scf_log_tail[bank] = mcp->mc_scf_log[bank] = p;
1556 } else {
1557 mcp->mc_scf_log_tail[bank]->sl_next = p;
1558 mcp->mc_scf_log_tail[bank] = p;
1559 }
1560 mcp->mc_scf_total[bank]++;
1561 }
1562 /*
1563 * This routine determines what kind of CE happens, intermittent
1564 * or permanent as follows. (See 4.7.3 in Columbus2 PRM.)
1565 * - Do rewrite by issuing REW_REQ command to MAC_PTRL_CNTL register.
1566 * - If CE is still detected on the same address even after doing
1567 * rewrite operation twice, it is determined as permanent error.
1568 * - If error is not detected anymore, it is determined as intermittent
1569 * error.
1570 * - If UE is detected due to rewrite operation, it should be treated
1571 * as UE.
1572 */
1573
1574 /* ARGSUSED */
1575 static void
mc_scrub_ce(mc_opl_t * mcp,int bank,mc_flt_stat_t * flt_stat,int ptrl_error)1576 mc_scrub_ce(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat, int ptrl_error)
1577 {
1578 uint32_t cntl;
1579 int i;
1580
1581 flt_stat->mf_type = FLT_TYPE_PERMANENT_CE;
1582 /*
1583 * rewrite request 1st time reads and correct error data
1584 * and write to DIMM. 2nd rewrite request must be issued
1585 * after REW_CE/UE/END is 0. When the 2nd request is completed,
1586 * if REW_CE = 1, then it is permanent CE.
1587 */
1588 for (i = 0; i < 2; i++) {
1589 cntl = do_rewrite(mcp, bank, flt_stat->mf_err_add, 0);
1590
1591 if (cntl == 0) {
1592 /* timeout case */
1593 return;
1594 }
1595 /*
1596 * If the error becomes UE or CMPE
1597 * we return to the caller immediately.
1598 */
1599 if (cntl & MAC_CNTL_REW_UE) {
1600 if (ptrl_error)
1601 flt_stat->mf_cntl |= MAC_CNTL_PTRL_UE;
1602 else
1603 flt_stat->mf_cntl |= MAC_CNTL_MI_UE;
1604 flt_stat->mf_type = FLT_TYPE_UE;
1605 return;
1606 }
1607 if (cntl & MAC_CNTL_REW_CMPE) {
1608 if (ptrl_error)
1609 flt_stat->mf_cntl |= MAC_CNTL_PTRL_CMPE;
1610 else
1611 flt_stat->mf_cntl |= MAC_CNTL_MI_CMPE;
1612 flt_stat->mf_type = FLT_TYPE_CMPE;
1613 return;
1614 }
1615 }
1616 if (!(cntl & MAC_CNTL_REW_CE)) {
1617 flt_stat->mf_type = FLT_TYPE_INTERMITTENT_CE;
1618 }
1619
1620 if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
1621 /* report PERMANENT_CE to SP via SCF */
1622 if (!(flt_stat->mf_err_log & MAC_ERR_LOG_INVALID)) {
1623 mc_queue_scf_log(mcp, flt_stat, bank);
1624 }
1625 }
1626 }
1627
1628 #define IS_CMPE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_CMPE :\
1629 MAC_CNTL_MI_CMPE))
1630 #define IS_UE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_UE : MAC_CNTL_MI_UE))
1631 #define IS_CE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_CE : MAC_CNTL_MI_CE))
1632 #define IS_OK(cntl, f) (!((cntl) & ((f) ? MAC_CNTL_PTRL_ERRS : \
1633 MAC_CNTL_MI_ERRS)))
1634
1635
1636 static int
IS_CE_ONLY(uint32_t cntl,int ptrl_error)1637 IS_CE_ONLY(uint32_t cntl, int ptrl_error)
1638 {
1639 if (ptrl_error) {
1640 return ((cntl & MAC_CNTL_PTRL_ERRS) == MAC_CNTL_PTRL_CE);
1641 } else {
1642 return ((cntl & MAC_CNTL_MI_ERRS) == MAC_CNTL_MI_CE);
1643 }
1644 }
1645
1646 void
mc_write_cntl(mc_opl_t * mcp,int bank,uint32_t value)1647 mc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
1648 {
1649 int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
1650
1651 if (mcp->mc_speedup_period[ebank] > 0)
1652 value |= mc_max_speed;
1653 else
1654 value |= mcp->mc_speed;
1655 ST_MAC_REG(MAC_PTRL_CNTL(mcp, bank), value);
1656 }
1657
1658 static void
mc_read_ptrl_reg(mc_opl_t * mcp,int bank,mc_flt_stat_t * flt_stat)1659 mc_read_ptrl_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1660 {
1661 flt_stat->mf_cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1662 MAC_CNTL_PTRL_ERRS;
1663 flt_stat->mf_err_add = LD_MAC_REG(MAC_PTRL_ERR_ADD(mcp, bank));
1664 flt_stat->mf_err_log = LD_MAC_REG(MAC_PTRL_ERR_LOG(mcp, bank));
1665 flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1666 flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
1667 flt_stat->mf_flt_maddr.ma_bank = bank;
1668 flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1669 }
1670
1671 static void
mc_read_mi_reg(mc_opl_t * mcp,int bank,mc_flt_stat_t * flt_stat)1672 mc_read_mi_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1673 {
1674 uint32_t status, old_status;
1675
1676 status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) & MAC_CNTL_MI_ERRS;
1677 old_status = 0;
1678
1679 /* we keep reading until the status is stable */
1680 while (old_status != status) {
1681 old_status = status;
1682 flt_stat->mf_err_add = LD_MAC_REG(MAC_MI_ERR_ADD(mcp, bank));
1683 flt_stat->mf_err_log = LD_MAC_REG(MAC_MI_ERR_LOG(mcp, bank));
1684 status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1685 MAC_CNTL_MI_ERRS;
1686 if (status == old_status) {
1687 break;
1688 }
1689 }
1690
1691 flt_stat->mf_cntl = status;
1692 flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1693 flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
1694 flt_stat->mf_flt_maddr.ma_bank = bank;
1695 flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1696 }
1697
1698
1699 /*
1700 * Error philosophy for mirror mode:
1701 *
1702 * PTRL (The error address for both banks are same, since ptrl stops if it
1703 * detects error.)
1704 * - Compare error log CMPE.
1705 *
1706 * - UE-UE Report MUE. No rewrite.
1707 *
1708 * - UE-* UE-(CE/OK). Rewrite to scrub UE. Report SUE.
1709 *
1710 * - CE-* CE-(CE/OK). Scrub to determine if CE is permanent.
1711 * If CE is permanent, inform SCF. Once for each
1712 * Dimm. If CE becomes UE or CMPE, go back to above.
1713 *
1714 *
1715 * MI (The error addresses for each bank are the same or different.)
1716 * - Compare error If addresses are the same. Just CMPE, so log CMPE.
1717 * If addresses are different (this could happen
1718 * as a result of scrubbing. Report each separately.
1719 * Only report error info on each side.
1720 *
1721 * - UE-UE Addresses are the same. Report MUE.
1722 * Addresses are different. Report SUE on each bank.
1723 * Rewrite to clear UE.
1724 *
1725 * - UE-* UE-(CE/OK)
1726 * Rewrite to clear UE. Report SUE for the bank.
1727 *
1728 * - CE-* CE-(CE/OK). Scrub to determine if CE is permanent.
1729 * If CE becomes UE or CMPE, go back to above.
1730 *
1731 */
1732
1733 static int
mc_process_error_mir(mc_opl_t * mcp,mc_aflt_t * mc_aflt,mc_flt_stat_t * flt_stat)1734 mc_process_error_mir(mc_opl_t *mcp, mc_aflt_t *mc_aflt, mc_flt_stat_t *flt_stat)
1735 {
1736 int ptrl_error = mc_aflt->mflt_is_ptrl;
1737 int i;
1738 int rv = 0;
1739 int bank;
1740 int rewrite_timeout = 0;
1741
1742 MC_LOG("process mirror errors cntl[0] = %x, cntl[1] = %x\n",
1743 flt_stat[0].mf_cntl, flt_stat[1].mf_cntl);
1744
1745 if (ptrl_error) {
1746 if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl) &
1747 MAC_CNTL_PTRL_ERRS) == 0)
1748 return (0);
1749 } else {
1750 if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl) &
1751 MAC_CNTL_MI_ERRS) == 0)
1752 return (0);
1753 }
1754
1755 /*
1756 * First we take care of the case of CE
1757 * because they can become UE or CMPE
1758 */
1759 for (i = 0; i < 2; i++) {
1760 if (IS_CE_ONLY(flt_stat[i].mf_cntl, ptrl_error)) {
1761 bank = flt_stat[i].mf_flt_maddr.ma_bank;
1762 MC_LOG("CE detected on bank %d\n", bank);
1763 mc_scrub_ce(mcp, bank, &flt_stat[i], ptrl_error);
1764 if (MC_REWRITE_ACTIVE(mcp, bank)) {
1765 rewrite_timeout = 1;
1766 }
1767 rv = 1;
1768 }
1769 }
1770
1771 if (rewrite_timeout)
1772 return (0);
1773
1774 /* The above scrubbing can turn CE into UE or CMPE */
1775
1776 /*
1777 * Now we distinguish two cases: same address or not
1778 * the same address. It might seem more intuitive to
1779 * distinguish PTRL v.s. MI error but it is more
1780 * complicated that way.
1781 */
1782
1783 if (flt_stat[0].mf_err_add == flt_stat[1].mf_err_add) {
1784
1785 if (IS_CMPE(flt_stat[0].mf_cntl, ptrl_error) ||
1786 IS_CMPE(flt_stat[1].mf_cntl, ptrl_error)) {
1787 flt_stat[0].mf_type = FLT_TYPE_CMPE;
1788 flt_stat[1].mf_type = FLT_TYPE_CMPE;
1789 mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1790 mc_aflt->mflt_nflts = 2;
1791 mc_aflt->mflt_stat[0] = &flt_stat[0];
1792 mc_aflt->mflt_stat[1] = &flt_stat[1];
1793 mc_aflt->mflt_pr = PR_UE;
1794 /*
1795 * Compare error is result of MAC internal error, so
1796 * simply log it instead of publishing an ereport. SCF
1797 * diagnoses all the MAC internal and its i/f error.
1798 */
1799 MC_LOG("cmpe error detected\n");
1800 return (1);
1801 }
1802
1803 if (IS_UE(flt_stat[0].mf_cntl, ptrl_error) &&
1804 IS_UE(flt_stat[1].mf_cntl, ptrl_error)) {
1805 /* Both side are UE's */
1806
1807 MAC_SET_ERRLOG_INFO(&flt_stat[0]);
1808 MAC_SET_ERRLOG_INFO(&flt_stat[1]);
1809 MC_LOG("MUE detected\n");
1810 flt_stat[0].mf_type = FLT_TYPE_MUE;
1811 flt_stat[1].mf_type = FLT_TYPE_MUE;
1812 mc_aflt->mflt_erpt_class = MC_OPL_MUE;
1813 mc_aflt->mflt_nflts = 2;
1814 mc_aflt->mflt_stat[0] = &flt_stat[0];
1815 mc_aflt->mflt_stat[1] = &flt_stat[1];
1816 mc_aflt->mflt_pr = PR_UE;
1817 mc_err_drain(mc_aflt);
1818 return (1);
1819 }
1820
1821 /* Now the only case is UE/CE, UE/OK, or don't care */
1822 for (i = 0; i < 2; i++) {
1823 if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1824
1825 /* rewrite can clear the one side UE error */
1826
1827 if (IS_OK(flt_stat[i^1].mf_cntl, ptrl_error)) {
1828 (void) do_rewrite(mcp,
1829 flt_stat[i].mf_flt_maddr.ma_bank,
1830 flt_stat[i].mf_flt_maddr.ma_dimm_addr, 0);
1831 }
1832 flt_stat[i].mf_type = FLT_TYPE_UE;
1833 MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1834 mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1835 mc_aflt->mflt_stat[0] = &flt_stat[i];
1836 mc_aflt->mflt_nflts = 1;
1837 mc_aflt->mflt_pr = PR_MCE;
1838 mc_err_drain(mc_aflt);
1839 /* Once we hit a UE/CE or UE/OK case, done */
1840 return (1);
1841 }
1842 }
1843
1844 } else {
1845 /*
1846 * addresses are different. That means errors
1847 * on the 2 banks are not related at all.
1848 */
1849 for (i = 0; i < 2; i++) {
1850 if (IS_CMPE(flt_stat[i].mf_cntl, ptrl_error)) {
1851 flt_stat[i].mf_type = FLT_TYPE_CMPE;
1852 mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1853 mc_aflt->mflt_nflts = 1;
1854 mc_aflt->mflt_stat[0] = &flt_stat[i];
1855 mc_aflt->mflt_pr = PR_UE;
1856 /*
1857 * Compare error is result of MAC internal
1858 * error, so simply log it instead of
1859 * publishing an ereport. SCF diagnoses all
1860 * the MAC internal and its interface error.
1861 */
1862 MC_LOG("cmpe error detected\n");
1863 /* no more report on this bank */
1864 flt_stat[i].mf_cntl = 0;
1865 rv = 1;
1866 }
1867 }
1868
1869 /* rewrite can clear the one side UE error */
1870
1871 for (i = 0; i < 2; i++) {
1872 if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1873 (void) do_rewrite(mcp,
1874 flt_stat[i].mf_flt_maddr.ma_bank,
1875 flt_stat[i].mf_flt_maddr.ma_dimm_addr,
1876 0);
1877 flt_stat[i].mf_type = FLT_TYPE_UE;
1878 MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1879 mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1880 mc_aflt->mflt_stat[0] = &flt_stat[i];
1881 mc_aflt->mflt_nflts = 1;
1882 mc_aflt->mflt_pr = PR_MCE;
1883 mc_err_drain(mc_aflt);
1884 rv = 1;
1885 }
1886 }
1887 }
1888 return (rv);
1889 }
1890 static void
mc_error_handler_mir(mc_opl_t * mcp,int bank,mc_rsaddr_info_t * rsaddr)1891 mc_error_handler_mir(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
1892 {
1893 mc_aflt_t mc_aflt;
1894 mc_flt_stat_t flt_stat[2], mi_flt_stat[2];
1895 int i;
1896 int mi_valid;
1897
1898 ASSERT(rsaddr);
1899
1900 bzero(&mc_aflt, sizeof (mc_aflt_t));
1901 bzero(&flt_stat, 2 * sizeof (mc_flt_stat_t));
1902 bzero(&mi_flt_stat, 2 * sizeof (mc_flt_stat_t));
1903
1904
1905 mc_aflt.mflt_mcp = mcp;
1906 mc_aflt.mflt_id = gethrtime();
1907
1908 /* Now read all the registers into flt_stat */
1909
1910 for (i = 0; i < 2; i++) {
1911 MC_LOG("Reading registers of bank %d\n", bank);
1912 /* patrol registers */
1913 mc_read_ptrl_reg(mcp, bank, &flt_stat[i]);
1914
1915 /*
1916 * In mirror mode, it is possible that only one bank
1917 * may report the error. We need to check for it to
1918 * ensure we pick the right addr value for patrol restart.
1919 * Note that if both banks reported errors, we pick the
1920 * 2nd one. Both banks should reported the same error address.
1921 */
1922 if (flt_stat[i].mf_cntl & MAC_CNTL_PTRL_ERRS)
1923 rsaddr->mi_restartaddr = flt_stat[i].mf_flt_maddr;
1924
1925 MC_LOG("ptrl registers cntl %x add %x log %x\n",
1926 flt_stat[i].mf_cntl, flt_stat[i].mf_err_add,
1927 flt_stat[i].mf_err_log);
1928
1929 /* MI registers */
1930 mc_read_mi_reg(mcp, bank, &mi_flt_stat[i]);
1931
1932 MC_LOG("MI registers cntl %x add %x log %x\n",
1933 mi_flt_stat[i].mf_cntl, mi_flt_stat[i].mf_err_add,
1934 mi_flt_stat[i].mf_err_log);
1935
1936 bank = bank^1;
1937 }
1938
1939 /* clear errors once we read all the registers */
1940 MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1941
1942 MAC_CLEAR_ERRS(mcp, bank ^ 1, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1943
1944 /* Process MI errors first */
1945
1946 /* if not error mode, cntl1 is 0 */
1947 if ((mi_flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
1948 (mi_flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
1949 mi_flt_stat[0].mf_cntl = 0;
1950
1951 if ((mi_flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
1952 (mi_flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
1953 mi_flt_stat[1].mf_cntl = 0;
1954
1955 mc_aflt.mflt_is_ptrl = 0;
1956 mi_valid = mc_process_error_mir(mcp, &mc_aflt, &mi_flt_stat[0]);
1957
1958 if ((((flt_stat[0].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
1959 MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat[0].mf_cntl &
1960 MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
1961 (flt_stat[0].mf_err_add ==
1962 ROUNDDOWN(mi_flt_stat[0].mf_err_add, MC_BOUND_BYTE)) &&
1963 (((flt_stat[1].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
1964 MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat[1].mf_cntl &
1965 MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
1966 (flt_stat[1].mf_err_add ==
1967 ROUNDDOWN(mi_flt_stat[1].mf_err_add, MC_BOUND_BYTE))) {
1968 #ifdef DEBUG
1969 MC_LOG("discarding PTRL error because "
1970 "it is the same as MI\n");
1971 #endif
1972 rsaddr->mi_valid = mi_valid;
1973 return;
1974 }
1975 /* if not error mode, cntl1 is 0 */
1976 if ((flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
1977 (flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
1978 flt_stat[0].mf_cntl = 0;
1979
1980 if ((flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
1981 (flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
1982 flt_stat[1].mf_cntl = 0;
1983
1984 mc_aflt.mflt_is_ptrl = 1;
1985 rsaddr->mi_valid = mc_process_error_mir(mcp, &mc_aflt, &flt_stat[0]);
1986 }
1987 static int
mc_process_error(mc_opl_t * mcp,int bank,mc_aflt_t * mc_aflt,mc_flt_stat_t * flt_stat)1988 mc_process_error(mc_opl_t *mcp, int bank, mc_aflt_t *mc_aflt,
1989 mc_flt_stat_t *flt_stat)
1990 {
1991 int ptrl_error = mc_aflt->mflt_is_ptrl;
1992 int rv = 0;
1993
1994 mc_aflt->mflt_erpt_class = NULL;
1995 if (IS_UE(flt_stat->mf_cntl, ptrl_error)) {
1996 MC_LOG("UE detected\n");
1997 flt_stat->mf_type = FLT_TYPE_UE;
1998 mc_aflt->mflt_erpt_class = MC_OPL_UE;
1999 mc_aflt->mflt_pr = PR_UE;
2000 MAC_SET_ERRLOG_INFO(flt_stat);
2001 rv = 1;
2002 } else if (IS_CE(flt_stat->mf_cntl, ptrl_error)) {
2003 MC_LOG("CE detected\n");
2004 MAC_SET_ERRLOG_INFO(flt_stat);
2005
2006 /* Error type can change after scrubbing */
2007 mc_scrub_ce(mcp, bank, flt_stat, ptrl_error);
2008 if (MC_REWRITE_ACTIVE(mcp, bank)) {
2009 return (0);
2010 }
2011
2012 if (flt_stat->mf_type == FLT_TYPE_INTERMITTENT_CE) {
2013 mc_aflt->mflt_erpt_class = MC_OPL_ICE;
2014 mc_aflt->mflt_pr = PR_MCE;
2015 } else if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
2016 mc_aflt->mflt_erpt_class = MC_OPL_CE;
2017 mc_aflt->mflt_pr = PR_MCE;
2018 } else if (flt_stat->mf_type == FLT_TYPE_UE) {
2019 mc_aflt->mflt_erpt_class = MC_OPL_UE;
2020 mc_aflt->mflt_pr = PR_UE;
2021 }
2022 rv = 1;
2023 }
2024 MC_LOG("mc_process_error: fault type %x erpt %s\n", flt_stat->mf_type,
2025 mc_aflt->mflt_erpt_class);
2026 if (mc_aflt->mflt_erpt_class) {
2027 mc_aflt->mflt_stat[0] = flt_stat;
2028 mc_aflt->mflt_nflts = 1;
2029 mc_err_drain(mc_aflt);
2030 }
2031 return (rv);
2032 }
2033
2034 static void
mc_error_handler(mc_opl_t * mcp,int bank,mc_rsaddr_info_t * rsaddr)2035 mc_error_handler(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
2036 {
2037 mc_aflt_t mc_aflt;
2038 mc_flt_stat_t flt_stat, mi_flt_stat;
2039 int mi_valid;
2040
2041 bzero(&mc_aflt, sizeof (mc_aflt_t));
2042 bzero(&flt_stat, sizeof (mc_flt_stat_t));
2043 bzero(&mi_flt_stat, sizeof (mc_flt_stat_t));
2044
2045 mc_aflt.mflt_mcp = mcp;
2046 mc_aflt.mflt_id = gethrtime();
2047
2048 /* patrol registers */
2049 mc_read_ptrl_reg(mcp, bank, &flt_stat);
2050
2051 ASSERT(rsaddr);
2052 rsaddr->mi_restartaddr = flt_stat.mf_flt_maddr;
2053
2054 MC_LOG("ptrl registers cntl %x add %x log %x\n", flt_stat.mf_cntl,
2055 flt_stat.mf_err_add, flt_stat.mf_err_log);
2056
2057 /* MI registers */
2058 mc_read_mi_reg(mcp, bank, &mi_flt_stat);
2059
2060
2061 MC_LOG("MI registers cntl %x add %x log %x\n", mi_flt_stat.mf_cntl,
2062 mi_flt_stat.mf_err_add, mi_flt_stat.mf_err_log);
2063
2064 /* clear errors once we read all the registers */
2065 MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
2066
2067 mc_aflt.mflt_is_ptrl = 0;
2068 if ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) &&
2069 ((mi_flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
2070 ((mi_flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
2071 mi_valid = mc_process_error(mcp, bank, &mc_aflt, &mi_flt_stat);
2072 }
2073
2074 if ((((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) >>
2075 MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat.mf_cntl &
2076 MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
2077 (flt_stat.mf_err_add ==
2078 ROUNDDOWN(mi_flt_stat.mf_err_add, MC_BOUND_BYTE))) {
2079 #ifdef DEBUG
2080 MC_LOG("discarding PTRL error because "
2081 "it is the same as MI\n");
2082 #endif
2083 rsaddr->mi_valid = mi_valid;
2084 return;
2085 }
2086
2087 mc_aflt.mflt_is_ptrl = 1;
2088 if ((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) &&
2089 ((flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
2090 ((flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
2091 rsaddr->mi_valid = mc_process_error(mcp, bank, &mc_aflt,
2092 &flt_stat);
2093 }
2094 }
2095 /*
2096 * memory patrol error handling algorithm:
2097 * timeout() is used to do periodic polling
2098 * This is the flow chart.
2099 * timeout ->
2100 * mc_check_errors()
2101 * if memory bank is installed, read the status register
2102 * if any error bit is set,
2103 * -> mc_error_handler()
2104 * -> read all error registers
2105 * -> mc_process_error()
2106 * determine error type
2107 * rewrite to clear error or scrub to determine CE type
2108 * inform SCF on permanent CE
2109 * -> mc_err_drain
2110 * page offline processing
2111 * -> mc_ereport_post()
2112 */
2113
2114 static void
mc_process_rewrite(mc_opl_t * mcp,int bank)2115 mc_process_rewrite(mc_opl_t *mcp, int bank)
2116 {
2117 uint32_t rew_addr, cntl;
2118 mc_retry_info_t *retry;
2119 struct mc_bank *bankp;
2120
2121 bankp = &(mcp->mc_bank[bank]);
2122 retry = bankp->mcb_active;
2123 if (retry == NULL)
2124 return;
2125
2126 if (retry->ri_state <= RETRY_STATE_ACTIVE) {
2127 cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
2128 if (cntl & MAC_CNTL_PTRL_STATUS)
2129 return;
2130 rew_addr = retry->ri_addr;
2131 ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), rew_addr);
2132 MAC_REW_REQ(mcp, bank);
2133
2134 retry->ri_state = RETRY_STATE_REWRITE;
2135 }
2136
2137 cntl = ldphysio(MAC_PTRL_CNTL(mcp, bank));
2138
2139 if (cntl & MAC_CNTL_REW_END) {
2140 MAC_CLEAR_ERRS(mcp, bank,
2141 MAC_CNTL_REW_ERRS);
2142 mc_clear_rewrite(mcp, bank);
2143 } else {
2144 /*
2145 * If the rewrite does not complete in
2146 * 1 hour, we have to consider this a HW
2147 * failure. However, there is no recovery
2148 * mechanism. The only thing we can do
2149 * to to print a warning message to the
2150 * console. We continue to increment the
2151 * counter but we only print the message
2152 * once. It will take the counter a long
2153 * time to wrap around and the user might
2154 * see a second message. In practice,
2155 * we have never hit this condition but
2156 * we have to keep the code here just in case.
2157 */
2158 if (++mcp->mc_bank[bank].mcb_rewrite_count
2159 == mc_max_rewrite_retry) {
2160 cmn_err(CE_WARN, "Memory patrol feature is"
2161 " partly suspended on /LSB%d/B%d"
2162 " due to heavy memory load,"
2163 " and it will restart"
2164 " automatically.\n", mcp->mc_board_num,
2165 bank);
2166 }
2167 }
2168 }
2169
2170 static void
mc_check_errors_func(mc_opl_t * mcp)2171 mc_check_errors_func(mc_opl_t *mcp)
2172 {
2173 mc_rsaddr_info_t rsaddr_info;
2174 int i, error_count = 0;
2175 uint32_t stat, cntl;
2176 int running;
2177 int wrapped;
2178 int ebk;
2179
2180 /*
2181 * scan errors.
2182 */
2183 if (mcp->mc_status & MC_MEMORYLESS)
2184 return;
2185
2186 for (i = 0; i < BANKNUM_PER_SB; i++) {
2187 if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2188 if (MC_REWRITE_ACTIVE(mcp, i)) {
2189 mc_process_rewrite(mcp, i);
2190 }
2191 stat = ldphysio(MAC_PTRL_STAT(mcp, i));
2192 cntl = ldphysio(MAC_PTRL_CNTL(mcp, i));
2193 running = cntl & MAC_CNTL_PTRL_START;
2194 wrapped = cntl & MAC_CNTL_PTRL_ADD_MAX;
2195
2196 /* Compute the effective bank idx */
2197 ebk = (IS_MIRROR(mcp, i)) ? MIRROR_IDX(i) : i;
2198
2199 if (mc_debug_show_all || stat) {
2200 MC_LOG("/LSB%d/B%d stat %x cntl %x\n",
2201 mcp->mc_board_num, i, stat, cntl);
2202 }
2203
2204 /*
2205 * Update stats and reset flag if the HW patrol
2206 * wrapped around in its scan.
2207 */
2208 if (wrapped) {
2209 MAC_CLEAR_MAX(mcp, i);
2210 mcp->mc_period[ebk]++;
2211 if (IS_MIRROR(mcp, i)) {
2212 MC_LOG("mirror mc period %ld on "
2213 "/LSB%d/B%d\n", mcp->mc_period[ebk],
2214 mcp->mc_board_num, i);
2215 } else {
2216 MC_LOG("mc period %ld on "
2217 "/LSB%d/B%d\n", mcp->mc_period[ebk],
2218 mcp->mc_board_num, i);
2219 }
2220 }
2221
2222 if (running) {
2223 /*
2224 * Mac patrol HW is still running.
2225 * Normally when an error is detected,
2226 * the HW patrol will stop so that we
2227 * can collect error data for reporting.
2228 * Certain errors (MI errors) detected may not
2229 * cause the HW patrol to stop which is a
2230 * problem since we cannot read error data while
2231 * the HW patrol is running. SW is not allowed
2232 * to stop the HW patrol while it is running
2233 * as it may cause HW inconsistency. This is
2234 * described in a HW errata.
2235 * In situations where we detected errors
2236 * that may not cause the HW patrol to stop.
2237 * We speed up the HW patrol scanning in
2238 * the hope that it will find the 'real' PTRL
2239 * errors associated with the previous errors
2240 * causing the HW to finally stop so that we
2241 * can do the reporting.
2242 */
2243 /*
2244 * Check to see if we did speed up
2245 * the HW patrol due to previous errors
2246 * detected that did not cause the patrol
2247 * to stop. We only do it if HW patrol scan
2248 * wrapped (counted as completing a 'period').
2249 */
2250 if (mcp->mc_speedup_period[ebk] > 0) {
2251 if (wrapped &&
2252 (--mcp->mc_speedup_period[ebk] ==
2253 0)) {
2254 /*
2255 * We did try to speed up.
2256 * The speed up period has
2257 * expired and the HW patrol
2258 * is still running. The
2259 * errors must be intermittent.
2260 * We have no choice but to
2261 * ignore them, reset the scan
2262 * speed to normal and clear
2263 * the MI error bits. For
2264 * mirror mode, we need to
2265 * clear errors on both banks.
2266 */
2267 MC_LOG("Clearing MI errors\n");
2268 MAC_CLEAR_ERRS(mcp, i,
2269 MAC_CNTL_MI_ERRS);
2270
2271 if (IS_MIRROR(mcp, i)) {
2272 MC_LOG("Clearing "
2273 "Mirror MI errs\n");
2274 MAC_CLEAR_ERRS(mcp,
2275 i^1,
2276 MAC_CNTL_MI_ERRS);
2277 }
2278 }
2279 } else if (stat & MAC_STAT_MI_ERRS) {
2280 /*
2281 * MI errors detected but we cannot
2282 * report them since the HW patrol
2283 * is still running.
2284 * We will attempt to speed up the
2285 * scanning and hopefully the HW
2286 * can detect PRTL errors at the same
2287 * location that cause the HW patrol
2288 * to stop.
2289 */
2290 mcp->mc_speedup_period[ebk] = 2;
2291 MAC_CMD(mcp, i, 0);
2292 }
2293 } else if (stat & (MAC_STAT_PTRL_ERRS |
2294 MAC_STAT_MI_ERRS)) {
2295 /*
2296 * HW Patrol has stopped and we found errors.
2297 * Proceed to collect and report error info.
2298 */
2299 mcp->mc_speedup_period[ebk] = 0;
2300 rsaddr_info.mi_valid = 0;
2301 rsaddr_info.mi_injectrestart = 0;
2302 if (IS_MIRROR(mcp, i)) {
2303 mc_error_handler_mir(mcp, i,
2304 &rsaddr_info);
2305 } else {
2306 mc_error_handler(mcp, i, &rsaddr_info);
2307 }
2308
2309 error_count++;
2310 (void) restart_patrol(mcp, i, &rsaddr_info);
2311 } else {
2312 /*
2313 * HW patrol scan has apparently stopped
2314 * but no errors detected/flagged.
2315 * Restart the HW patrol just to be sure.
2316 * In mirror mode, the odd bank might have
2317 * reported errors that caused the patrol to
2318 * stop. We'll defer the restart to the odd
2319 * bank in this case.
2320 */
2321 if (!IS_MIRROR(mcp, i) || (i & 0x1))
2322 (void) restart_patrol(mcp, i, NULL);
2323 }
2324 }
2325 }
2326 if (error_count > 0)
2327 mcp->mc_last_error += error_count;
2328 else
2329 mcp->mc_last_error = 0;
2330 }
2331
2332 /*
2333 * mc_polling -- Check errors for only one instance,
2334 * but process errors for all instances to make sure we drain the errors
2335 * faster than they can be accumulated.
2336 *
2337 * Polling on each board should be done only once per each
2338 * mc_patrol_interval_sec. This is equivalent to setting mc_tick_left
2339 * to OPL_MAX_BOARDS and decrement by 1 on each timeout.
2340 * Once mc_tick_left becomes negative, the board becomes a candidate
2341 * for polling because it has waited for at least
2342 * mc_patrol_interval_sec's long. If mc_timeout_period is calculated
2343 * differently, this has to be updated accordingly.
2344 */
2345
2346 static void
mc_polling(void)2347 mc_polling(void)
2348 {
2349 int i, scan_error;
2350 mc_opl_t *mcp;
2351
2352
2353 scan_error = 1;
2354 for (i = 0; i < OPL_MAX_BOARDS; i++) {
2355 mutex_enter(&mcmutex);
2356 if ((mcp = mc_instances[i]) == NULL) {
2357 mutex_exit(&mcmutex);
2358 continue;
2359 }
2360 mutex_enter(&mcp->mc_lock);
2361 mutex_exit(&mcmutex);
2362 if (!(mcp->mc_status & MC_POLL_RUNNING)) {
2363 mutex_exit(&mcp->mc_lock);
2364 continue;
2365 }
2366 if (scan_error && mcp->mc_tick_left <= 0) {
2367 mc_check_errors_func((void *)mcp);
2368 mcp->mc_tick_left = OPL_MAX_BOARDS;
2369 scan_error = 0;
2370 } else {
2371 mcp->mc_tick_left--;
2372 }
2373 mc_process_scf_log(mcp);
2374 mutex_exit(&mcp->mc_lock);
2375 }
2376 }
2377
2378 static void
get_ptrl_start_address(mc_opl_t * mcp,int bank,mc_addr_t * maddr)2379 get_ptrl_start_address(mc_opl_t *mcp, int bank, mc_addr_t *maddr)
2380 {
2381 maddr->ma_bd = mcp->mc_board_num;
2382 maddr->ma_bank = bank;
2383 maddr->ma_dimm_addr = 0;
2384 }
2385
2386 typedef struct mc_mem_range {
2387 uint64_t addr;
2388 uint64_t size;
2389 } mc_mem_range_t;
2390
2391 static int
get_base_address(mc_opl_t * mcp)2392 get_base_address(mc_opl_t *mcp)
2393 {
2394 mc_mem_range_t *mem_range;
2395 int len;
2396
2397 if (ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2398 "sb-mem-ranges", (caddr_t)&mem_range, &len) != DDI_SUCCESS) {
2399 return (DDI_FAILURE);
2400 }
2401
2402 mcp->mc_start_address = mem_range->addr;
2403 mcp->mc_size = mem_range->size;
2404
2405 kmem_free(mem_range, len);
2406 return (DDI_SUCCESS);
2407 }
2408
2409 struct mc_addr_spec {
2410 uint32_t bank;
2411 uint32_t phys_hi;
2412 uint32_t phys_lo;
2413 };
2414
2415 #define REGS_PA(m, i) ((((uint64_t)m[i].phys_hi)<<32) | m[i].phys_lo)
2416
2417 static char *mc_tbl_name[] = {
2418 "cs0-mc-pa-trans-table",
2419 "cs1-mc-pa-trans-table"
2420 };
2421
2422 /*
2423 * This routine performs a rangecheck for a given PA
2424 * to see if it belongs to the memory range for this board.
2425 * Return 1 if it is valid (within the range) and 0 otherwise
2426 */
2427 static int
mc_rangecheck_pa(mc_opl_t * mcp,uint64_t pa)2428 mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa)
2429 {
2430 if ((pa < mcp->mc_start_address) || (mcp->mc_start_address +
2431 mcp->mc_size <= pa))
2432 return (0);
2433 else
2434 return (1);
2435 }
2436
2437 static void
mc_memlist_delete(struct memlist * mlist)2438 mc_memlist_delete(struct memlist *mlist)
2439 {
2440 struct memlist *ml;
2441
2442 for (ml = mlist; ml; ml = mlist) {
2443 mlist = ml->ml_next;
2444 kmem_free(ml, sizeof (struct memlist));
2445 }
2446 }
2447
2448 static struct memlist *
mc_memlist_dup(struct memlist * mlist)2449 mc_memlist_dup(struct memlist *mlist)
2450 {
2451 struct memlist *hl = NULL, *tl, **mlp;
2452
2453 if (mlist == NULL)
2454 return (NULL);
2455
2456 mlp = &hl;
2457 tl = *mlp;
2458 for (; mlist; mlist = mlist->ml_next) {
2459 *mlp = kmem_alloc(sizeof (struct memlist), KM_SLEEP);
2460 (*mlp)->ml_address = mlist->ml_address;
2461 (*mlp)->ml_size = mlist->ml_size;
2462 (*mlp)->ml_prev = tl;
2463 tl = *mlp;
2464 mlp = &((*mlp)->ml_next);
2465 }
2466 *mlp = NULL;
2467
2468 return (hl);
2469 }
2470
2471
2472 static struct memlist *
mc_memlist_del_span(struct memlist * mlist,uint64_t base,uint64_t len)2473 mc_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
2474 {
2475 uint64_t end;
2476 struct memlist *ml, *tl, *nlp;
2477
2478 if (mlist == NULL)
2479 return (NULL);
2480
2481 end = base + len;
2482 if ((end <= mlist->ml_address) || (base == end))
2483 return (mlist);
2484
2485 for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
2486 uint64_t mend;
2487
2488 nlp = ml->ml_next;
2489
2490 if (end <= ml->ml_address)
2491 break;
2492
2493 mend = ml->ml_address + ml->ml_size;
2494 if (base < mend) {
2495 if (base <= ml->ml_address) {
2496 ml->ml_address = end;
2497 if (end >= mend)
2498 ml->ml_size = 0ull;
2499 else
2500 ml->ml_size = mend - ml->ml_address;
2501 } else {
2502 ml->ml_size = base - ml->ml_address;
2503 if (end < mend) {
2504 struct memlist *nl;
2505 /*
2506 * splitting an memlist entry.
2507 */
2508 nl = kmem_alloc(sizeof (struct memlist),
2509 KM_SLEEP);
2510 nl->ml_address = end;
2511 nl->ml_size = mend - nl->ml_address;
2512 if ((nl->ml_next = nlp) != NULL)
2513 nlp->ml_prev = nl;
2514 nl->ml_prev = ml;
2515 ml->ml_next = nl;
2516 nlp = nl;
2517 }
2518 }
2519 if (ml->ml_size == 0ull) {
2520 if (ml == mlist) {
2521 if ((mlist = nlp) != NULL)
2522 nlp->ml_prev = NULL;
2523 kmem_free(ml, sizeof (struct memlist));
2524 if (mlist == NULL)
2525 break;
2526 ml = nlp;
2527 } else {
2528 if ((tl->ml_next = nlp) != NULL)
2529 nlp->ml_prev = tl;
2530 kmem_free(ml, sizeof (struct memlist));
2531 ml = tl;
2532 }
2533 }
2534 }
2535 }
2536
2537 return (mlist);
2538 }
2539
2540 static void
mc_get_mlist(mc_opl_t * mcp)2541 mc_get_mlist(mc_opl_t *mcp)
2542 {
2543 struct memlist *mlist;
2544
2545 memlist_read_lock();
2546 mlist = mc_memlist_dup(phys_install);
2547 memlist_read_unlock();
2548
2549 if (mlist) {
2550 mlist = mc_memlist_del_span(mlist, 0ull, mcp->mc_start_address);
2551 }
2552
2553 if (mlist) {
2554 uint64_t startpa, endpa;
2555
2556 startpa = mcp->mc_start_address + mcp->mc_size;
2557 endpa = ptob(physmax + 1);
2558 if (endpa > startpa) {
2559 mlist = mc_memlist_del_span(mlist, startpa,
2560 endpa - startpa);
2561 }
2562 }
2563
2564 if (mlist) {
2565 mcp->mlist = mlist;
2566 }
2567 }
2568
2569 int
mc_board_add(mc_opl_t * mcp)2570 mc_board_add(mc_opl_t *mcp)
2571 {
2572 struct mc_addr_spec *macaddr;
2573 cs_status_t *cs_status;
2574 int len, len1, i, bk, cc;
2575 mc_rsaddr_info_t rsaddr;
2576 uint32_t mirr;
2577 int nbanks = 0;
2578 uint64_t nbytes = 0;
2579 int mirror_mode = 0;
2580 int ret;
2581
2582 /*
2583 * Get configurations from "pseudo-mc" node which includes:
2584 * board# : LSB number
2585 * mac-addr : physical base address of MAC registers
2586 * csX-mac-pa-trans-table: translation table from DIMM address
2587 * to physical address or vice versa.
2588 */
2589 mcp->mc_board_num = (int)ddi_getprop(DDI_DEV_T_ANY, mcp->mc_dip,
2590 DDI_PROP_DONTPASS, "board#", -1);
2591
2592 if (mcp->mc_board_num == -1) {
2593 return (DDI_FAILURE);
2594 }
2595
2596 /*
2597 * Get start address in this CAB. It can be gotten from
2598 * "sb-mem-ranges" property.
2599 */
2600
2601 if (get_base_address(mcp) == DDI_FAILURE) {
2602 return (DDI_FAILURE);
2603 }
2604 /* get mac-pa trans tables */
2605 for (i = 0; i < MC_TT_CS; i++) {
2606 len = MC_TT_ENTRIES;
2607 cc = ddi_getlongprop_buf(DDI_DEV_T_ANY, mcp->mc_dip,
2608 DDI_PROP_DONTPASS, mc_tbl_name[i],
2609 (caddr_t)mcp->mc_trans_table[i], &len);
2610
2611 if (cc != DDI_SUCCESS) {
2612 bzero(mcp->mc_trans_table[i], MC_TT_ENTRIES);
2613 }
2614 }
2615 mcp->mlist = NULL;
2616
2617 mc_get_mlist(mcp);
2618
2619 /* initialize bank informations */
2620 cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2621 "mc-addr", (caddr_t)&macaddr, &len);
2622 if (cc != DDI_SUCCESS) {
2623 cmn_err(CE_WARN, "Cannot get mc-addr. err=%d\n", cc);
2624 return (DDI_FAILURE);
2625 }
2626
2627 cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2628 "cs-status", (caddr_t)&cs_status, &len1);
2629
2630 if (cc != DDI_SUCCESS) {
2631 if (len > 0)
2632 kmem_free(macaddr, len);
2633 cmn_err(CE_WARN, "Cannot get cs-status. err=%d\n", cc);
2634 return (DDI_FAILURE);
2635 }
2636 /* get the physical board number for a given logical board number */
2637 mcp->mc_phys_board_num = mc_opl_get_physical_board(mcp->mc_board_num);
2638
2639 if (mcp->mc_phys_board_num < 0) {
2640 if (len > 0)
2641 kmem_free(macaddr, len);
2642 cmn_err(CE_WARN, "Unable to obtain the physical board number");
2643 return (DDI_FAILURE);
2644 }
2645
2646 mutex_init(&mcp->mc_lock, NULL, MUTEX_DRIVER, NULL);
2647
2648 for (i = 0; i < len1 / sizeof (cs_status_t); i++) {
2649 nbytes += ((uint64_t)cs_status[i].cs_avail_hi << 32) |
2650 ((uint64_t)cs_status[i].cs_avail_low);
2651 }
2652 if (len1 > 0)
2653 kmem_free(cs_status, len1);
2654 nbanks = len / sizeof (struct mc_addr_spec);
2655
2656 if (nbanks > 0)
2657 nbytes /= nbanks;
2658 else {
2659 /* No need to free macaddr because len must be 0 */
2660 mcp->mc_status |= MC_MEMORYLESS;
2661 return (DDI_SUCCESS);
2662 }
2663
2664 for (i = 0; i < BANKNUM_PER_SB; i++) {
2665 mcp->mc_scf_retry[i] = 0;
2666 mcp->mc_period[i] = 0;
2667 mcp->mc_speedup_period[i] = 0;
2668 }
2669
2670 /*
2671 * Get the memory size here. Let it be B (bytes).
2672 * Let T be the time in u.s. to scan 64 bytes.
2673 * If we want to complete 1 round of scanning in P seconds.
2674 *
2675 * B * T * 10^(-6) = P
2676 * ---------------
2677 * 64
2678 *
2679 * T = P * 64 * 10^6
2680 * -------------
2681 * B
2682 *
2683 * = P * 64 * 10^6
2684 * -------------
2685 * B
2686 *
2687 * The timing bits are set in PTRL_CNTL[28:26] where
2688 *
2689 * 0 - 1 m.s
2690 * 1 - 512 u.s.
2691 * 10 - 256 u.s.
2692 * 11 - 128 u.s.
2693 * 100 - 64 u.s.
2694 * 101 - 32 u.s.
2695 * 110 - 0 u.s.
2696 * 111 - reserved.
2697 *
2698 *
2699 * a[0] = 110, a[1] = 101, ... a[6] = 0
2700 *
2701 * cs-status property is int x 7
2702 * 0 - cs#
2703 * 1 - cs-status
2704 * 2 - cs-avail.hi
2705 * 3 - cs-avail.lo
2706 * 4 - dimm-capa.hi
2707 * 5 - dimm-capa.lo
2708 * 6 - #of dimms
2709 */
2710
2711 if (nbytes > 0) {
2712 int i;
2713 uint64_t ms;
2714 ms = ((uint64_t)mc_scan_period * 64 * 1000000)/nbytes;
2715 mcp->mc_speed = mc_scan_speeds[MC_MAX_SPEEDS - 1].mc_speeds;
2716 for (i = 0; i < MC_MAX_SPEEDS - 1; i++) {
2717 if (ms < mc_scan_speeds[i + 1].mc_period) {
2718 mcp->mc_speed = mc_scan_speeds[i].mc_speeds;
2719 break;
2720 }
2721 }
2722 } else
2723 mcp->mc_speed = 0;
2724
2725
2726 for (i = 0; i < len / sizeof (struct mc_addr_spec); i++) {
2727 struct mc_bank *bankp;
2728 mc_retry_info_t *retry;
2729 uint32_t reg;
2730 int k;
2731
2732 /*
2733 * setup bank
2734 */
2735 bk = macaddr[i].bank;
2736 bankp = &(mcp->mc_bank[bk]);
2737 bankp->mcb_status = BANK_INSTALLED;
2738 bankp->mcb_reg_base = REGS_PA(macaddr, i);
2739
2740 bankp->mcb_retry_freelist = NULL;
2741 bankp->mcb_retry_pending = NULL;
2742 bankp->mcb_active = NULL;
2743 retry = &bankp->mcb_retry_infos[0];
2744 for (k = 0; k < MC_RETRY_COUNT; k++, retry++) {
2745 mc_retry_info_put(&bankp->mcb_retry_freelist, retry);
2746 }
2747
2748 reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bk));
2749 bankp->mcb_ptrl_cntl = (reg & MAC_CNTL_PTRL_PRESERVE_BITS);
2750
2751 /*
2752 * check if mirror mode
2753 */
2754 mirr = LD_MAC_REG(MAC_MIRR(mcp, bk));
2755
2756 if (mirr & MAC_MIRR_MIRROR_MODE) {
2757 MC_LOG("Mirror -> /LSB%d/B%d\n", mcp->mc_board_num,
2758 bk);
2759 bankp->mcb_status |= BANK_MIRROR_MODE;
2760 mirror_mode = 1;
2761 /*
2762 * The following bit is only used for
2763 * error injection. We should clear it
2764 */
2765 if (mirr & MAC_MIRR_BANK_EXCLUSIVE)
2766 ST_MAC_REG(MAC_MIRR(mcp, bk), 0);
2767 }
2768
2769 /*
2770 * restart if not mirror mode or the other bank
2771 * of the mirror is not running
2772 */
2773 if (!(mirr & MAC_MIRR_MIRROR_MODE) ||
2774 !(mcp->mc_bank[bk^1].mcb_status & BANK_PTRL_RUNNING)) {
2775 MC_LOG("Starting up /LSB%d/B%d\n", mcp->mc_board_num,
2776 bk);
2777 get_ptrl_start_address(mcp, bk, &rsaddr.mi_restartaddr);
2778 rsaddr.mi_valid = 0;
2779 rsaddr.mi_injectrestart = 0;
2780 (void) restart_patrol(mcp, bk, &rsaddr);
2781 } else {
2782 MC_LOG("Not starting up /LSB%d/B%d\n",
2783 mcp->mc_board_num, bk);
2784 }
2785 bankp->mcb_status |= BANK_PTRL_RUNNING;
2786 }
2787 if (len > 0)
2788 kmem_free(macaddr, len);
2789
2790 ret = ndi_prop_update_int(DDI_DEV_T_NONE, mcp->mc_dip, "mirror-mode",
2791 mirror_mode);
2792 if (ret != DDI_PROP_SUCCESS) {
2793 cmn_err(CE_WARN, "Unable to update mirror-mode property");
2794 }
2795
2796 mcp->mc_dimm_list = mc_get_dimm_list(mcp);
2797
2798 /*
2799 * set interval in HZ.
2800 */
2801 mcp->mc_last_error = 0;
2802
2803 /* restart memory patrol checking */
2804 mcp->mc_status |= MC_POLL_RUNNING;
2805
2806 return (DDI_SUCCESS);
2807 }
2808
2809 int
mc_board_del(mc_opl_t * mcp)2810 mc_board_del(mc_opl_t *mcp)
2811 {
2812 int i;
2813 scf_log_t *p;
2814
2815 /*
2816 * cleanup mac state
2817 */
2818 mutex_enter(&mcp->mc_lock);
2819 if (mcp->mc_status & MC_MEMORYLESS) {
2820 mutex_exit(&mcp->mc_lock);
2821 mutex_destroy(&mcp->mc_lock);
2822 return (DDI_SUCCESS);
2823 }
2824 for (i = 0; i < BANKNUM_PER_SB; i++) {
2825 if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2826 mcp->mc_bank[i].mcb_status &= ~BANK_INSTALLED;
2827 }
2828 }
2829
2830 /* stop memory patrol checking */
2831 mcp->mc_status &= ~MC_POLL_RUNNING;
2832
2833 /* just throw away all the scf logs */
2834 for (i = 0; i < BANKNUM_PER_SB; i++) {
2835 while ((p = mcp->mc_scf_log[i]) != NULL) {
2836 mcp->mc_scf_log[i] = p->sl_next;
2837 mcp->mc_scf_total[i]--;
2838 kmem_free(p, sizeof (scf_log_t));
2839 }
2840 }
2841
2842 if (mcp->mlist)
2843 mc_memlist_delete(mcp->mlist);
2844
2845 if (mcp->mc_dimm_list)
2846 mc_free_dimm_list(mcp->mc_dimm_list);
2847
2848 mutex_exit(&mcp->mc_lock);
2849
2850 mutex_destroy(&mcp->mc_lock);
2851 return (DDI_SUCCESS);
2852 }
2853
2854 int
mc_suspend(mc_opl_t * mcp,uint32_t flag)2855 mc_suspend(mc_opl_t *mcp, uint32_t flag)
2856 {
2857 /* stop memory patrol checking */
2858 mutex_enter(&mcp->mc_lock);
2859 if (mcp->mc_status & MC_MEMORYLESS) {
2860 mutex_exit(&mcp->mc_lock);
2861 return (DDI_SUCCESS);
2862 }
2863
2864 mcp->mc_status &= ~MC_POLL_RUNNING;
2865
2866 mcp->mc_status |= flag;
2867 mutex_exit(&mcp->mc_lock);
2868
2869 return (DDI_SUCCESS);
2870 }
2871
2872 void
opl_mc_update_mlist(void)2873 opl_mc_update_mlist(void)
2874 {
2875 int i;
2876 mc_opl_t *mcp;
2877
2878 /*
2879 * memory information is not updated until
2880 * the post attach/detach stage during DR.
2881 * This interface is used by dr_mem to inform
2882 * mc-opl to update the mlist.
2883 */
2884
2885 mutex_enter(&mcmutex);
2886 for (i = 0; i < OPL_MAX_BOARDS; i++) {
2887 if ((mcp = mc_instances[i]) == NULL)
2888 continue;
2889 mutex_enter(&mcp->mc_lock);
2890 if (mcp->mlist)
2891 mc_memlist_delete(mcp->mlist);
2892 mcp->mlist = NULL;
2893 mc_get_mlist(mcp);
2894 mutex_exit(&mcp->mc_lock);
2895 }
2896 mutex_exit(&mcmutex);
2897 }
2898
2899 /* caller must clear the SUSPEND bits or this will do nothing */
2900
2901 int
mc_resume(mc_opl_t * mcp,uint32_t flag)2902 mc_resume(mc_opl_t *mcp, uint32_t flag)
2903 {
2904 int i;
2905 uint64_t basepa;
2906
2907 mutex_enter(&mcp->mc_lock);
2908 if (mcp->mc_status & MC_MEMORYLESS) {
2909 mutex_exit(&mcp->mc_lock);
2910 return (DDI_SUCCESS);
2911 }
2912 basepa = mcp->mc_start_address;
2913 if (get_base_address(mcp) == DDI_FAILURE) {
2914 mutex_exit(&mcp->mc_lock);
2915 return (DDI_FAILURE);
2916 }
2917
2918 if (basepa != mcp->mc_start_address) {
2919 if (mcp->mlist)
2920 mc_memlist_delete(mcp->mlist);
2921 mcp->mlist = NULL;
2922 mc_get_mlist(mcp);
2923 }
2924
2925 mcp->mc_status &= ~flag;
2926
2927 if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
2928 mutex_exit(&mcp->mc_lock);
2929 return (DDI_SUCCESS);
2930 }
2931
2932 if (!(mcp->mc_status & MC_POLL_RUNNING)) {
2933 /* restart memory patrol checking */
2934 mcp->mc_status |= MC_POLL_RUNNING;
2935 for (i = 0; i < BANKNUM_PER_SB; i++) {
2936 if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2937 mc_check_errors_func(mcp);
2938 }
2939 }
2940 }
2941 mutex_exit(&mcp->mc_lock);
2942
2943 return (DDI_SUCCESS);
2944 }
2945
2946 static mc_opl_t *
mc_pa_to_mcp(uint64_t pa)2947 mc_pa_to_mcp(uint64_t pa)
2948 {
2949 mc_opl_t *mcp;
2950 int i;
2951
2952 ASSERT(MUTEX_HELD(&mcmutex));
2953 for (i = 0; i < OPL_MAX_BOARDS; i++) {
2954 if ((mcp = mc_instances[i]) == NULL)
2955 continue;
2956 /* if mac patrol is suspended, we cannot rely on it */
2957 if (!(mcp->mc_status & MC_POLL_RUNNING) ||
2958 (mcp->mc_status & MC_SOFT_SUSPENDED))
2959 continue;
2960 if (mc_rangecheck_pa(mcp, pa)) {
2961 return (mcp);
2962 }
2963 }
2964 return (NULL);
2965 }
2966
2967 /*
2968 * Get Physical Board number from Logical one.
2969 */
2970 static int
mc_opl_get_physical_board(int sb)2971 mc_opl_get_physical_board(int sb)
2972 {
2973 if (&opl_get_physical_board) {
2974 return (opl_get_physical_board(sb));
2975 }
2976
2977 cmn_err(CE_NOTE, "!opl_get_physical_board() not loaded\n");
2978 return (-1);
2979 }
2980
2981 /* ARGSUSED */
2982 int
mc_get_mem_unum(int synd_code,uint64_t flt_addr,char * buf,int buflen,int * lenp)2983 mc_get_mem_unum(int synd_code, uint64_t flt_addr, char *buf, int buflen,
2984 int *lenp)
2985 {
2986 int i;
2987 int j;
2988 int sb;
2989 int bank;
2990 int cs;
2991 int rv = 0;
2992 mc_opl_t *mcp;
2993 char memb_num;
2994
2995 mutex_enter(&mcmutex);
2996
2997 if (((mcp = mc_pa_to_mcp(flt_addr)) == NULL) ||
2998 (!pa_is_valid(mcp, flt_addr))) {
2999 mutex_exit(&mcmutex);
3000 if (snprintf(buf, buflen, "UNKNOWN") >= buflen) {
3001 return (ENOSPC);
3002 } else {
3003 if (lenp)
3004 *lenp = strlen(buf);
3005 }
3006 return (0);
3007 }
3008
3009 bank = pa_to_bank(mcp, flt_addr - mcp->mc_start_address);
3010 sb = mcp->mc_phys_board_num;
3011 cs = pa_to_cs(mcp, flt_addr - mcp->mc_start_address);
3012
3013 if (sb == -1) {
3014 mutex_exit(&mcmutex);
3015 return (ENXIO);
3016 }
3017
3018 switch (plat_model) {
3019 case MODEL_DC:
3020 i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
3021 j = (cs == 0) ? i : i + 2;
3022 (void) snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
3023 model_names[plat_model].unit_name, sb,
3024 mc_dc_dimm_unum_table[j],
3025 mc_dc_dimm_unum_table[j + 1]);
3026 break;
3027 case MODEL_FF2:
3028 case MODEL_FF1:
3029 i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
3030 j = (cs == 0) ? i : i + 2;
3031 memb_num = mc_ff_dimm_unum_table[i][0];
3032 (void) snprintf(buf, buflen, "/%s/%s%c/MEM%s MEM%s",
3033 model_names[plat_model].unit_name,
3034 model_names[plat_model].mem_name, memb_num,
3035 &mc_ff_dimm_unum_table[j][1],
3036 &mc_ff_dimm_unum_table[j + 1][1]);
3037 break;
3038 case MODEL_IKKAKU:
3039 i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
3040 j = (cs == 0) ? i : i + 2;
3041 (void) snprintf(buf, buflen, "/%s/MEM%s MEM%s",
3042 model_names[plat_model].unit_name,
3043 &mc_ff_dimm_unum_table[j][1],
3044 &mc_ff_dimm_unum_table[j + 1][1]);
3045 break;
3046 default:
3047 rv = ENXIO;
3048 }
3049 if (lenp) {
3050 *lenp = strlen(buf);
3051 }
3052 mutex_exit(&mcmutex);
3053 return (rv);
3054 }
3055
3056 int
opl_mc_suspend(void)3057 opl_mc_suspend(void)
3058 {
3059 mc_opl_t *mcp;
3060 int i;
3061
3062 mutex_enter(&mcmutex);
3063 for (i = 0; i < OPL_MAX_BOARDS; i++) {
3064 if ((mcp = mc_instances[i]) == NULL)
3065 continue;
3066 (void) mc_suspend(mcp, MC_SOFT_SUSPENDED);
3067 }
3068 mutex_exit(&mcmutex);
3069
3070 return (0);
3071 }
3072
3073 int
opl_mc_resume(void)3074 opl_mc_resume(void)
3075 {
3076 mc_opl_t *mcp;
3077 int i;
3078
3079 mutex_enter(&mcmutex);
3080 for (i = 0; i < OPL_MAX_BOARDS; i++) {
3081 if ((mcp = mc_instances[i]) == NULL)
3082 continue;
3083 (void) mc_resume(mcp, MC_SOFT_SUSPENDED);
3084 }
3085 mutex_exit(&mcmutex);
3086
3087 return (0);
3088 }
3089 static void
insert_mcp(mc_opl_t * mcp)3090 insert_mcp(mc_opl_t *mcp)
3091 {
3092 mutex_enter(&mcmutex);
3093 if (mc_instances[mcp->mc_board_num] != NULL) {
3094 MC_LOG("mc-opl instance for board# %d already exists\n",
3095 mcp->mc_board_num);
3096 }
3097 mc_instances[mcp->mc_board_num] = mcp;
3098 mutex_exit(&mcmutex);
3099 }
3100
3101 static void
delete_mcp(mc_opl_t * mcp)3102 delete_mcp(mc_opl_t *mcp)
3103 {
3104 mutex_enter(&mcmutex);
3105 mc_instances[mcp->mc_board_num] = 0;
3106 mutex_exit(&mcmutex);
3107 }
3108
3109 /* Error injection interface */
3110
3111 static void
mc_lock_va(uint64_t pa,caddr_t new_va)3112 mc_lock_va(uint64_t pa, caddr_t new_va)
3113 {
3114 tte_t tte;
3115
3116 vtag_flushpage(new_va, (uint64_t)ksfmmup);
3117 sfmmu_memtte(&tte, pa >> PAGESHIFT, PROC_DATA|HAT_NOSYNC, TTE8K);
3118 tte.tte_intlo |= TTE_LCK_INT;
3119 sfmmu_dtlb_ld_kva(new_va, &tte);
3120 }
3121
3122 static void
mc_unlock_va(caddr_t va)3123 mc_unlock_va(caddr_t va)
3124 {
3125 vtag_flushpage(va, (uint64_t)ksfmmup);
3126 }
3127
3128 /* ARGSUSED */
3129 int
mc_inject_error(int error_type,uint64_t pa,uint32_t flags)3130 mc_inject_error(int error_type, uint64_t pa, uint32_t flags)
3131 {
3132 mc_opl_t *mcp;
3133 int bank;
3134 uint32_t dimm_addr;
3135 uint32_t cntl;
3136 mc_rsaddr_info_t rsaddr;
3137 uint32_t data, stat;
3138 int both_sides = 0;
3139 uint64_t pa0;
3140 int extra_injection_needed = 0;
3141 extern void cpu_flush_ecache(void);
3142
3143 MC_LOG("HW mc_inject_error(%x, %lx, %x)\n", error_type, pa, flags);
3144
3145 mutex_enter(&mcmutex);
3146 if ((mcp = mc_pa_to_mcp(pa)) == NULL) {
3147 mutex_exit(&mcmutex);
3148 MC_LOG("mc_inject_error: invalid pa\n");
3149 return (ENOTSUP);
3150 }
3151
3152 mutex_enter(&mcp->mc_lock);
3153 mutex_exit(&mcmutex);
3154
3155 if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
3156 mutex_exit(&mcp->mc_lock);
3157 MC_LOG("mc-opl has been suspended. No error injection.\n");
3158 return (EBUSY);
3159 }
3160
3161 /* convert pa to offset within the board */
3162 MC_LOG("pa %lx, offset %lx\n", pa, pa - mcp->mc_start_address);
3163
3164 if (!pa_is_valid(mcp, pa)) {
3165 mutex_exit(&mcp->mc_lock);
3166 return (EINVAL);
3167 }
3168
3169 pa0 = pa - mcp->mc_start_address;
3170
3171 bank = pa_to_bank(mcp, pa0);
3172
3173 if (flags & MC_INJECT_FLAG_OTHER)
3174 bank = bank ^ 1;
3175
3176 if (MC_INJECT_MIRROR(error_type) && !IS_MIRROR(mcp, bank)) {
3177 mutex_exit(&mcp->mc_lock);
3178 MC_LOG("Not mirror mode\n");
3179 return (EINVAL);
3180 }
3181
3182 dimm_addr = pa_to_dimm(mcp, pa0);
3183
3184 MC_LOG("injecting error to /LSB%d/B%d/%x\n", mcp->mc_board_num, bank,
3185 dimm_addr);
3186
3187
3188 switch (error_type) {
3189 case MC_INJECT_INTERMITTENT_MCE:
3190 case MC_INJECT_PERMANENT_MCE:
3191 case MC_INJECT_MUE:
3192 both_sides = 1;
3193 }
3194
3195 if (flags & MC_INJECT_FLAG_RESET)
3196 ST_MAC_REG(MAC_EG_CNTL(mcp, bank), 0);
3197
3198 ST_MAC_REG(MAC_EG_ADD(mcp, bank), dimm_addr & MAC_EG_ADD_MASK);
3199
3200 if (both_sides) {
3201 ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), 0);
3202 ST_MAC_REG(MAC_EG_ADD(mcp, bank^1), dimm_addr &
3203 MAC_EG_ADD_MASK);
3204 }
3205
3206 switch (error_type) {
3207 case MC_INJECT_SUE:
3208 extra_injection_needed = 1;
3209 /*FALLTHROUGH*/
3210 case MC_INJECT_UE:
3211 case MC_INJECT_MUE:
3212 if (flags & MC_INJECT_FLAG_PATH) {
3213 cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_READ00 |
3214 MAC_EG_FORCE_READ16 | MAC_EG_RDERR_ONCE;
3215 } else {
3216 cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR00 |
3217 MAC_EG_FORCE_DERR16 | MAC_EG_DERR_ONCE;
3218 }
3219 flags |= MC_INJECT_FLAG_ST;
3220 break;
3221 case MC_INJECT_INTERMITTENT_CE:
3222 case MC_INJECT_INTERMITTENT_MCE:
3223 if (flags & MC_INJECT_FLAG_PATH) {
3224 cntl = MAC_EG_ADD_FIX |MAC_EG_FORCE_READ00 |
3225 MAC_EG_RDERR_ONCE;
3226 } else {
3227 cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR16 |
3228 MAC_EG_DERR_ONCE;
3229 }
3230 extra_injection_needed = 1;
3231 flags |= MC_INJECT_FLAG_ST;
3232 break;
3233 case MC_INJECT_PERMANENT_CE:
3234 case MC_INJECT_PERMANENT_MCE:
3235 if (flags & MC_INJECT_FLAG_PATH) {
3236 cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_READ00 |
3237 MAC_EG_RDERR_ALWAYS;
3238 } else {
3239 cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR16 |
3240 MAC_EG_DERR_ALWAYS;
3241 }
3242 flags |= MC_INJECT_FLAG_ST;
3243 break;
3244 case MC_INJECT_CMPE:
3245 data = 0xabcdefab;
3246 stphys(pa, data);
3247 cpu_flush_ecache();
3248 MC_LOG("CMPE: writing data %x to %lx\n", data, pa);
3249 ST_MAC_REG(MAC_MIRR(mcp, bank), MAC_MIRR_BANK_EXCLUSIVE);
3250 stphys(pa, data ^ 0xffffffff);
3251 membar_sync();
3252 cpu_flush_ecache();
3253 ST_MAC_REG(MAC_MIRR(mcp, bank), 0);
3254 MC_LOG("CMPE: write new data %xto %lx\n", data, pa);
3255 cntl = 0;
3256 break;
3257 case MC_INJECT_NOP:
3258 cntl = 0;
3259 break;
3260 default:
3261 MC_LOG("mc_inject_error: invalid option\n");
3262 cntl = 0;
3263 }
3264
3265 if (cntl) {
3266 ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl & MAC_EG_SETUP_MASK);
3267 ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
3268
3269 if (both_sides) {
3270 ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
3271 MAC_EG_SETUP_MASK);
3272 ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
3273 }
3274 }
3275
3276 /*
3277 * For all injection cases except compare error, we
3278 * must write to the PA to trigger the error.
3279 */
3280
3281 if (flags & MC_INJECT_FLAG_ST) {
3282 data = 0xf0e0d0c0;
3283 MC_LOG("Writing %x to %lx\n", data, pa);
3284 stphys(pa, data);
3285 cpu_flush_ecache();
3286 }
3287
3288
3289 if (flags & MC_INJECT_FLAG_LD) {
3290 if (flags & MC_INJECT_FLAG_PREFETCH) {
3291 /*
3292 * Use strong prefetch operation to
3293 * inject MI errors.
3294 */
3295 page_t *pp;
3296 extern void mc_prefetch(caddr_t);
3297
3298 MC_LOG("prefetch\n");
3299
3300 pp = page_numtopp_nolock(pa >> PAGESHIFT);
3301 if (pp != NULL) {
3302 caddr_t va, va1;
3303
3304 va = ppmapin(pp, PROT_READ|PROT_WRITE,
3305 (caddr_t)-1);
3306 kpreempt_disable();
3307 mc_lock_va((uint64_t)pa, va);
3308 va1 = va + (pa & (PAGESIZE - 1));
3309 mc_prefetch(va1);
3310 mc_unlock_va(va);
3311 kpreempt_enable();
3312 ppmapout(va);
3313
3314 /*
3315 * For MI errors, we need one extra
3316 * injection for HW patrol to stop.
3317 */
3318 extra_injection_needed = 1;
3319 } else {
3320 cmn_err(CE_WARN, "Cannot find page structure"
3321 " for PA %lx\n", pa);
3322 }
3323 } else {
3324 MC_LOG("Reading from %lx\n", pa);
3325 data = ldphys(pa);
3326 MC_LOG("data = %x\n", data);
3327 }
3328
3329 if (extra_injection_needed) {
3330 /*
3331 * These are the injection cases where the
3332 * requested injected errors will not cause the HW
3333 * patrol to stop. For these cases, we need to inject
3334 * an extra 'real' PTRL error to force the
3335 * HW patrol to stop so that we can report the
3336 * errors injected. Note that we cannot read
3337 * and report error status while the HW patrol
3338 * is running.
3339 */
3340 ST_MAC_REG(MAC_EG_CNTL(mcp, bank),
3341 cntl & MAC_EG_SETUP_MASK);
3342 ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
3343
3344 if (both_sides) {
3345 ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
3346 MAC_EG_SETUP_MASK);
3347 ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
3348 }
3349 data = 0xf0e0d0c0;
3350 MC_LOG("Writing %x to %lx\n", data, pa);
3351 stphys(pa, data);
3352 cpu_flush_ecache();
3353 }
3354 }
3355
3356 if (flags & MC_INJECT_FLAG_RESTART) {
3357 MC_LOG("Restart patrol\n");
3358 rsaddr.mi_restartaddr.ma_bd = mcp->mc_board_num;
3359 rsaddr.mi_restartaddr.ma_bank = bank;
3360 rsaddr.mi_restartaddr.ma_dimm_addr = dimm_addr;
3361 rsaddr.mi_valid = 1;
3362 rsaddr.mi_injectrestart = 1;
3363 (void) restart_patrol(mcp, bank, &rsaddr);
3364 }
3365
3366 if (flags & MC_INJECT_FLAG_POLL) {
3367 int running;
3368 int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
3369
3370 MC_LOG("Poll patrol error\n");
3371 stat = LD_MAC_REG(MAC_PTRL_STAT(mcp, bank));
3372 cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
3373 running = cntl & MAC_CNTL_PTRL_START;
3374
3375 if (!running &&
3376 (stat & (MAC_STAT_PTRL_ERRS|MAC_STAT_MI_ERRS))) {
3377 /*
3378 * HW patrol stopped and we have errors to
3379 * report. Do it.
3380 */
3381 mcp->mc_speedup_period[ebank] = 0;
3382 rsaddr.mi_valid = 0;
3383 rsaddr.mi_injectrestart = 0;
3384 if (IS_MIRROR(mcp, bank)) {
3385 mc_error_handler_mir(mcp, bank, &rsaddr);
3386 } else {
3387 mc_error_handler(mcp, bank, &rsaddr);
3388 }
3389
3390 (void) restart_patrol(mcp, bank, &rsaddr);
3391 } else {
3392 /*
3393 * We are expecting to report injected
3394 * errors but the HW patrol is still running.
3395 * Speed up the scanning
3396 */
3397 mcp->mc_speedup_period[ebank] = 2;
3398 MAC_CMD(mcp, bank, 0);
3399 (void) restart_patrol(mcp, bank, NULL);
3400 }
3401 }
3402
3403 mutex_exit(&mcp->mc_lock);
3404 return (0);
3405 }
3406
3407 void
mc_stphysio(uint64_t pa,uint32_t data)3408 mc_stphysio(uint64_t pa, uint32_t data)
3409 {
3410 MC_LOG("0x%x -> pa(%lx)\n", data, pa);
3411 stphysio(pa, data);
3412
3413 /* force the above write to be processed by mac patrol */
3414 data = ldphysio(pa);
3415 MC_LOG("pa(%lx) = 0x%x\n", pa, data);
3416 }
3417
3418 uint32_t
mc_ldphysio(uint64_t pa)3419 mc_ldphysio(uint64_t pa)
3420 {
3421 uint32_t rv;
3422
3423 rv = ldphysio(pa);
3424 MC_LOG("pa(%lx) = 0x%x\n", pa, rv);
3425 return (rv);
3426 }
3427
3428 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
3429
3430 /*
3431 * parse_unum_memory -- extract the board number and the DIMM name from
3432 * the unum.
3433 *
3434 * Return 0 for success and non-zero for a failure.
3435 */
3436 int
parse_unum_memory(char * unum,int * board,char * dname)3437 parse_unum_memory(char *unum, int *board, char *dname)
3438 {
3439 char *c;
3440 char x, y, z;
3441
3442 if ((c = strstr(unum, "CMU")) != NULL) {
3443 /* DC Model */
3444 c += 3;
3445 *board = (uint8_t)stoi(&c);
3446 if ((c = strstr(c, "MEM")) == NULL) {
3447 return (1);
3448 }
3449 c += 3;
3450 if (strlen(c) < 3) {
3451 return (2);
3452 }
3453 if ((!isdigit(c[0])) || (!(isdigit(c[1]))) ||
3454 ((c[2] != 'A') && (c[2] != 'B'))) {
3455 return (3);
3456 }
3457 x = c[0];
3458 y = c[1];
3459 z = c[2];
3460 } else if ((c = strstr(unum, "MBU_")) != NULL) {
3461 /* FF1/FF2/Ikkaku Model */
3462 c += 4;
3463 if ((c[0] != 'A') && (c[0] != 'B')) {
3464 return (4);
3465 }
3466 if (plat_model == MODEL_IKKAKU) {
3467 /* Ikkaku Model */
3468 x = '0';
3469 *board = 0;
3470 } else {
3471 /* FF1/FF2 Model */
3472 if ((c = strstr(c, "MEMB")) == NULL) {
3473 return (5);
3474 }
3475 c += 4;
3476
3477 x = c[0];
3478 *board = ((uint8_t)stoi(&c)) / 4;
3479 }
3480
3481 if ((c = strstr(c, "MEM")) == NULL) {
3482 return (6);
3483 }
3484 c += 3;
3485 if (strlen(c) < 2) {
3486 return (7);
3487 }
3488 if ((!isdigit(c[0])) || ((c[1] != 'A') && (c[1] != 'B'))) {
3489 return (8);
3490 }
3491 y = c[0];
3492 z = c[1];
3493 } else {
3494 return (9);
3495 }
3496 if (*board < 0) {
3497 return (10);
3498 }
3499 dname[0] = x;
3500 dname[1] = y;
3501 dname[2] = z;
3502 dname[3] = '\0';
3503 return (0);
3504 }
3505
3506 /*
3507 * mc_get_mem_sid_dimm -- Get the serial-ID for a given board and
3508 * the DIMM name.
3509 */
3510 int
mc_get_mem_sid_dimm(mc_opl_t * mcp,char * dname,char * buf,int buflen,int * lenp)3511 mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
3512 int buflen, int *lenp)
3513 {
3514 int ret = ENODEV;
3515 mc_dimm_info_t *d = NULL;
3516
3517 if ((d = mcp->mc_dimm_list) == NULL) {
3518 MC_LOG("mc_get_mem_sid_dimm: mc_dimm_list is NULL\n");
3519 return (EINVAL);
3520 }
3521
3522 for (; d != NULL; d = d->md_next) {
3523 if (strcmp(d->md_dimmname, dname) == 0) {
3524 break;
3525 }
3526 }
3527 if (d != NULL) {
3528 *lenp = strlen(d->md_serial) + strlen(d->md_partnum);
3529 if (buflen <= *lenp) {
3530 cmn_err(CE_WARN, "mc_get_mem_sid_dimm: "
3531 "buflen is smaller than %d\n", *lenp);
3532 ret = ENOSPC;
3533 } else {
3534 (void) snprintf(buf, buflen, "%s:%s",
3535 d->md_serial, d->md_partnum);
3536 ret = 0;
3537 }
3538 }
3539 MC_LOG("mc_get_mem_sid_dimm: Ret=%d Name=%s Serial-ID=%s\n",
3540 ret, dname, (ret == 0) ? buf : "");
3541 return (ret);
3542 }
3543
3544 int
mc_set_mem_sid(mc_opl_t * mcp,char * buf,int buflen,int sb,int bank,uint32_t mf_type,uint32_t d_slot)3545 mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int sb,
3546 int bank, uint32_t mf_type, uint32_t d_slot)
3547 {
3548 int lenp = buflen;
3549 int id;
3550 int ret;
3551 char *dimmnm;
3552
3553 if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
3554 mf_type == FLT_TYPE_PERMANENT_CE) {
3555 if (plat_model == MODEL_DC) {
3556 /*
3557 * All DC models
3558 */
3559 id = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
3560 dimmnm = mc_dc_dimm_unum_table[id];
3561 } else {
3562 /*
3563 * All FF and Ikkaku models
3564 */
3565 id = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
3566 dimmnm = mc_ff_dimm_unum_table[id];
3567 }
3568 if ((ret = mc_get_mem_sid_dimm(mcp, dimmnm, buf, buflen,
3569 &lenp)) != 0) {
3570 return (ret);
3571 }
3572 } else {
3573 return (1);
3574 }
3575
3576 return (0);
3577 }
3578
3579 /*
3580 * mc_get_mem_sid -- get the DIMM serial-ID corresponding to the unum.
3581 */
3582 int
mc_get_mem_sid(char * unum,char * buf,int buflen,int * lenp)3583 mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp)
3584 {
3585 int i;
3586 int ret = ENODEV;
3587 int board;
3588 char dname[MCOPL_MAX_DIMMNAME + 1];
3589 mc_opl_t *mcp;
3590
3591 MC_LOG("mc_get_mem_sid: unum=%s buflen=%d\n", unum, buflen);
3592 if ((ret = parse_unum_memory(unum, &board, dname)) != 0) {
3593 MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
3594 unum, ret);
3595 return (EINVAL);
3596 }
3597
3598 if (board < 0) {
3599 MC_LOG("mc_get_mem_sid: Invalid board=%d dimm=%s\n",
3600 board, dname);
3601 return (EINVAL);
3602 }
3603
3604 mutex_enter(&mcmutex);
3605 /*
3606 * return ENOENT if we can not find the matching board.
3607 */
3608 ret = ENOENT;
3609 for (i = 0; i < OPL_MAX_BOARDS; i++) {
3610 if ((mcp = mc_instances[i]) == NULL)
3611 continue;
3612 mutex_enter(&mcp->mc_lock);
3613 if (mcp->mc_phys_board_num != board) {
3614 mutex_exit(&mcp->mc_lock);
3615 continue;
3616 }
3617 ret = mc_get_mem_sid_dimm(mcp, dname, buf, buflen, lenp);
3618 if (ret == 0) {
3619 mutex_exit(&mcp->mc_lock);
3620 break;
3621 }
3622 mutex_exit(&mcp->mc_lock);
3623 }
3624 mutex_exit(&mcmutex);
3625 return (ret);
3626 }
3627
3628 /*
3629 * mc_get_mem_offset -- get the offset in a DIMM for a given physical address.
3630 */
3631 int
mc_get_mem_offset(uint64_t paddr,uint64_t * offp)3632 mc_get_mem_offset(uint64_t paddr, uint64_t *offp)
3633 {
3634 int i;
3635 int ret = ENODEV;
3636 mc_addr_t maddr;
3637 mc_opl_t *mcp;
3638
3639 mutex_enter(&mcmutex);
3640 for (i = 0; ((i < OPL_MAX_BOARDS) && (ret != 0)); i++) {
3641 if ((mcp = mc_instances[i]) == NULL)
3642 continue;
3643 mutex_enter(&mcp->mc_lock);
3644 if (!pa_is_valid(mcp, paddr)) {
3645 mutex_exit(&mcp->mc_lock);
3646 continue;
3647 }
3648 if (pa_to_maddr(mcp, paddr, &maddr) == 0) {
3649 *offp = maddr.ma_dimm_addr;
3650 ret = 0;
3651 }
3652 mutex_exit(&mcp->mc_lock);
3653 }
3654 mutex_exit(&mcmutex);
3655 MC_LOG("mc_get_mem_offset: Ret=%d paddr=0x%lx offset=0x%lx\n",
3656 ret, paddr, *offp);
3657 return (ret);
3658 }
3659
3660 /*
3661 * dname_to_bankslot - Get the bank and slot number from the DIMM name.
3662 */
3663 int
dname_to_bankslot(char * dname,int * bank,int * slot)3664 dname_to_bankslot(char *dname, int *bank, int *slot)
3665 {
3666 int i;
3667 int tsz;
3668 char **tbl;
3669
3670 if (plat_model == MODEL_DC) {
3671 /*
3672 * All DC models
3673 */
3674 tbl = mc_dc_dimm_unum_table;
3675 tsz = OPL_MAX_DIMMS;
3676 } else {
3677 /*
3678 * All FF and Ikkaku models
3679 */
3680 tbl = mc_ff_dimm_unum_table;
3681 tsz = 2 * OPL_MAX_DIMMS;
3682 }
3683
3684 for (i = 0; i < tsz; i++) {
3685 if (strcmp(dname, tbl[i]) == 0) {
3686 break;
3687 }
3688 }
3689 if (i == tsz) {
3690 return (1);
3691 }
3692 *bank = INDEX_TO_BANK(i);
3693 *slot = INDEX_TO_SLOT(i);
3694 return (0);
3695 }
3696
3697 /*
3698 * mc_get_mem_addr -- get the physical address of a DIMM corresponding
3699 * to the unum and sid.
3700 */
3701 int
mc_get_mem_addr(char * unum,char * sid,uint64_t offset,uint64_t * paddr)3702 mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr)
3703 {
3704 int board;
3705 int bank;
3706 int slot;
3707 int i;
3708 int ret = ENODEV;
3709 char dname[MCOPL_MAX_DIMMNAME + 1];
3710 mc_addr_t maddr;
3711 mc_opl_t *mcp;
3712
3713 MC_LOG("mc_get_mem_addr: unum=%s sid=%s offset=0x%lx\n",
3714 unum, sid, offset);
3715 if (parse_unum_memory(unum, &board, dname) != 0) {
3716 MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
3717 unum, ret);
3718 return (EINVAL);
3719 }
3720
3721 if (board < 0) {
3722 MC_LOG("mc_get_mem_addr: Invalid board=%d dimm=%s\n",
3723 board, dname);
3724 return (EINVAL);
3725 }
3726
3727 mutex_enter(&mcmutex);
3728 for (i = 0; i < OPL_MAX_BOARDS; i++) {
3729 if ((mcp = mc_instances[i]) == NULL)
3730 continue;
3731 mutex_enter(&mcp->mc_lock);
3732 if (mcp->mc_phys_board_num != board) {
3733 mutex_exit(&mcp->mc_lock);
3734 continue;
3735 }
3736
3737 ret = dname_to_bankslot(dname, &bank, &slot);
3738 MC_LOG("mc_get_mem_addr: bank=%d slot=%d\n", bank, slot);
3739 if (ret != 0) {
3740 MC_LOG("mc_get_mem_addr: dname_to_bankslot failed\n");
3741 ret = ENODEV;
3742 } else {
3743 maddr.ma_bd = mcp->mc_board_num;
3744 maddr.ma_bank = bank;
3745 maddr.ma_dimm_addr = offset;
3746 ret = mcaddr_to_pa(mcp, &maddr, paddr);
3747 if (ret != 0) {
3748 MC_LOG("mc_get_mem_addr: "
3749 "mcaddr_to_pa failed\n");
3750 ret = ENODEV;
3751 mutex_exit(&mcp->mc_lock);
3752 continue;
3753 }
3754 mutex_exit(&mcp->mc_lock);
3755 break;
3756 }
3757 mutex_exit(&mcp->mc_lock);
3758 }
3759 mutex_exit(&mcmutex);
3760 MC_LOG("mc_get_mem_addr: Ret=%d, Paddr=0x%lx\n", ret, *paddr);
3761 return (ret);
3762 }
3763
3764 static void
mc_free_dimm_list(mc_dimm_info_t * d)3765 mc_free_dimm_list(mc_dimm_info_t *d)
3766 {
3767 mc_dimm_info_t *next;
3768
3769 while (d != NULL) {
3770 next = d->md_next;
3771 kmem_free(d, sizeof (mc_dimm_info_t));
3772 d = next;
3773 }
3774 }
3775
3776 /*
3777 * mc_get_dimm_list -- get the list of dimms with serial-id info
3778 * from the SP.
3779 */
3780 mc_dimm_info_t *
mc_get_dimm_list(mc_opl_t * mcp)3781 mc_get_dimm_list(mc_opl_t *mcp)
3782 {
3783 uint32_t bufsz;
3784 uint32_t maxbufsz;
3785 int ret;
3786 int sexp;
3787 board_dimm_info_t *bd_dimmp;
3788 mc_dimm_info_t *dimm_list = NULL;
3789
3790 maxbufsz = bufsz = sizeof (board_dimm_info_t) +
3791 ((MCOPL_MAX_DIMMNAME + MCOPL_MAX_SERIAL +
3792 MCOPL_MAX_PARTNUM) * OPL_MAX_DIMMS);
3793
3794 bd_dimmp = (board_dimm_info_t *)kmem_alloc(bufsz, KM_SLEEP);
3795 ret = scf_get_dimminfo(mcp->mc_board_num, (void *)bd_dimmp, &bufsz);
3796
3797 MC_LOG("mc_get_dimm_list: scf_service_getinfo returned=%d\n", ret);
3798 if (ret == 0) {
3799 sexp = sizeof (board_dimm_info_t) +
3800 ((bd_dimmp->bd_dnamesz + bd_dimmp->bd_serialsz +
3801 bd_dimmp->bd_partnumsz) * bd_dimmp->bd_numdimms);
3802
3803 if ((bd_dimmp->bd_version == OPL_DIMM_INFO_VERSION) &&
3804 (bd_dimmp->bd_dnamesz <= MCOPL_MAX_DIMMNAME) &&
3805 (bd_dimmp->bd_serialsz <= MCOPL_MAX_SERIAL) &&
3806 (bd_dimmp->bd_partnumsz <= MCOPL_MAX_PARTNUM) &&
3807 (sexp <= bufsz)) {
3808
3809 #ifdef DEBUG
3810 if (oplmc_debug)
3811 mc_dump_dimm_info(bd_dimmp);
3812 #endif
3813 dimm_list = mc_prepare_dimmlist(bd_dimmp);
3814
3815 } else {
3816 cmn_err(CE_WARN, "DIMM info version mismatch\n");
3817 }
3818 }
3819 kmem_free(bd_dimmp, maxbufsz);
3820 MC_LOG("mc_get_dimm_list: dimmlist=0x%p\n", (void *)dimm_list);
3821 return (dimm_list);
3822 }
3823
3824 /*
3825 * mc_prepare_dimmlist - Prepare the dimm list from the information
3826 * received from the SP.
3827 */
3828 mc_dimm_info_t *
mc_prepare_dimmlist(board_dimm_info_t * bd_dimmp)3829 mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp)
3830 {
3831 char *dimm_name;
3832 char *serial;
3833 char *part;
3834 int dimm;
3835 int dnamesz = bd_dimmp->bd_dnamesz;
3836 int sersz = bd_dimmp->bd_serialsz;
3837 int partsz = bd_dimmp->bd_partnumsz;
3838 mc_dimm_info_t *dimm_list = NULL;
3839 mc_dimm_info_t *d;
3840
3841 dimm_name = (char *)(bd_dimmp + 1);
3842 for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
3843
3844 d = (mc_dimm_info_t *)kmem_alloc(sizeof (mc_dimm_info_t),
3845 KM_SLEEP);
3846
3847 bcopy(dimm_name, d->md_dimmname, dnamesz);
3848 d->md_dimmname[dnamesz] = 0;
3849
3850 serial = dimm_name + dnamesz;
3851 bcopy(serial, d->md_serial, sersz);
3852 d->md_serial[sersz] = 0;
3853
3854 part = serial + sersz;
3855 bcopy(part, d->md_partnum, partsz);
3856 d->md_partnum[partsz] = 0;
3857
3858 d->md_next = dimm_list;
3859 dimm_list = d;
3860 dimm_name = part + partsz;
3861 }
3862 return (dimm_list);
3863 }
3864
3865 static int
mc_get_mem_fmri(mc_flt_page_t * fpag,char ** unum)3866 mc_get_mem_fmri(mc_flt_page_t *fpag, char **unum)
3867 {
3868 if (fpag->fmri_addr == 0 || fpag->fmri_sz > MEM_FMRI_MAX_BUFSIZE)
3869 return (EINVAL);
3870
3871 *unum = kmem_alloc(fpag->fmri_sz, KM_SLEEP);
3872 if (copyin((void *)fpag->fmri_addr, *unum, fpag->fmri_sz) != 0) {
3873 kmem_free(*unum, fpag->fmri_sz);
3874 return (EFAULT);
3875 }
3876 return (0);
3877 }
3878
3879 static int
mc_scf_log_event(mc_flt_page_t * flt_pag)3880 mc_scf_log_event(mc_flt_page_t *flt_pag)
3881 {
3882 mc_opl_t *mcp;
3883 int board, bank, slot;
3884 int len, rv = 0;
3885 char *unum, *sid;
3886 char dname[MCOPL_MAX_DIMMNAME + 1];
3887 size_t sid_sz;
3888 uint64_t pa;
3889 mc_flt_stat_t flt_stat;
3890
3891 if ((sid_sz = cpu_get_name_bufsize()) == 0)
3892 return (ENOTSUP);
3893
3894 if ((rv = mc_get_mem_fmri(flt_pag, &unum)) != 0) {
3895 MC_LOG("mc_scf_log_event: mc_get_mem_fmri failed\n");
3896 return (rv);
3897 }
3898
3899 sid = kmem_zalloc(sid_sz, KM_SLEEP);
3900
3901 if ((rv = mc_get_mem_sid(unum, sid, sid_sz, &len)) != 0) {
3902 MC_LOG("mc_scf_log_event: mc_get_mem_sid failed\n");
3903 goto out;
3904 }
3905
3906 if ((rv = mc_get_mem_addr(unum, sid, (uint64_t)flt_pag->err_add,
3907 &pa)) != 0) {
3908 MC_LOG("mc_scf_log_event: mc_get_mem_addr failed\n");
3909 goto out;
3910 }
3911
3912 if (parse_unum_memory(unum, &board, dname) != 0) {
3913 MC_LOG("mc_scf_log_event: parse_unum_memory failed\n");
3914 rv = EINVAL;
3915 goto out;
3916 }
3917
3918 if (board < 0) {
3919 MC_LOG("mc_scf_log_event: Invalid board=%d dimm=%s\n",
3920 board, dname);
3921 rv = EINVAL;
3922 goto out;
3923 }
3924
3925 if (dname_to_bankslot(dname, &bank, &slot) != 0) {
3926 MC_LOG("mc_scf_log_event: dname_to_bankslot failed\n");
3927 rv = EINVAL;
3928 goto out;
3929 }
3930
3931 mutex_enter(&mcmutex);
3932
3933 flt_stat.mf_err_add = flt_pag->err_add;
3934 flt_stat.mf_err_log = flt_pag->err_log;
3935 flt_stat.mf_flt_paddr = pa;
3936
3937 if ((mcp = mc_pa_to_mcp(pa)) == NULL) {
3938 mutex_exit(&mcmutex);
3939 MC_LOG("mc_scf_log_event: invalid pa\n");
3940 rv = EINVAL;
3941 goto out;
3942 }
3943
3944 MC_LOG("mc_scf_log_event: DIMM%s, /LSB%d/B%d/%x, pa %lx elog %x\n",
3945 unum, mcp->mc_board_num, bank, flt_pag->err_add, pa,
3946 flt_pag->err_log);
3947
3948 mutex_enter(&mcp->mc_lock);
3949
3950 if (!pa_is_valid(mcp, pa)) {
3951 mutex_exit(&mcp->mc_lock);
3952 mutex_exit(&mcmutex);
3953 rv = EINVAL;
3954 goto out;
3955 }
3956
3957 rv = 0;
3958
3959 mc_queue_scf_log(mcp, &flt_stat, bank);
3960
3961 mutex_exit(&mcp->mc_lock);
3962 mutex_exit(&mcmutex);
3963
3964 out:
3965 kmem_free(unum, flt_pag->fmri_sz);
3966 kmem_free(sid, sid_sz);
3967
3968 return (rv);
3969 }
3970
3971 #ifdef DEBUG
3972 void
mc_dump_dimm(char * buf,int dnamesz,int serialsz,int partnumsz)3973 mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz)
3974 {
3975 char dname[MCOPL_MAX_DIMMNAME + 1];
3976 char serial[MCOPL_MAX_SERIAL + 1];
3977 char part[ MCOPL_MAX_PARTNUM + 1];
3978 char *b;
3979
3980 b = buf;
3981 bcopy(b, dname, dnamesz);
3982 dname[dnamesz] = 0;
3983
3984 b += dnamesz;
3985 bcopy(b, serial, serialsz);
3986 serial[serialsz] = 0;
3987
3988 b += serialsz;
3989 bcopy(b, part, partnumsz);
3990 part[partnumsz] = 0;
3991
3992 printf("DIMM=%s Serial=%s PartNum=%s\n", dname, serial, part);
3993 }
3994
3995 void
mc_dump_dimm_info(board_dimm_info_t * bd_dimmp)3996 mc_dump_dimm_info(board_dimm_info_t *bd_dimmp)
3997 {
3998 int dimm;
3999 int dnamesz = bd_dimmp->bd_dnamesz;
4000 int sersz = bd_dimmp->bd_serialsz;
4001 int partsz = bd_dimmp->bd_partnumsz;
4002 char *buf;
4003
4004 printf("Version=%d Board=%02d DIMMs=%d NameSize=%d "
4005 "SerialSize=%d PartnumSize=%d\n", bd_dimmp->bd_version,
4006 bd_dimmp->bd_boardnum, bd_dimmp->bd_numdimms, bd_dimmp->bd_dnamesz,
4007 bd_dimmp->bd_serialsz, bd_dimmp->bd_partnumsz);
4008 printf("======================================================\n");
4009
4010 buf = (char *)(bd_dimmp + 1);
4011 for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
4012 mc_dump_dimm(buf, dnamesz, sersz, partsz);
4013 buf += dnamesz + sersz + partsz;
4014 }
4015 printf("======================================================\n");
4016 }
4017
4018
4019 /* ARGSUSED */
4020 static int
mc_ioctl_debug(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)4021 mc_ioctl_debug(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
4022 int *rvalp)
4023 {
4024 caddr_t buf, kbuf;
4025 uint64_t pa;
4026 int rv = 0;
4027 int i;
4028 uint32_t flags;
4029 static uint32_t offset = 0;
4030
4031
4032 flags = (cmd >> 4) & 0xfffffff;
4033
4034 cmd &= 0xf;
4035
4036 MC_LOG("mc_ioctl(cmd = %x, flags = %x)\n", cmd, flags);
4037
4038 if (arg != NULL) {
4039 if (ddi_copyin((const void *)arg, (void *)&pa,
4040 sizeof (uint64_t), 0) < 0) {
4041 rv = EFAULT;
4042 return (rv);
4043 }
4044 buf = NULL;
4045 } else {
4046 buf = (caddr_t)kmem_alloc(PAGESIZE, KM_SLEEP);
4047
4048 pa = va_to_pa(buf);
4049 pa += offset;
4050
4051 offset += 64;
4052 if (offset >= PAGESIZE)
4053 offset = 0;
4054 }
4055
4056 switch (cmd) {
4057 case MCI_CE:
4058 (void) mc_inject_error(MC_INJECT_INTERMITTENT_CE, pa, flags);
4059 break;
4060 case MCI_PERM_CE:
4061 (void) mc_inject_error(MC_INJECT_PERMANENT_CE, pa, flags);
4062 break;
4063 case MCI_UE:
4064 (void) mc_inject_error(MC_INJECT_UE, pa, flags);
4065 break;
4066 case MCI_M_CE:
4067 (void) mc_inject_error(MC_INJECT_INTERMITTENT_MCE, pa, flags);
4068 break;
4069 case MCI_M_PCE:
4070 (void) mc_inject_error(MC_INJECT_PERMANENT_MCE, pa, flags);
4071 break;
4072 case MCI_M_UE:
4073 (void) mc_inject_error(MC_INJECT_MUE, pa, flags);
4074 break;
4075 case MCI_CMP:
4076 (void) mc_inject_error(MC_INJECT_CMPE, pa, flags);
4077 break;
4078 case MCI_NOP:
4079 (void) mc_inject_error(MC_INJECT_NOP, pa, flags); break;
4080 case MCI_SHOW_ALL:
4081 mc_debug_show_all = 1;
4082 break;
4083 case MCI_SHOW_NONE:
4084 mc_debug_show_all = 0;
4085 break;
4086 case MCI_ALLOC:
4087 /*
4088 * just allocate some kernel memory and never free it
4089 * 512 MB seems to be the maximum size supported.
4090 */
4091 cmn_err(CE_NOTE, "Allocating kmem %d MB\n", flags * 512);
4092 for (i = 0; i < flags; i++) {
4093 kbuf = kmem_alloc(512 * 1024 * 1024, KM_SLEEP);
4094 cmn_err(CE_NOTE, "kmem buf %llx PA %llx\n",
4095 (u_longlong_t)kbuf, (u_longlong_t)va_to_pa(kbuf));
4096 }
4097 break;
4098 case MCI_SUSPEND:
4099 (void) opl_mc_suspend();
4100 break;
4101 case MCI_RESUME:
4102 (void) opl_mc_resume();
4103 break;
4104 default:
4105 rv = ENXIO;
4106 }
4107 if (buf)
4108 kmem_free(buf, PAGESIZE);
4109
4110 return (rv);
4111 }
4112
4113 #endif /* DEBUG */
4114