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