mc-opl.c revision aeb241b2bcd5321bd5e76ba2b5c9a8370d81a6de
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The contents of this file are subject to the terms of the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Common Development and Distribution License (the "License").
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You may not use this file except in compliance with the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * or http://www.opensolaris.org/os/licensing.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * See the License for the specific language governing permissions
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and limitations under the License.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * When distributing Covered Code, include this CDDL HEADER in each
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If applicable, add the following below this CDDL HEADER, with the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * fields enclosed by brackets "[]" replaced with your own identifying
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * information: Portions Copyright [yyyy] [name of copyright owner]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Function prototypes
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_open(dev_t *, int, int, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_close(dev_t, int, int, cred_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_attach(dev_info_t *, ddi_attach_cmd_t);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_detach(dev_info_t *, ddi_detach_cmd_t);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_poll_init(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_poll_fini(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_suspend(mc_opl_t *mcp, uint32_t flag);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_resume(mc_opl_t *mcp, uint32_t flag);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_get_mem_unum(int, uint64_t, char *, int, int *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_get_mem_offset(uint64_t paddr, uint64_t *offp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_dimm_info_t *mc_get_dimm_list(mc_opl_t *mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_dimm_info_t *mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int lsb, int bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_free_dimm_list(mc_dimm_info_t *d);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_polling(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_ioctl_debug(dev_t, int, intptr_t, int, cred_t *, int *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid mc_dump_dimm_info(board_dimm_info_t *bd_dimmp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int plat_max_boards(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Configuration data structures
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 0, /* streamtab */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 0, /* refcnt */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Driver globals
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy} plat_model = MODEL_DC; /* The default behaviour is DC */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The DIMM Names for DC platform.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The index into this table is made up of (bank, dslot),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Where dslot occupies bits 0-1 and bank occupies 2-4.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic char *mc_dc_dimm_unum_table[OPL_MAX_DIMMS] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --------CMUnn----------- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --CS0-----|--CS1------ */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* -H-|--L-- | -H- | -L-- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "13A", "12A", "13B", "12B", /* Bank 1 (MAC 0 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "23A", "22A", "23B", "22B", /* Bank 2 (MAC 1 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "33A", "32A", "33B", "32B", /* Bank 3 (MAC 1 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "01A", "00A", "01B", "00B", /* Bank 4 (MAC 2 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "11A", "10A", "11B", "10B", /* Bank 5 (MAC 2 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "21A", "20A", "21B", "20B", /* Bank 6 (MAC 3 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "31A", "30A", "31B", "30B" /* Bank 7 (MAC 3 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The DIMM Names for FF1/FF2 platforms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The index into this table is made up of (board, bank, dslot),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Where dslot occupies bits 0-1, bank occupies 2-4 and
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * board occupies the bit 5.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic char *mc_ff_dimm_unum_table[2 * OPL_MAX_DIMMS] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --------CMU0---------- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --CS0-----|--CS1------ */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* -H-|--L-- | -H- | -L-- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "01A", "00A", "01B", "00B", /* Bank 1 (MAC 0 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "13A", "12A", "13B", "12B", /* Bank 2 (MAC 1 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "11A", "10A", "11B", "10B", /* Bank 3 (MAC 1 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "23A", "22A", "23B", "22B", /* Bank 4 (MAC 2 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "21A", "20A", "21B", "20B", /* Bank 5 (MAC 2 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "33A", "32A", "33B", "32B", /* Bank 6 (MAC 3 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "31A", "30A", "31B", "30B", /* Bank 7 (MAC 3 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --------CMU1---------- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* --CS0-----|--CS1------ */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* -H-|--L-- | -H- | -L-- */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "43A", "42A", "43B", "42B", /* Bank 0 (MAC 0 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "41A", "40A", "41B", "40B", /* Bank 1 (MAC 0 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "53A", "52A", "53B", "52B", /* Bank 2 (MAC 1 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "51A", "50A", "51B", "50B", /* Bank 3 (MAC 1 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "63A", "62A", "63B", "62B", /* Bank 4 (MAC 2 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "61A", "60A", "61B", "60B", /* Bank 5 (MAC 2 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "73A", "72A", "73B", "72B", /* Bank 6 (MAC 3 bank 0) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "71A", "70A", "71B", "70B" /* Bank 7 (MAC 3 bank 1) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (((bd & 0x01) << 5) | ((bk & 0x07) << 2) | (s & 0x03))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define INDEX_TO_BANK(i) (((i) & 0x1C) >> 2)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define SLOT_TO_CS(slot) ((slot & 0x3) >> 1)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* Isolation unit size is 64 MB */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define MC_ISOLATION_BSIZE (64 * 1024 * 1024)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode, we normalized the bank idx to "even" since
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the HW treats them as one unit w.r.t programming.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This bank index will be the "effective" bank index.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * All mirrored bank state info on mc_period, mc_speedup_period
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * will be stored in the even bank structure to avoid code duplication.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic mc_scan_speed_t mc_scan_speeds[MC_MAX_SPEEDS] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint32_t mc_max_speed = (0x6 << 26);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_isolation_bsize = MC_ISOLATION_BSIZE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_patrol_interval_sec = MC_PATROL_INTERVAL_SEC;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_max_errlog_processed = BANKNUM_PER_SB*2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_scan_period = 12 * 60 * 60; /* 12 hours period */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * it takes SCF about 300 m.s. to process a requst. We can bail out
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * if it is busy. It does not pay to wait for it too long.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Mutex heierachy in mc-opl
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If both mcmutex and mc_lock must be held,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mcmutex must be acquired first, and then mc_lock.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_timeout_period = 0; /* this is in m.s. */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mod_driverops, /* module type, this one is a driver */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "OPL Memory-controller %I%", /* module name */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int (*opl_get_mem_unum)(int, uint64_t, char *, int, int *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int (*opl_get_mem_sid)(char *unum, char *buf, int buflen, int *lenp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int (*opl_get_mem_offset)(uint64_t paddr, uint64_t *offp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int (*opl_get_mem_addr)(char *unum, char *sid, uint64_t offset,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * pseudo-mc node portid format
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [8] = LSB_ID[4] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [7:4] = LSB_ID[3:0]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * These are the module initialization routines.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((error = ddi_soft_state_init(&mc_statep,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_init(&mcmutex, NULL, MUTEX_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) prom_getprop(node, "model", model);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((error = mod_remove(&modlinkage)) != 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_timedwait(&mc_polling_cv, &mc_polling_lock,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * signal if any one is waiting for this thread to exit.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* NOTREACHED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_init(&mc_polling_lock, NULL, MUTEX_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_init(&mc_polling_cv, NULL, CV_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_init(&mc_poll_exit_cv, NULL, CV_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_wait(&mc_poll_exit_cv, &mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get the instance of this devi */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp = ddi_get_soft_state(mc_statep, instance);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ddi_soft_state_zalloc(mc_statep, instance) != DDI_SUCCESS)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_patrol_interval_sec = (int)ddi_getprop(DDI_DEV_T_ANY, devi,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DDI_PROP_DONTPASS, "mc-timeout-interval-sec",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 1000000 * mc_patrol_interval_sec / OPL_MAX_BOARDS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* set informations in mc state */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Start the polling thread if it is not running already.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) thread_create(NULL, 0, (void (*)())mc_polling_thread,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get the instance of this devi */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mc_suspend(mcp, MC_DRIVER_SUSPENDED);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* free up the soft state */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_open(dev_t *devp, int flag, int otyp, cred_t *credp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_close(dev_t devp, int flag, int otyp, cred_t *credp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (mc_ioctl_debug(dev, cmd, arg, mode, credp, rvalp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA validity check:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This function return 1 if the PA is a valid PA
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * in the running Solaris instance i.e. in physinstall
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Otherwise, return 0.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mlist && address_in_memlist(mcp->mlist, addr, 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mac-pa translation routines.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Input: mc driver state, (LSB#, Bank#, DIMM address)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Output: physical address
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Valid - return value: 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Invalid - return value: -1
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymcaddr_to_pa(mc_opl_t *mcp, mc_addr_t *maddr, uint64_t *pa)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs = (maddr->ma_dimm_addr >> CS_SHIFT) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mcaddr /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* loc validity check */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(maddr->ma_bd >= 0 && OPL_BOARD_MAX > maddr->ma_bd);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Do translation */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = (maddr->ma_dimm_addr >> mc_bit) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (pa_to_maddr(mcp, *pa, &maddr1) == -1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "mcaddr_to_pa: /LSB%d/B%d/%x failed to "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode, PA is always translated to the even bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * there is no need to check ma_bd because it is generated from
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mcp. They are the same.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (maddr->ma_dimm_addr == maddr1.ma_dimm_addr)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Translation error source /LSB%d/B%d/%x, "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "PA %lx, target /LSB%d/B%d/%x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to CS (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_cs(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* MAC address bit<29> is arranged on the same PA bit */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* on both table. So we may use any table. */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_trans_table[0][i] == CS_SHIFT) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to DIMM (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_dimm(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to Bank (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_bank(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bankno = mcp->mc_trans_table[cs][INDEX_OF_BANK_SUPPLEMENT_BIT];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to MAC address translation
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Input: MAC driver state, physicall adress
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Output: LSB#, Bank id, mac address
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Valid - return value: 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Invalid - return value: -1
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Do translation */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_phys_bd = mcp->mc_phys_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_bank = pa_to_bank(mcp, pa_offset);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_dimm_addr = pa_to_dimm(mcp, pa_offset);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("pa %lx -> mcaddr /LSB%d/B%d/%x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_offset, maddr->ma_bd, maddr->ma_bank, maddr->ma_dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * UNUM format for DC is "/CMUnn/MEMxyZ", where
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * nn = 00..03 for DC1 and 00..07 for DC2 and 00..15 for DC3.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * x = MAC 0..3
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * y = 0..3 (slot info).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Z = 'A' or 'B'
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * UNUM format for FF1 is "/MBU_A/MEMBx/MEMyZ", where
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * x = 0..3 (MEMB number)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * y = 0..3 (slot info).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Z = 'A' or 'B'
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * UNUM format for FF2 is "/MBU_B/MEMBx/MEMyZ"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * x = 0..7 (MEMB number)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * y = 0..3 (slot info).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Z = 'A' or 'B'
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_set_mem_unum(char *buf, int buflen, int sb, int bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].unit_name, sb, dimmnm);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "/%s/%s%c/MEM%s MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].mem_name, memb_num,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *p, *s = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ereport = errorq_elem_nvl(ereport_errorq, eqep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nva = errorq_elem_nva(ereport_errorq, eqep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Create the scheme "dev" FMRI.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) ddi_pathname(mc_aflt->mflt_mcp->mc_dip, device_path);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Encode all the common data into the ereport.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_is_ptrl ? MC_OPL_PTRL_SUBCLASS :
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_ereport_post: ereport %s\n", buf);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_ena_generate(mc_aflt->mflt_id, FM_ENA_FMT1),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Set payload.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_BOARD, DATA_TYPE_UINT32,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_PA, DATA_TYPE_UINT64,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = mc_aflt->mflt_stat[i]->mf_flt_maddr.ma_bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_BANK, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = mc_aflt->mflt_stat[i]->mf_cntl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_STATUS, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = mc_aflt->mflt_stat[i]->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* offset is set only for PCE */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_aflt->mflt_stat[0]->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_ADD, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = mc_aflt->mflt_stat[i]->mf_err_log;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_LOG, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, synd, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_DIMMSLOT,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, dslot, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ret = mc_set_mem_unum(p + strlen(p), blen,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type, flt_stat->mf_dimm_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "mc_ereport_post: Failed to determine the unum "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "for board=%d bank=%d type=0x%x slot=0x%x",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type, flt_stat->mf_dimm_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ret = mc_set_mem_sid(mc_aflt->mflt_mcp, s + strlen(s),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy blen, flt_stat->mf_flt_maddr.ma_phys_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type, flt_stat->mf_dimm_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy NULL, device_path, (ret == 0) ? sid : NULL,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_RESOURCE, DATA_TYPE_NVLIST,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fm_ereport_post(ereport, EVCH_TRYHARD);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we come here only when we have:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode: CMPE, MUE, SUE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In normal mode: UE, Permanent CE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < mc_aflt->mflt_nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &(mc_aflt->mflt_stat[i]->mf_flt_maddr), &pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Ensure the pa is valid (not in isolated memory block) */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (rv == 0 && pa_is_valid(mc_aflt->mflt_mcp, pa))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[i]->mf_flt_paddr = (uint64_t)-1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Do page retirement except for the PCE case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This is taken care by the OPL DE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_aflt->mflt_stat[0]->mf_type != FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("offline page at pa %lx error %x\n", pa,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Some memory do not have page structure so
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we keep going in case of EINVAL.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < mc_aflt->mflt_nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_aflt->mflt_stat[i]->mf_flt_paddr != (uint64_t)-1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt0.mflt_stat[0] = mc_aflt->mflt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The restart address is actually defined in unit of PA[37:6]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the mac patrol will convert that to dimm offset. If the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * address is not in the bank, it will continue to search for
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the next PA that is within the bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Also the mac patrol scans the dimms based on PA, not
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * dimm offset.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyrestart_patrol(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr_info)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (rsaddr_info == NULL || (rsaddr_info->mi_valid == 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mcaddr_to_pa(mcp, &rsaddr_info->mi_restartaddr, &pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("cannot convert mcaddr to pa. use auto restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* pa is not on this board, just retry */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "restart_patrol: invalid address %lx "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * For non-errorinjection restart we need to
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * determine if the current restart pa/page is
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * a "good" page. A "good" page is a page that
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * has not been page retired. If the current
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * page that contains the pa is "good", we will
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * do a HW auto restart and let HW patrol continue
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * where it last stopped. Most desired scenario.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If the current page is not "good", we will advance
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to the next page to find the next "good" page and
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * restart the patrol from there.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Not in physinstall - advance to the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * next memory isolation blocksize
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((rv = page_retire_check(pa, NULL)) != 0 &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The page is "good" (not retired), we will
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * use automatic HW restart algorithm if
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * this is the original current starting page
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Page has no error. Auto restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* found a subsequent good page */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Skip to the next page
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Check to see if we hit the end of the memory range */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (pa >= (mcp->mc_start_address + mcp->mc_size)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Failed to find a good page. Just restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * We reached here either:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 1. We are doing an error injection restart that specify
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the exact pa/page to restart. OR
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 2. We found a subsequent good page different from the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * original restart pa/page.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Restart MAC patrol: PA[37:6]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_RESTART_ADD(mcp, bank), MAC_RESTART_PA(pa));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Rewriting is used for two purposes.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - to correct the error in memory.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - to determine whether the error is permanent or intermittent.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * It's done by writing the address in MAC_BANKm_REWRITE_ADD
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and issuing REW_REQ command in MAC_BANKm_PTRL_CNRL. After that,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * REW_END (and REW_CE/REW_UE if some error detected) is set when
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * rewrite operation is done. See 4.7.3 and 4.7.11 in Columbus2 PRM.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Note that rewrite operation doesn't change RAW_UE to Marked UE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Therefore, we use it only CE case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydo_rewrite(mc_opl_t *mcp, int bank, uint32_t dimm_addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* first wait to make sure PTRL_STATUS is 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If there are other MEMORY or PCI activities, this
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * will be BUSY, else it should be set immediately
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* This is bad. Just reset the circuit */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "mc-opl rewrite timeout on /LSB%d/B%d\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (bank = 0; bank < BANKNUM_PER_SB; bank++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while ((p = mcp->mc_scf_log[bank]) != NULL &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while ((LD_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_STATIC_ERR_LOG(mcp, p->sl_bank),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* if we try too many times, just drop the req */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_scf_retry[bank]++ <= mc_max_scf_retry) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "Cannot report Permanent CE to SCF\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_queue_scf_log(mc_opl_t *mcp, mc_flt_stat_t *flt_stat, int bank)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_scf_total[bank] >= mc_max_scf_logs) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Too many Permanent CE requests.\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p = kmem_zalloc(sizeof (scf_log_t), KM_SLEEP);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we rely on mc_scf_log to detect NULL queue.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mc_scf_log_tail is irrelevant is such case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_log_tail[bank] = mcp->mc_scf_log[bank] = p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This routine determines what kind of CE happens, intermittent
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * or permanent as follows. (See 4.7.3 in Columbus2 PRM.)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - Do rewrite by issuing REW_REQ command to MAC_PTRL_CNTL register.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - If CE is still detected on the same address even after doing
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * rewrite operation twice, it is determined as permanent error.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - If error is not detected anymore, it is determined as intermittent
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - If UE is detected due to rewrite operation, it should be treated
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_scrub_ce(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat, int ptrl_error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_PERMANENT_CE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * rewrite request 1st time reads and correct error data
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and write to DIMM. 2nd rewrite request must be issued
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * after REW_CE/UE/END is 0. When the 2nd request is completed,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * if REW_CE = 1, then it is permanent CE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = do_rewrite(mcp, bank, flt_stat->mf_err_add);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If the error becomes UE or CMPE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we return to the caller immediately.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_INTERMITTENT_CE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* report PERMANENT_CE to SP via SCF */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(flt_stat->mf_err_log & MAC_ERR_LOG_INVALID)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define IS_CMPE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_CMPE :\
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define IS_UE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_UE : MAC_CNTL_MI_UE))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define IS_CE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_CE : MAC_CNTL_MI_CE))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define IS_OK(cntl, f) (!((cntl) & ((f) ? MAC_CNTL_PTRL_ERRS : \
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return ((cntl & MAC_CNTL_PTRL_ERRS) == MAC_CNTL_PTRL_CE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return ((cntl & MAC_CNTL_MI_ERRS) == MAC_CNTL_MI_CE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_PTRL_CNTL(mcp, bank), value);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_read_ptrl_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_err_add = LD_MAC_REG(MAC_PTRL_ERR_ADD(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_err_log = LD_MAC_REG(MAC_PTRL_ERR_LOG(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_read_mi_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* we keep reading until the status is stable */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Error philosophy for mirror mode:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PTRL (The error address for both banks are same, since ptrl stops if it
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * detects error.)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - Compaire error Report CMPE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-UE Report MUE. No rewrite.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-* UE-(CE/OK). Rewrite to scrub UE. Report SUE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - CE-* CE-(CE/OK). Scrub to determine if CE is permanent.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If CE is permanent, inform SCF. Once for each
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Dimm. If CE becomes UE or CMPE, go back to above.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * MI (The error addresses for each bank are the same or different.)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - Compair error If addresses are the same. Just CMPE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If addresses are different (this could happen
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * as a result of scrubbing. Report each seperately.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Only report error info on each side.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-UE Addresses are the same. Report MUE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Addresses are different. Report SUE on each bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Rewrite to clear UE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-* UE-(CE/OK)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Rewrite to clear UE. Report SUE for the bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - CE-* CE-(CE/OK). Scrub to determine if CE is permanent.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If CE becomes UE or CMPE, go back to above.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_process_error_mir(mc_opl_t *mcp, mc_aflt_t *mc_aflt, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("process mirror errors cntl[0] = %x, cntl[1] = %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[0].mf_cntl, flt_stat[1].mf_cntl);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * First we take care of the case of CE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * because they can become UE or CMPE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_CE_ONLY(flt_stat[i].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_scrub_ce(mcp, flt_stat[i].mf_flt_maddr.ma_bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* The above scrubbing can turn CE into UE or CMPE */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Now we distinguish two cases: same address or not
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the same address. It might seem more intuitive to
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * distinguish PTRL v.s. MI error but it is more
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * complicated that way.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat[0].mf_err_add == flt_stat[1].mf_err_add) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_CMPE(flt_stat[0].mf_cntl, ptrl_error) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy IS_CMPE(flt_stat[1].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat[0].mf_cntl, ptrl_error) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Both side are UE's */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Now the only case is UE/CE, UE/OK, or don't care */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* rewrite can clear the one side UE error */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_OK(flt_stat[i^1].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Once we hit a UE/CE or UE/OK case, done */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * addresses are different. That means errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * on the 2 banks are not related at all.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_CMPE(flt_stat[i].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* no more report on this bank */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* rewrite can clear the one side UE error */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_error_handler_mir(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_flt_stat_t flt_stat[2], mi_flt_stat[2];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&flt_stat, 2 * sizeof (mc_flt_stat_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&mi_flt_stat, 2 * sizeof (mc_flt_stat_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Now read all the registers into flt_stat */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < 2; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Reading registers of bank %d\n", bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* patrol registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_read_ptrl_reg(mcp, bank, &flt_stat[i]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode, it is possible that only one bank
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * may report the error. We need to check for it to
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * ensure we pick the right addr value for patrol restart.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Note that if both banks reported errors, we pick the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 2nd one. Both banks should reported the same error address.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat[i].mf_cntl & MAC_CNTL_PTRL_ERRS)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_restartaddr = flt_stat[i].mf_flt_maddr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("ptrl registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* MI registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_read_mi_reg(mcp, bank, &mi_flt_stat[i]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("MI registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* clear errors once we read all the registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank ^ 1, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Process MI errors first */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* if not error mode, cntl1 is 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mi_flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (mi_flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mi_flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (mi_flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_valid = mc_process_error_mir(mcp, &mc_aflt, &mi_flt_stat[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((((flt_stat[0].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat[0].mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat[0].mf_err_add == mi_flt_stat[0].mf_err_add) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (((flt_stat[1].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat[1].mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat[1].mf_err_add == mi_flt_stat[1].mf_err_add)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "it is the same as MI\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* if not error mode, cntl1 is 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_valid = mc_process_error_mir(mcp, &mc_aflt, &flt_stat[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_process_error(mc_opl_t *mcp, int bank, mc_aflt_t *mc_aflt,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat->mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (IS_CE(flt_stat->mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Error type can change after scrubing */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_scrub_ce(mcp, bank, flt_stat, ptrl_error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (flt_stat->mf_type == FLT_TYPE_UE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_process_error: fault type %x erpt %s\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_error_handler(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&mi_flt_stat, sizeof (mc_flt_stat_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* patrol registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_restartaddr = flt_stat.mf_flt_maddr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("ptrl registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* MI registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("MI registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* clear errors once we read all the registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_valid = mc_process_error(mcp, bank, &mc_aflt, &mi_flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat.mf_err_add == mi_flt_stat.mf_err_add)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "it is the same as MI\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_valid = mc_process_error(mcp, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * memory patrol error handling algorithm:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * timeout() is used to do periodic polling
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This is the flow chart.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mc_check_errors()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * if memory bank is installed, read the status register
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * if any error bit is set,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -> mc_error_handler()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -> read all error regsiters
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -> mc_process_error()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * determine error type
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * rewrite to clear error or scrub to determine CE type
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * inform SCF on permanent CE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -> mc_err_drain
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * page offline processing
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -> mc_ereport_post()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * scan errors.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Compute the effective bank idx */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ebk = (IS_MIRROR(mcp, i)) ? MIRROR_IDX(i) : i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Update stats and reset flag if the HW patrol
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * wrapped around in its scan.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Mac patrol HW is still running.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Normally when an error is detected,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the HW patrol will stop so that we
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * can collect error data for reporting.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Certain errors (MI errors) detected may not
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * cause the HW patrol to stop which is a
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * problem since we cannot read error data while
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the HW patrol is running. SW is not allowed
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to stop the HW patrol while it is running
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * as it may cause HW inconsistency. This is
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * described in a HW errata.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In situations where we detected errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * that may not cause the HW patrol to stop.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * We speed up the HW patrol scanning in
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the hope that it will find the 'real' PTRL
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * errors associated with the previous errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * causing the HW to finally stop so that we
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * can do the reporting.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Check to see if we did speed up
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * the HW patrol due to previous errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * detected that did not cause the patrol
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to stop. We only do it if HW patrol scan
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * wrapped (counted as completing a 'period').
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * We did try to speed up.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The speed up period has expired
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and the HW patrol is still running.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The errors must be intermittent.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * We have no choice but to ignore
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * them, reset the scan speed to normal
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * and clear the MI error bits. For
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mirror mode, we need to clear errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * on both banks.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * MI errors detected but we cannot
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * report them since the HW patrol
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * is still running.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * We will attempt to speed up the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * scanning and hopefully the HW
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * can detect PRTL errors at the same
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * location that cause the HW patrol
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * HW Patrol has stopped and we found errors.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Proceed to collect and report error info.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_error_handler_mir(mcp, i, &rsaddr_info);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * HW patrol scan has apparently stopped
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * but no errors detected/flagged.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Restart the HW patrol just to be sure.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode, the odd bank might have
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * reported errors that caused the patrol to
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * stop. We'll defer the restart to the odd
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * bank in this case.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mc_polling -- Check errors for only one instance,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * but process errors for all instances to make sure we drain the errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * faster than they can be accumulated.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Polling on each board should be done only once per each
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mc_patrol_interval_sec. This is equivalent to setting mc_tick_left
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to OPL_MAX_BOARDS and decrement by 1 on each timeout.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Once mc_tick_left becomes negative, the board becomes a candidate
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * for polling because it has waited for at least
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mc_patrol_interval_sec's long. If mc_timeout_period is calculated
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * differently, this has to beupdated accordingly.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < OPL_MAX_BOARDS; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(mcp->mc_status & MC_POLL_RUNNING)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (scan_error && mcp->mc_tick_left <= 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyget_ptrl_start_address(mc_opl_t *mcp, int bank, mc_addr_t *maddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "sb-mem-ranges", (caddr_t)&mem_range, &len) != DDI_SUCCESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define REGS_PA(m, i) ((((uint64_t)m[i].phys_hi)<<32) | m[i].phys_lo)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic char *mc_tbl_name[] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "cs0-mc-pa-trans-table",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "cs1-mc-pa-trans-table"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This routine performs a rangecheck for a given PA
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to see if it belongs to the memory range for this board.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Return 1 if it is valid (within the range) and 0 otherwise
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (mcp->mc_start_address + mcp->mc_size <= pa))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct memlist *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *mlp = kmem_alloc(sizeof (struct memlist), KM_SLEEP);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct memlist *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((end <= mlist->address) || (base == end))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * splitting an memlist entry.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlist = mc_memlist_del_span(mlist, 0ull, mcp->mc_start_address);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy startpa = mcp->mc_start_address + mcp->mc_size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Get configurations from "pseudo-mc" node which includes:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * board# : LSB number
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mac-addr : physical base address of MAC registers
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * csX-mac-pa-trans-table: translation table from DIMM address
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * to physical address or vice versa.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num = (int)ddi_getprop(DDI_DEV_T_ANY, mcp->mc_dip,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Get start address in this CAB. It can be gotten from
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * "sb-mem-ranges" property.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (get_base_address(mcp) == DDI_FAILURE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get mac-pa trans tables */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < MC_TT_CS; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cc = ddi_getlongprop_buf(DDI_DEV_T_ANY, mcp->mc_dip,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(mcp->mc_trans_table[i], MC_TT_ENTRIES);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* initialize bank informations */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Cannot get mc-addr. err=%d\n", cc);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Cannot get cs-status. err=%d\n", cc);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get the physical board number for a given logical board number */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_phys_board_num = mc_opl_get_physical_board(mcp->mc_board_num);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Unable to obtain the physical board number");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_init(&mcp->mc_lock, NULL, MUTEX_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < len1 / sizeof (cs_status_t); i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nbytes += ((uint64_t)cs_status[i].cs_avail_hi << 32) |
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nbanks = len / sizeof (struct mc_addr_spec);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* No need to free macaddr because len must be 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Get the memory size here. Let it be B (bytes).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Let T be the time in u.s. to scan 64 bytes.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If we want to complete 1 round of scanning in P seconds.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * B * T * 10^(-6) = P
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * ---------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * T = P * 64 * 10^6
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * = P * 64 * 10^6
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The timing bits are set in PTRL_CNTL[28:26] where
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 111 - reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * a[0] = 110, a[1] = 101, ... a[6] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * cs-status property is int x 7
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 1 - cs-status
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 3 - cs-avail.lo
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 5 - dimm-capa.lo
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 6 - #of dimms
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ms = ((uint64_t)mc_scan_period * 64 * 1000000)/nbytes;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speed = mc_scan_speeds[MC_MAX_SPEEDS - 1].mc_speeds;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ms < mc_scan_speeds[i + 1].mc_period) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speed = mc_scan_speeds[i].mc_speeds;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < len / sizeof (struct mc_addr_spec); i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_reg_base = REGS_PA(macaddr, i);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_ptrl_cntl = (reg & MAC_CNTL_PTRL_PRESERVE_BITS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * check if mirror mode
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The following bit is only used for
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * error injection. We should clear it
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * restart if not mirror mode or the other bank
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * of the mirror is not running
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy get_ptrl_start_address(mcp, bk, &rsaddr.mi_restartaddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_dimm_list = mc_get_dimm_list(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * set interval in HZ.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* restart memory patrol checking */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * cleanup mac state
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_bank[i].mcb_status &= ~BANK_INSTALLED;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* stop memory patrol checking */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* just throw away all the scf logs */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while ((p = mcp->mc_scf_log[i]) != NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* stop memory patrol checking */
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy/* caller must clear the SUSPEND bits or this will do nothing */
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (get_base_address(mcp) == DDI_FAILURE) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (!(mcp->mc_status & MC_POLL_RUNNING)) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy /* restart memory patrol checking */
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
static mc_opl_t *
for (i = 0; i < OPL_MAX_BOARDS; i++) {
return (mcp);
return (NULL);
if (&opl_get_physical_board) {
int *lenp)
int sb;
int bank;
int cs;
char memb_num;
return (ENOSPC);
if (lenp)
return (ENXIO);
if (lenp) {
opl_mc_suspend(void)
for (i = 0; i < OPL_MAX_BOARDS; i++) {
opl_mc_resume(void)
for (i = 0; i < OPL_MAX_BOARDS; i++) {
int bank;
int both_sides = 0;
int extra_injection_needed = 0;
extern void cpu_flush_ecache(void);
return (ENOTSUP);
return (EBUSY);
return (EINVAL);
return (EINVAL);
switch (error_type) {
case MC_INJECT_PERMANENT_MCE:
case MC_INJECT_MUE:
if (both_sides) {
switch (error_type) {
case MC_INJECT_SUE:
case MC_INJECT_UE:
case MC_INJECT_MUE:
case MC_INJECT_PERMANENT_CE:
case MC_INJECT_PERMANENT_MCE:
case MC_INJECT_CMPE:
membar_sync();
cntl = 0;
case MC_INJECT_NOP:
cntl = 0;
cntl = 0;
if (cntl) {
if (both_sides) {
if (extra_injection_needed) {
if (both_sides) {
int running;
if (!running &&
return (rv);
if (*board < 0) {
dname[0] = x;
return (ENOTSUP);
if (d != NULL) {
ret = 0;
return (ret);
int id;
int ret;
char *dimmnm;
&lenp)) != 0) {
return (ret);
int board;
return (EINVAL);
if (board < 0) {
return (EINVAL);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if (ret == 0) {
return (ret);
ret = 0;
return (ret);
int tsz;
char **tbl;
for (i = 0; i < tsz; i++) {
if (i == tsz) {
int board;
int bank;
int slot;
return (EINVAL);
if (board < 0) {
return (EINVAL);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if (ret != 0) {
if (ret != 0) {
return (ret);
while (d != NULL) {
d = next;
int ret;
int sexp;
if (ret == 0) {
#ifdef DEBUG
if (oplmc_debug)
return (dimm_list);
char *dimm_name;
char *serial;
char *part;
int dimm;
mc_dimm_info_t *d;
KM_SLEEP);
dimm_list = d;
return (dimm_list);
#ifdef DEBUG
b = buf;
b += dnamesz;
b += serialsz;
int dimm;
char *buf;
int *rvalp)
int rv = 0;
sizeof (uint64_t), 0) < 0) {
return (rv);
offset = 0;
switch (cmd) {
case MCI_CE:
flags);
case MCI_PERM_CE:
flags);
case MCI_UE:
flags);
case MCI_M_CE:
flags);
case MCI_M_PCE:
flags);
case MCI_M_UE:
flags);
case MCI_CMP:
flags);
case MCI_NOP:
case MCI_SHOW_ALL:
case MCI_SHOW_NONE:
mc_debug_show_all = 0;
case MCI_ALLOC:
for (i = 0; i < flags; i++) {
case MCI_SUSPEND:
(void) opl_mc_suspend();
case MCI_RESUME:
(void) opl_mc_resume();
return (rv);