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