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