mc-opl.c revision aeb241b2bcd5321bd5e76ba2b5c9a8370d81a6de
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER START
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
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 *
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 *
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * CDDL HEADER END
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Use is subject to license terms.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma ident "%Z%%M% %I% %E% SMI"
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/types.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/sysmacros.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/conf.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/modctl.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/stat.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/async.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/machcpuvar.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/machsystm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/promif.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/ksynch.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/ddi.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/sunddi.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/ddifm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/fm/protocol.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/fm/util.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/kmem.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/fm/io/opl_mc_fm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/memlist.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/param.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/disp.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <vm/page.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/mc-opl.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/opl.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/opl_dimm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/scfd/scfostoescf.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/cpu_module.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <vm/seg_kmem.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/vmem.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <vm/hat_sfmmu.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/vmsystm.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/membar.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Function prototypes
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
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 Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_poll_init(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_poll_fini(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_board_add(mc_opl_t *mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_board_del(mc_opl_t *mcp);
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 Kennedyint opl_mc_suspend(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint opl_mc_resume(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void insert_mcp(mc_opl_t *mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void delete_mcp(mc_opl_t *mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 Kennedy int buflen, int *lenp);
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 Kennedy uint32_t mf_type, uint32_t d_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_free_dimm_list(mc_dimm_info_t *d);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_get_mlist(mc_opl_t *);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void mc_polling(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_opl_get_physical_board(int);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#ifdef DEBUG
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 Kennedy#endif
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma weak opl_get_physical_board
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int opl_get_physical_board(int);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern int plat_max_boards(void);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Configuration data structures
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct cb_ops mc_cb_ops = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_open, /* open */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_close, /* close */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* strategy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* print */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev, /* dump */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* read */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* write */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_ioctl, /* ioctl */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev, /* devmap */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev, /* mmap */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev, /* segmap */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nochpoll, /* poll */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_prop_op, /* cb_prop_op */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 0, /* streamtab */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy CB_REV, /* rev */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev, /* cb_aread */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nodev /* cb_awrite */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct dev_ops mc_ops = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DEVO_REV, /* rev */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 0, /* refcnt */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_getinfo_1to1, /* getinfo */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* identify */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* probe */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_attach, /* attach */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_detach, /* detach */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev, /* reset */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mc_cb_ops, /* cb_ops */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (struct bus_ops *)0, /* bus_ops */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nulldev /* power */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Driver globals
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic enum {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MODEL_FF1 = 0,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MODEL_FF2 = 1,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MODEL_DC = 2
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy} plat_model = MODEL_DC; /* The default behaviour is DC */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct plat_model_names {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy const char *unit_name;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy const char *mem_name;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy} model_names[] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy { "MBU_A", "MEMB" },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy { "MBU_B", "MEMB" },
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy { "CMU", "" }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 Kennedy */
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};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 Kennedy */
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};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define BD_BK_SLOT_TO_INDEX(bd, bk, s) \
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (((bd & 0x01) << 5) | ((bk & 0x07) << 2) | (s & 0x03))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define INDEX_TO_BANK(i) (((i) & 0x1C) >> 2)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define INDEX_TO_SLOT(i) ((i) & 0x03)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define SLOT_TO_CS(slot) ((slot & 0x3) >> 1)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* Isolation unit size is 64 MB */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define MC_ISOLATION_BSIZE (64 * 1024 * 1024)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define MC_MAX_SPEEDS 7
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t mc_speeds;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t mc_period;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy} mc_scan_speed_t;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define MC_CNTL_SPEED_SHIFT 26
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define MIRROR_IDX(bankidx) (bankidx & ~1)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic mc_scan_speed_t mc_scan_speeds[MC_MAX_SPEEDS] = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x6 << MC_CNTL_SPEED_SHIFT, 0},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x5 << MC_CNTL_SPEED_SHIFT, 32},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x4 << MC_CNTL_SPEED_SHIFT, 64},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x3 << MC_CNTL_SPEED_SHIFT, 128},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x2 << MC_CNTL_SPEED_SHIFT, 256},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x1 << MC_CNTL_SPEED_SHIFT, 512},
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy {0x0 << MC_CNTL_SPEED_SHIFT, 1024}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint32_t mc_max_speed = (0x6 << 26);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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_scf_retry = 16;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_max_scf_logs = 64;
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 Kennedyint mc_max_rewrite_loop = 100;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_rewrite_delay = 10;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_max_scf_loop = 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_scf_delay = 100;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_pce_dropped = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_poll_priority = MINCLSYSPRI;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic kmutex_t mcmutex;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_opl_t *mc_instances[OPL_MAX_BOARDS];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic kmutex_t mc_polling_lock;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic kcondvar_t mc_polling_cv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic kcondvar_t mc_poll_exit_cv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_poll_cmd = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_pollthr_running = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint mc_timeout_period = 0; /* this is in m.s. */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid *mc_statep;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#ifdef DEBUG
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint oplmc_debug = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#endif
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int mc_debug_show_all = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyextern struct mod_ops mod_driverops;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct modldrv modldrv = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mod_driverops, /* module type, this one is a driver */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "OPL Memory-controller %I%", /* module name */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mc_ops, /* driver ops */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct modlinkage modlinkage = {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MODREV_1, /* rev */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void *)&modldrv,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy NULL
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma weak opl_get_mem_unum
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma weak opl_get_mem_sid
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma weak opl_get_mem_offset
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#pragma weak opl_get_mem_addr
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 uint64_t *paddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * pseudo-mc node portid format
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [10] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [9] = 1
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [8] = LSB_ID[4] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [7:4] = LSB_ID[3:0]
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * [3:0] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * These are the module initialization routines.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy_init(void)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int plen;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char model[20];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pnode_t node;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((error = ddi_soft_state_init(&mc_statep,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy sizeof (mc_opl_t), 1)) != 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((error = mc_poll_init()) != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_soft_state_fini(&mc_statep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_init(&mcmutex, NULL, MUTEX_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_unum)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_unum = mc_get_mem_unum;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_sid)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_sid = mc_get_mem_sid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_offset = mc_get_mem_offset;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_addr = mc_get_mem_addr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy node = prom_rootnode();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy plen = prom_getproplen(node, "model");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (plen > 0 && plen < sizeof (model)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) prom_getprop(node, "model", model);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model[plen] = '\0';
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (strcmp(model, "FF1") == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy plat_model = MODEL_FF1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else if (strcmp(model, "FF2") == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy plat_model = MODEL_FF2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else if (strncmp(model, "DC", 2) == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy plat_model = MODEL_DC;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error = mod_install(&modlinkage);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_unum)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_unum = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_sid)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_sid = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_offset = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_addr = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_destroy(&mcmutex);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_poll_fini();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_soft_state_fini(&mc_statep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy_fini(void)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((error = mod_remove(&modlinkage)) != 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_unum)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_unum = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_sid)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_sid = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_offset = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (&opl_get_mem_addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy opl_get_mem_addr = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_destroy(&mcmutex);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_poll_fini();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_soft_state_fini(&mc_statep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy_info(struct modinfo *modinfop)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (mod_info(&modlinkage, modinfop));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_polling_thread()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_pollthr_running = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (!(mc_poll_cmd & MC_POLL_EXIT)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_polling();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_timedwait(&mc_polling_cv, &mc_polling_lock,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_get_lbolt() + mc_timeout_period);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_pollthr_running = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * signal if any one is waiting for this thread to exit.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_signal(&mc_poll_exit_cv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy thread_exit();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* NOTREACHED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_poll_init()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
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 return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_poll_fini()
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_pollthr_running) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_poll_cmd = MC_POLL_EXIT;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_signal(&mc_polling_cv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (mc_pollthr_running) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_wait(&mc_poll_exit_cv, &mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_destroy(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_destroy(&mc_polling_cv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cv_destroy(&mc_poll_exit_cv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_opl_t *mcp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int instance;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get the instance of this devi */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy instance = ddi_get_instance(devi);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy switch (cmd) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case DDI_ATTACH:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case DDI_RESUME:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp = ddi_get_soft_state(mc_statep, instance);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mc_resume(mcp, MC_DRIVER_SUSPENDED);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (rv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy default:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ddi_soft_state_zalloc(mc_statep, instance) != DDI_SUCCESS)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto bad;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_timeout_period == 0) {
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 mc_patrol_interval_sec);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_timeout_period = drv_usectohz(
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 1000000 * mc_patrol_interval_sec / OPL_MAX_BOARDS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* set informations in mc state */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_dip = devi;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_board_add(mcp))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto bad;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy insert_mcp(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Start the polling thread if it is not running already.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!mc_pollthr_running) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) thread_create(NULL, 0, (void (*)())mc_polling_thread,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy NULL, 0, &p0, TS_RUN, mc_poll_priority);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mc_polling_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_report_dev(devi);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedybad:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_soft_state_free(mc_statep, instance);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int instance;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_opl_t *mcp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get the instance of this devi */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy instance = ddi_get_instance(devi);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy switch (cmd) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case DDI_SUSPEND:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mc_suspend(mcp, MC_DRIVER_SUSPENDED);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (rv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case DDI_DETACH:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy default:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy delete_mcp(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_board_del(mcp) != DDI_SUCCESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* free up the soft state */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ddi_soft_state_free(mc_statep, instance);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_open(dev_t *devp, int flag, int otyp, cred_t *credp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_close(dev_t devp, int flag, int otyp, cred_t *credp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int *rvalp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#ifdef DEBUG
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (mc_ioctl_debug(dev, cmd, arg, mode, credp, rvalp));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (ENXIO);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#endif
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_is_valid(mc_opl_t *mcp, uint64_t addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mlist == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_get_mlist(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mlist && address_in_memlist(mcp->mlist, addr, 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * mac-pa translation routines.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Input: mc driver state, (LSB#, Bank#, DIMM address)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Output: physical address
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Valid - return value: 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Invalid - return value: -1
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymcaddr_to_pa(mc_opl_t *mcp, mc_addr_t *maddr, uint64_t *pa)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t pa_offset = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs = (maddr->ma_dimm_addr >> CS_SHIFT) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bank = maddr->ma_bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_addr_t maddr1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bank0, bank1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mcaddr /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* loc validity check */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(maddr->ma_bd >= 0 && OPL_BOARD_MAX > maddr->ma_bd);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(bank >= 0 && OPL_BANK_MAX > bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Do translation */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int pa_bit = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int mc_bit = mcp->mc_trans_table[cs][i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_bit < MC_ADDRESS_BITS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = (maddr->ma_dimm_addr >> mc_bit) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (mc_bit == MP_NONE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (mc_bit == MP_BANK_0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = bank & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (mc_bit == MP_BANK_1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = (bank >> 1) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (mc_bit == MP_BANK_2) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_bit = (bank >> 2) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_offset |= ((uint64_t)pa_bit) << i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *pa = mcp->mc_start_address + pa_offset;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("pa = %lx\n", *pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 "convert PA %lx\n", maddr->ma_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_dimm_addr, *pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (-1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * In mirror mode, PA is always translated to the even bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_MIRROR(mcp, maddr->ma_bank)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank0 = maddr->ma_bank & ~(1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank1 = maddr1.ma_bank & ~(1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank0 = maddr->ma_bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank1 = maddr1.ma_bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((bank0 == bank1) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (maddr->ma_dimm_addr == maddr1.ma_dimm_addr)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
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 maddr->ma_bd, bank, maddr->ma_dimm_addr,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *pa, maddr1.ma_bd, maddr1.ma_bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr1.ma_dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (-1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to CS (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_cs(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 cs = (pa_offset >> i) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (cs);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to DIMM (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint32_t
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_dimm(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs = pa_to_cs(mcp, pa_offset);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t dimm_addr = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int pa_bit_value = (pa_offset >> i) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int mc_bit = mcp->mc_trans_table[cs][i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_bit < MC_ADDRESS_BITS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dimm_addr |= pa_bit_value << mc_bit;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dimm_addr |= cs << CS_SHIFT;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to Bank (used by pa_to_maddr).
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_bank(mc_opl_t *mcp, uint64_t pa_offset)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs = pa_to_cs(mcp, pa_offset);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bankno = mcp->mc_trans_table[cs][INDEX_OF_BANK_SUPPLEMENT_BIT];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < PA_BITS_FOR_MAC; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int pa_bit_value = (pa_offset >> i) & 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int mc_bit = mcp->mc_trans_table[cs][i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy switch (mc_bit) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case MP_BANK_0:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankno |= pa_bit_value;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case MP_BANK_1:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankno |= pa_bit_value << 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case MP_BANK_2:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankno |= pa_bit_value << 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (bankno);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * PA to MAC address translation
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Input: MAC driver state, physicall adress
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Output: LSB#, Bank id, mac address
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Valid - return value: 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Invalid - return value: -1
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedypa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t pa_offset;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!mc_rangecheck_pa(mcp, pa))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (-1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Do translation */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa_offset = pa - mcp->mc_start_address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_bd = mcp->mc_board_num;
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 return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 *
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 *
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 Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_set_mem_unum(char *buf, int buflen, int sb, int bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t mf_type, uint32_t d_slot)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *dimmnm;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char memb_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int cs;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int j;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cs = SLOT_TO_CS(d_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (plat_model == MODEL_DC) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy i = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dimmnm = mc_dc_dimm_unum_table[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(buf, buflen, "/%s%02d/MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].unit_name, sb, dimmnm);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy j = (cs == 0) ? i : i + 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].unit_name, sb,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_dc_dimm_unum_table[j],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_dc_dimm_unum_table[j + 1]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dimmnm = mc_ff_dimm_unum_table[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy memb_num = dimmnm[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(buf, buflen, "/%s/%s%c/MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].unit_name,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].mem_name,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy memb_num, &dimmnm[1]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy j = (cs == 0) ? i : i + 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy memb_num = mc_ff_dimm_unum_table[i][0],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(buf, buflen,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "/%s/%s%c/MEM%s MEM%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].unit_name,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy model_names[plat_model].mem_name, memb_num,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mc_ff_dimm_unum_table[j][1],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &mc_ff_dimm_unum_table[j + 1][1]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_ereport_post(mc_aflt_t *mc_aflt)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char buf[FM_MAX_CLASS];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char device_path[MAXPATHLEN];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char sid[MAXPATHLEN];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nv_alloc_t *nva = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nvlist_t *ereport, *detector, *resource;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy errorq_elem_t *eqep;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int nflts;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_flt_stat_t *flt_stat;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i, n;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int blen = MAXPATHLEN;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *p, *s = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t values[2], synd[2], dslot[2];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t offset = (uint64_t)-1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ret = -1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (panicstr) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy eqep = errorq_reserve(ereport_errorq);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (eqep == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ereport = errorq_elem_nvl(ereport_errorq, eqep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nva = errorq_elem_nva(ereport_errorq, eqep);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ereport = fm_nvlist_create(nva);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Create the scheme "dev" FMRI.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy detector = fm_nvlist_create(nva);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy resource = fm_nvlist_create(nva);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nflts = mc_aflt->mflt_nflts;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(nflts >= 1 && nflts <= 2);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat = mc_aflt->mflt_stat[0];
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 device_path, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Encode all the common data into the ereport.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_OPL_ERROR_CLASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_is_ptrl ? MC_OPL_PTRL_SUBCLASS :
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_OPL_MI_SUBCLASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_ereport_post: ereport %s\n", buf);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 detector, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Set payload.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_BOARD, DATA_TYPE_UINT32,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_bd, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_PA, DATA_TYPE_UINT64,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_paddr, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_FLT_TYPE,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT8, ECC_STICKY, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_BANK, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = mc_aflt->mflt_stat[i]->mf_cntl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_STATUS, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
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 offset = values[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_ADD, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_LOG, DATA_TYPE_UINT32_ARRAY,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat = mc_aflt->mflt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_errlog_valid) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy synd[i] = flt_stat->mf_synd;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dslot[i] = flt_stat->mf_dimm_slot;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = flt_stat->mf_dram_place;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy synd[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dslot[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy values[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_SYND,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, synd, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_DIMMSLOT,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, dslot, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_ERR_DRAM,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DATA_TYPE_UINT32_ARRAY, nflts, values, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy device_path[0] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p = &device_path[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy sid[0] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy s = &sid[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ret = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat = mc_aflt->mflt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank = flt_stat->mf_flt_maddr.ma_bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ret = mc_set_mem_unum(p + strlen(p), blen,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_phys_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type, flt_stat->mf_dimm_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ret != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN,
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_flt_maddr.ma_bd, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type, flt_stat->mf_dimm_slot);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy continue;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy n = strlen(device_path);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy blen = MAXPATHLEN - n;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p = &device_path[n];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (i < (nflts - 1)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy snprintf(p, blen, " ");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy blen--;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ret == 0) {
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 (ret == 0) ? offset : (uint64_t)-1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_payload_set(ereport, MC_OPL_RESOURCE, DATA_TYPE_NVLIST,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy resource, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (panicstr) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fm_ereport_post(ereport, EVCH_TRYHARD);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_nvlist_destroy(ereport, FM_NVA_FREE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_nvlist_destroy(detector, FM_NVA_FREE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fm_nvlist_destroy(resource, FM_NVA_FREE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_err_drain(mc_aflt_t *mc_aflt)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t pa = (uint64_t)(-1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_err_drain: %s\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < mc_aflt->mflt_nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mcaddr_to_pa(mc_aflt->mflt_mcp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &(mc_aflt->mflt_stat[i]->mf_flt_maddr), &pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 = pa;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[i]->mf_flt_paddr = (uint64_t)-1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_err_drain:pa = %lx\n", pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy switch (page_retire_check(pa, NULL)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case 0:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case EAGAIN:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Page retired or pending\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case EIO:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
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 mc_aflt->mflt_pr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) page_retire(pa, mc_aflt->mflt_pr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case EINVAL:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy default:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Some memory do not have page structure so
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we keep going in case of EINVAL.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < mc_aflt->mflt_nflts; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt_t mc_aflt0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_aflt->mflt_stat[i]->mf_flt_paddr != (uint64_t)-1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt0 = *mc_aflt;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt0.mflt_nflts = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt0.mflt_stat[0] = mc_aflt->mflt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_ereport_post(&mc_aflt0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Also the mac patrol scans the dimms based on PA, not
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * dimm offset.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyrestart_patrol(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr_info)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t pa;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (rsaddr_info == NULL || (rsaddr_info->mi_valid == 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = mcaddr_to_pa(mcp, &rsaddr_info->mi_restartaddr, &pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (rv != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("cannot convert mcaddr to pa. use auto restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!mc_rangecheck_pa(mcp, pa)) {
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 "on board %d\n", pa, mcp->mc_board_num);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("restart_patrol: pa = %lx\n", pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!rsaddr_info->mi_injectrestart) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 *
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int wrapcount = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t origpa = pa;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (wrapcount < 2) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!pa_is_valid(mcp, pa)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Not in physinstall - advance to the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * next memory isolation blocksize
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Invalid PA\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa = roundup(pa + 1, mc_isolation_bsize);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((rv = page_retire_check(pa, NULL)) != 0 &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv != EAGAIN) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (pa == origpa) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Page has no error. Auto restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* found a subsequent good page */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Skip to the next page
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa = roundup(pa + 1, PAGESIZE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Skipping bad page to %lx\n", pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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("Wrap around\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pa = mcp->mc_start_address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy wrapcount++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (wrapcount > 1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Failed to find a good page. Just restart\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("restart at pa = %lx\n", pa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_RESTART_ADD(mcp, bank), MAC_RESTART_PA(pa));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_PTRL_START_ADD(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 *
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 Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic uint32_t
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydo_rewrite(mc_opl_t *mcp, int bank, uint32_t dimm_addr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t cntl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int count = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* first wait to make sure PTRL_STATUS is 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (count++ < mc_max_rewrite_loop) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(cntl & MAC_CNTL_PTRL_STATUS))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy drv_usecwait(mc_rewrite_delay);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (count >= mc_max_rewrite_loop)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto bad;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy count = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_REW_REQ(mcp, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy do {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (count++ >= mc_max_rewrite_loop) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy goto bad;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy drv_usecwait(mc_rewrite_delay);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } while (!(cntl & MAC_CNTL_REW_END));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (cntl);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedybad:
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 mcp->mc_board_num, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = MAC_CNTL_REW_END;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CMD(mcp, bank, MAC_CNTL_PTRL_RESET);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (cntl);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_process_scf_log(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int count;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int n = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy scf_log_t *p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 (n < mc_max_errlog_processed)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(bank == p->sl_bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy count = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while ((LD_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy & MAC_STATIC_ERR_VLD)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (count++ >= (mc_max_scf_loop)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy drv_usecwait(mc_scf_delay);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (count < mc_max_scf_loop) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_STATIC_ERR_LOG(mcp, p->sl_bank),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_err_log);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_err_add|MAC_STATIC_ERR_VLD);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_retry[bank] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
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 return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((++mc_pce_dropped & 0xff) == 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "Cannot report Permanent CE to SCF\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy n++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_log[bank] = p->sl_next;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_total[bank]--;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(mcp->mc_scf_total[bank] >= 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(p, sizeof (scf_log_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_queue_scf_log(mc_opl_t *mcp, mc_flt_stat_t *flt_stat, int bank)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy scf_log_t *p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_scf_total[bank] >= mc_max_scf_logs) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((++mc_pce_dropped & 0xff) == 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Too many Permanent CE requests.\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p = kmem_zalloc(sizeof (scf_log_t), KM_SLEEP);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_next = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_err_add = flt_stat->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_err_log = flt_stat->mf_err_log;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy p->sl_bank = bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_scf_log[bank] == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_log_tail[bank] = mcp->mc_scf_log[bank] = p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_log_tail[bank]->sl_next = p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_log_tail[bank] = p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_total[bank]++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 * error.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - If UE is detected due to rewrite operation, it should be treated
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * as UE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/* ARGSUSED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_scrub_ce(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat, int ptrl_error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t cntl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_PERMANENT_CE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
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 /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * If the error becomes UE or CMPE
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * we return to the caller immediately.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (cntl & MAC_CNTL_REW_UE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ptrl_error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl |= MAC_CNTL_PTRL_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl |= MAC_CNTL_MI_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (cntl & MAC_CNTL_REW_CMPE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ptrl_error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl |= MAC_CNTL_PTRL_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl |= MAC_CNTL_MI_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(cntl & MAC_CNTL_REW_CE)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_INTERMITTENT_CE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 mc_queue_scf_log(mcp, flt_stat, bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define IS_CMPE(cntl, f) ((cntl) & ((f) ? MAC_CNTL_PTRL_CMPE :\
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_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 MAC_CNTL_MI_ERRS)))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren KennedyIS_CE_ONLY(uint32_t cntl, int ptrl_error)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ptrl_error) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return ((cntl & MAC_CNTL_PTRL_ERRS) == MAC_CNTL_PTRL_CE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return ((cntl & MAC_CNTL_MI_ERRS) == MAC_CNTL_MI_CE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyvoid
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_speedup_period[ebank] > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy value |= mc_max_speed;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy value |= mcp->mc_speed;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_PTRL_CNTL(mcp, bank), value);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_read_ptrl_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_PTRL_ERRS;
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_bank = bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_read_mi_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t status, old_status;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERRS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy old_status = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* we keep reading until the status is stable */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while (old_status != status) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy old_status = status;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_err_add =
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy LD_MAC_REG(MAC_MI_ERR_ADD(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_err_log =
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy LD_MAC_REG(MAC_MI_ERR_LOG(mcp, bank));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERRS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (status == old_status) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_cntl = status;
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_bank = bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Error philosophy for mirror mode:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-UE Report MUE. No rewrite.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-* UE-(CE/OK). Rewrite to scrub UE. Report SUE.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
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 *
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * - UE-* UE-(CE/OK)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Rewrite to clear UE. Report SUE for the bank.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
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 Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_process_error_mir(mc_opl_t *mcp, mc_aflt_t *mc_aflt, mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ptrl_error = mc_aflt->mflt_is_ptrl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ptrl_error) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy & MAC_CNTL_PTRL_ERRS) == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy & MAC_CNTL_MI_ERRS) == 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
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_LOG("CE detected on bank %d\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_flt_maddr.ma_bank);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_scrub_ce(mcp, flt_stat[i].mf_flt_maddr.ma_bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy &flt_stat[i], ptrl_error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* The above scrubbing can turn CE into UE or CMPE */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat[0].mf_err_add == flt_stat[1].mf_err_add) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 flt_stat[0].mf_type = FLT_TYPE_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[1].mf_type = FLT_TYPE_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("cmpe error detected\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = &flt_stat[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[1] = &flt_stat[1];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat[0].mf_cntl, ptrl_error) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy IS_UE(flt_stat[1].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Both side are UE's */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(&flt_stat[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(&flt_stat[1]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("MUE detected\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[0].mf_type = FLT_TYPE_MUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[1].mf_type = FLT_TYPE_MUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_MUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = &flt_stat[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[1] = &flt_stat[1];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* rewrite can clear the one side UE error */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_OK(flt_stat[i^1].mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) do_rewrite(mcp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_flt_maddr.ma_bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_flt_maddr.ma_dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_type = FLT_TYPE_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(&flt_stat[i]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_SUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = &flt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_MCE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Once we hit a UE/CE or UE/OK case, done */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * addresses are different. That means errors
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * on the 2 banks are not related at all.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
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 flt_stat[i].mf_type = FLT_TYPE_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("cmpe error detected\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = &flt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* no more report on this bank */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_cntl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* rewrite can clear the one side UE error */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 (void) do_rewrite(mcp,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_flt_maddr.ma_bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_flt_maddr.ma_dimm_addr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_type = FLT_TYPE_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(&flt_stat[i]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_SUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = &flt_stat[i];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_MCE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (rv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_error_handler_mir(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt_t mc_aflt;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_flt_stat_t flt_stat[2], mi_flt_stat[2];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int mi_valid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(rsaddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&mc_aflt, sizeof (mc_aflt_t));
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_mcp = mcp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_id = gethrtime();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Now read all the registers into flt_stat */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("ptrl registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_cntl,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_err_add,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat[i].mf_err_log);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* MI registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_read_mi_reg(mcp, bank, &mi_flt_stat[i]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("MI registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat[i].mf_cntl,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat[i].mf_err_add,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat[i].mf_err_log);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bank = bank^1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* clear errors once we read all the registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, bank ^ 1, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Process MI errors first */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 mi_flt_stat[0].mf_cntl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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_flt_stat[1].mf_cntl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_is_ptrl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_valid = mc_process_error_mir(mcp, &mc_aflt, &mi_flt_stat[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((((flt_stat[0].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_PTRL_ERR_SHIFT) ==
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat[0].mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERR_SHIFT)) &&
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 MAC_CNTL_PTRL_ERR_SHIFT) ==
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat[1].mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERR_SHIFT)) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat[1].mf_err_add == mi_flt_stat[1].mf_err_add)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#ifdef DEBUG
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("discarding PTRL error because "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "it is the same as MI\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#endif
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_valid = mi_valid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
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 flt_stat[0].mf_cntl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 flt_stat[1].mf_cntl = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_is_ptrl = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_valid = mc_process_error_mir(mcp, &mc_aflt, &flt_stat[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_process_error(mc_opl_t *mcp, int bank, mc_aflt_t *mc_aflt,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_flt_stat_t *flt_stat)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ptrl_error = mc_aflt->mflt_is_ptrl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int rv = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_UE(flt_stat->mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("UE deteceted\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type = FLT_TYPE_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (IS_CE(flt_stat->mf_cntl, ptrl_error)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("CE deteceted\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_SET_ERRLOG_INFO(flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Error type can change after scrubing */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_scrub_ce(mcp, bank, flt_stat, ptrl_error);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_CE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_MCE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (flt_stat->mf_type == FLT_TYPE_UE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class = MC_OPL_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_pr = PR_UE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rv = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc_process_error: fault type %x erpt %s\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat->mf_type,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_erpt_class);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_aflt->mflt_erpt_class) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_stat[0] = flt_stat;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt->mflt_nflts = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_err_drain(mc_aflt);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (rv);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_error_handler(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt_t mc_aflt;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_flt_stat_t flt_stat, mi_flt_stat;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int mi_valid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&mc_aflt, sizeof (mc_aflt_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&flt_stat, sizeof (mc_flt_stat_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(&mi_flt_stat, sizeof (mc_flt_stat_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_mcp = mcp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_id = gethrtime();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* patrol registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_read_ptrl_reg(mcp, bank, &flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ASSERT(rsaddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_restartaddr = flt_stat.mf_flt_maddr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("ptrl registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat.mf_cntl,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat.mf_err_add,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flt_stat.mf_err_log);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* MI registers */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_read_mi_reg(mcp, bank, &mi_flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("MI registers cntl %x add %x log %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat.mf_cntl,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat.mf_err_add,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mi_flt_stat.mf_err_log);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_is_ptrl = 0;
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 }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_PTRL_ERR_SHIFT) ==
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) >>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERR_SHIFT)) &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (flt_stat.mf_err_add == mi_flt_stat.mf_err_add)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#ifdef DEBUG
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("discarding PTRL error because "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "it is the same as MI\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#endif
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr->mi_valid = mi_valid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_aflt.mflt_is_ptrl = 1;
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 &mc_aflt, &flt_stat);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 * timeout ->
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_check_errors_func(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_rsaddr_info_t rsaddr_info;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i, error_count = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t stat, cntl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int running;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int wrapped;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ebk;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * scan errors.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_status & MC_MEMORYLESS)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 stat = ldphysio(MAC_PTRL_STAT(mcp, i));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cntl = ldphysio(MAC_PTRL_CNTL(mcp, i));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy running = cntl & MAC_CNTL_PTRL_START;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy wrapped = cntl & MAC_CNTL_PTRL_ADD_MAX;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Compute the effective bank idx */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ebk = (IS_MIRROR(mcp, i)) ? MIRROR_IDX(i) : i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mc_debug_show_all || stat) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("/LSB%d/B%d stat %x cntl %x\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, i,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy stat, cntl);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Update stats and reset flag if the HW patrol
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * wrapped around in its scan.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (wrapped) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_MAX(mcp, i);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_period[ebk]++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_MIRROR(mcp, i))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mirror mc period %ld on "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "/LSB%d/B%d\n", mcp->mc_period[ebk],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, i);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("mc period %ld on "
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "/LSB%d/B%d\n", mcp->mc_period[ebk],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, i);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (running) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_speedup_period[ebk] > 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (wrapped &&
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (--mcp->mc_speedup_period[ebk] == 0)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Clearing MI errors\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, i,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_MIRROR(mcp, i)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Clearing Mirror MI errs\n");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CLEAR_ERRS(mcp, i^1,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CNTL_MI_ERRS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (stat & MAC_STAT_MI_ERRS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 * to stop.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speedup_period[ebk] = 2;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_CMD(mcp, i, 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (stat & (MAC_STAT_PTRL_ERRS |
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MAC_STAT_MI_ERRS)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * HW Patrol has stopped and we found errors.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Proceed to collect and report error info.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speedup_period[ebk] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr_info.mi_valid = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr_info.mi_injectrestart = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (IS_MIRROR(mcp, i)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_error_handler_mir(mcp, i, &rsaddr_info);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_error_handler(mcp, i, &rsaddr_info);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy error_count++;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy restart_patrol(mcp, i, &rsaddr_info);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!IS_MIRROR(mcp, i) || (i & 0x1))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy restart_patrol(mcp, i, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (error_count > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_last_error += error_count;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_last_error = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 *
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_polling(void)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i, scan_error;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_opl_t *mcp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy scan_error = 1;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < OPL_MAX_BOARDS; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mcmutex);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mcp = mc_instances[i]) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcmutex);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy continue;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcmutex);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(mcp->mc_status & MC_POLL_RUNNING)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy continue;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (scan_error && mcp->mc_tick_left <= 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_check_errors_func((void *)mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_tick_left = OPL_MAX_BOARDS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy scan_error = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_tick_left--;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_process_scf_log(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyget_ptrl_start_address(mc_opl_t *mcp, int bank, mc_addr_t *maddr)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_bd = mcp->mc_board_num;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_bank = bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy maddr->ma_dimm_addr = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedytypedef struct mc_mem_range {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t addr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy} mc_mem_range_t;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyget_base_address(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_mem_range_t *mem_range;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int len;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_start_address = mem_range->addr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_size = mem_range->size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(mem_range, len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystruct mc_addr_spec {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t phys_hi;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t phys_lo;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#define REGS_PA(m, i) ((((uint64_t)m[i].phys_hi)<<32) | m[i].phys_lo)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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};
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
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 Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic int
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((pa < mcp->mc_start_address) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (mcp->mc_start_address + mcp->mc_size <= pa))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_memlist_delete(struct memlist *mlist)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct memlist *ml;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (ml = mlist; ml; ml = mlist) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlist = ml->next;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(ml, sizeof (struct memlist));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct memlist *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_memlist_dup(struct memlist *mlist)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct memlist *hl = NULL, *tl, **mlp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlp = &hl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy tl = *mlp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (; mlist; mlist = mlist->next) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *mlp = kmem_alloc(sizeof (struct memlist), KM_SLEEP);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (*mlp)->address = mlist->address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (*mlp)->size = mlist->size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (*mlp)->prev = tl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy tl = *mlp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlp = &((*mlp)->next);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *mlp = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (hl);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic struct memlist *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t end;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct memlist *ml, *tl, *nlp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy end = base + len;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((end <= mlist->address) || (base == end))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (mlist);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t mend;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nlp = ml->next;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (end <= ml->address)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mend = ml->address + ml->size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (base < mend) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (base <= ml->address) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml->address = end;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (end >= mend)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml->size = 0ull;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml->size = mend - ml->address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml->size = base - ml->address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (end < mend) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct memlist *nl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * splitting an memlist entry.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nl = kmem_alloc(sizeof (struct memlist),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy KM_SLEEP);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nl->address = end;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nl->size = mend - nl->address;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((nl->next = nlp) != NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nlp->prev = nl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nl->prev = ml;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml->next = nl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nlp = nl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ml->size == 0ull) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (ml == mlist) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((mlist = nlp) != NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nlp->prev = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(ml, sizeof (struct memlist));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml = nlp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((tl->next = nlp) != NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nlp->prev = tl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(ml, sizeof (struct memlist));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ml = tl;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (mlist);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_get_mlist(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct memlist *mlist;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy memlist_read_lock();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlist = mc_memlist_dup(phys_install);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy memlist_read_unlock();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlist = mc_memlist_del_span(mlist, 0ull, mcp->mc_start_address);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t startpa, endpa;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy startpa = mcp->mc_start_address + mcp->mc_size;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy endpa = ptob(physmax + 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (endpa > startpa) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mlist = mc_memlist_del_span(mlist,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy startpa, endpa - startpa);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mlist) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mlist = mlist;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_board_add(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct mc_addr_spec *macaddr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cs_status_t *cs_status;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int len, len1, i, bk, cc;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_rsaddr_info_t rsaddr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t mirr;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int nbanks = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t nbytes = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num = (int)ddi_getprop(DDI_DEV_T_ANY, mcp->mc_dip,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DDI_PROP_DONTPASS, "board#", -1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_board_num == -1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Get start address in this CAB. It can be gotten from
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * "sb-mem-ranges" property.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (get_base_address(mcp) == DDI_FAILURE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* get mac-pa trans tables */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < MC_TT_CS; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy len = MC_TT_ENTRIES;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cc = ddi_getlongprop_buf(DDI_DEV_T_ANY, mcp->mc_dip,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DDI_PROP_DONTPASS, mc_tbl_name[i],
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (caddr_t)mcp->mc_trans_table[i], &len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (cc != DDI_SUCCESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bzero(mcp->mc_trans_table[i], MC_TT_ENTRIES);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mlist = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_get_mlist(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 "mc-addr", (caddr_t)&macaddr, &len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (cc != DDI_SUCCESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Cannot get mc-addr. err=%d\n", cc);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy "cs-status", (caddr_t)&cs_status, &len1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (cc != DDI_SUCCESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (len > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(macaddr, len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Cannot get cs-status. err=%d\n", cc);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
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
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_phys_board_num < 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (len > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(macaddr, len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy cmn_err(CE_WARN, "Unable to obtain the physical board number");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_FAILURE);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_init(&mcp->mc_lock, NULL, MUTEX_DRIVER, NULL);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 ((uint64_t)cs_status[i].cs_avail_low);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (len1 > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(cs_status, len1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nbanks = len / sizeof (struct mc_addr_spec);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (nbanks > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy nbytes /= nbanks;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* No need to free macaddr because len must be 0 */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_status |= MC_MEMORYLESS;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_retry[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_period[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speedup_period[i] = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
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 *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * B * T * 10^(-6) = P
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * ---------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 64
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * T = P * 64 * 10^6
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * B
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * = P * 64 * 10^6
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * -------------
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * B
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The timing bits are set in PTRL_CNTL[28:26] where
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 0 - 1 m.s
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 1 - 512 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 10 - 256 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 11 - 128 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 100 - 64 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 101 - 32 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 110 - 0 u.s.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 111 - reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * a[0] = 110, a[1] = 101, ... a[6] = 0
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * cs-status property is int x 7
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 0 - cs#
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 1 - cs-status
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 2 - cs-avail.hi
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 3 - cs-avail.lo
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 4 - dimm-capa.hi
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 5 - dimm-capa.lo
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 6 - #of dimms
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (nbytes > 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint64_t ms;
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 for (i = 0; i < MC_MAX_SPEEDS - 1; i++) {
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 break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_speed = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy for (i = 0; i < len / sizeof (struct mc_addr_spec); i++) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct mc_bank *bankp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy uint32_t reg;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * setup bank
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bk = macaddr[i].bank;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp = &(mcp->mc_bank[bk]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_status = BANK_INSTALLED;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_reg_base = REGS_PA(macaddr, i);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bk));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_ptrl_cntl = (reg & MAC_CNTL_PTRL_PRESERVE_BITS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * check if mirror mode
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mirr = LD_MAC_REG(MAC_MIRR(mcp, bk));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mirr & MAC_MIRR_MIRROR_MODE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Mirror -> /LSB%d/B%d\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, bk);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_status |= BANK_MIRROR_MODE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The following bit is only used for
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * error injection. We should clear it
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mirr & MAC_MIRR_BANK_EXCLUSIVE)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy ST_MAC_REG(MAC_MIRR(mcp, bk),
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy 0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * restart if not mirror mode or the other bank
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * of the mirror is not running
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (!(mirr & MAC_MIRR_MIRROR_MODE) ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy !(mcp->mc_bank[bk^1].mcb_status &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy BANK_PTRL_RUNNING)) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Starting up /LSB%d/B%d\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, bk);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy get_ptrl_start_address(mcp, bk, &rsaddr.mi_restartaddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr.mi_valid = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rsaddr.mi_injectrestart = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy restart_patrol(mcp, bk, &rsaddr);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy MC_LOG("Not starting up /LSB%d/B%d\n",
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_board_num, bk);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy bankp->mcb_status |= BANK_PTRL_RUNNING;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (len > 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(macaddr, len);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_dimm_list = mc_get_dimm_list(mcp);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * set interval in HZ.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_last_error = 0;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* restart memory patrol checking */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_status |= MC_POLL_RUNNING;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_board_del(mc_opl_t *mcp)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int i;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy scf_log_t *p;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * cleanup mac state
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_status & MC_MEMORYLESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_destroy(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
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 }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* stop memory patrol checking */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_status &= ~MC_POLL_RUNNING;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
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 mcp->mc_scf_log[i] = p->sl_next;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_scf_total[i]--;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy kmem_free(p, sizeof (scf_log_t));
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mlist)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_memlist_delete(mcp->mlist);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_dimm_list)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mc_free_dimm_list(mcp->mc_dimm_list);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_destroy(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymc_suspend(mc_opl_t *mcp, uint32_t flag)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* stop memory patrol checking */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_enter(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (mcp->mc_status & MC_MEMORYLESS) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (DDI_SUCCESS);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_status &= ~MC_POLL_RUNNING;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mcp->mc_status |= flag;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mutex_exit(&mcp->mc_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (DDI_SUCCESS);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy}
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy/* caller must clear the SUSPEND bits or this will do nothing */
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedyint
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedymc_resume(mc_opl_t *mcp, uint32_t flag)
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy{
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy int i;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy uint64_t basepa;
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_enter(&mcp->mc_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy if (mcp->mc_status & MC_MEMORYLESS) {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy mutex_exit(&mcp->mc_lock);
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy return (DDI_SUCCESS);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy basepa = mcp->mc_start_address;
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (get_base_address(mcp) == DDI_FAILURE) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mutex_exit(&mcp->mc_lock);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy return (DDI_FAILURE);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (basepa != mcp->mc_start_address) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (mcp->mlist)
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mc_memlist_delete(mcp->mlist);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mcp->mlist = NULL;
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mc_get_mlist(mcp);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mcp->mc_status &= ~flag;
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mutex_exit(&mcp->mc_lock);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy return (DDI_SUCCESS);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (!(mcp->mc_status & MC_POLL_RUNNING)) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy /* restart memory patrol checking */
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mcp->mc_status |= MC_POLL_RUNNING;
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy for (i = 0; i < BANKNUM_PER_SB; i++) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy restart_patrol(mcp, i, NULL);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy }
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy mutex_exit(&mcp->mc_lock);
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy
52244c0958bdf281ca42932b449f644b4decfdc2John Wren Kennedy return (DDI_SUCCESS);
}
static mc_opl_t *
mc_pa_to_mcp(uint64_t pa)
{
mc_opl_t *mcp;
int i;
ASSERT(MUTEX_HELD(&mcmutex));
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
/* if mac patrol is suspended, we cannot rely on it */
if (!(mcp->mc_status & MC_POLL_RUNNING) ||
(mcp->mc_status & MC_SOFT_SUSPENDED))
continue;
if (mc_rangecheck_pa(mcp, pa)) {
return (mcp);
}
}
return (NULL);
}
/*
* Get Physical Board number from Logical one.
*/
static int
mc_opl_get_physical_board(int sb)
{
if (&opl_get_physical_board) {
return (opl_get_physical_board(sb));
}
cmn_err(CE_NOTE, "!opl_get_physical_board() not loaded\n");
return (-1);
}
/* ARGSUSED */
int
mc_get_mem_unum(int synd_code, uint64_t flt_addr, char *buf, int buflen,
int *lenp)
{
int i;
int j;
int sb;
int bank;
int cs;
mc_opl_t *mcp;
char memb_num;
mutex_enter(&mcmutex);
if (((mcp = mc_pa_to_mcp(flt_addr)) == NULL) ||
(!pa_is_valid(mcp, flt_addr))) {
mutex_exit(&mcmutex);
if (snprintf(buf, buflen, "UNKNOWN") >= buflen) {
return (ENOSPC);
} else {
if (lenp)
*lenp = strlen(buf);
}
return (0);
}
bank = pa_to_bank(mcp, flt_addr - mcp->mc_start_address);
sb = mcp->mc_phys_board_num;
cs = pa_to_cs(mcp, flt_addr - mcp->mc_start_address);
if (sb == -1) {
mutex_exit(&mcmutex);
return (ENXIO);
}
if (plat_model == MODEL_DC) {
i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
j = (cs == 0) ? i : i + 2;
snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
model_names[plat_model].unit_name, sb,
mc_dc_dimm_unum_table[j],
mc_dc_dimm_unum_table[j + 1]);
} else {
i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
j = (cs == 0) ? i : i + 2;
memb_num = mc_ff_dimm_unum_table[i][0];
snprintf(buf, buflen, "/%s/%s%c/MEM%s MEM%s",
model_names[plat_model].unit_name,
model_names[plat_model].mem_name, memb_num,
&mc_ff_dimm_unum_table[j][1],
&mc_ff_dimm_unum_table[j + 1][1]);
}
if (lenp) {
*lenp = strlen(buf);
}
mutex_exit(&mcmutex);
return (0);
}
int
opl_mc_suspend(void)
{
mc_opl_t *mcp;
int i;
mutex_enter(&mcmutex);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
mc_suspend(mcp, MC_SOFT_SUSPENDED);
}
mutex_exit(&mcmutex);
return (0);
}
int
opl_mc_resume(void)
{
mc_opl_t *mcp;
int i;
mutex_enter(&mcmutex);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
mc_resume(mcp, MC_SOFT_SUSPENDED);
}
mutex_exit(&mcmutex);
return (0);
}
static void
insert_mcp(mc_opl_t *mcp)
{
mutex_enter(&mcmutex);
if (mc_instances[mcp->mc_board_num] != NULL) {
MC_LOG("mc-opl instance for board# %d already exists\n",
mcp->mc_board_num);
}
mc_instances[mcp->mc_board_num] = mcp;
mutex_exit(&mcmutex);
}
static void
delete_mcp(mc_opl_t *mcp)
{
mutex_enter(&mcmutex);
mc_instances[mcp->mc_board_num] = 0;
mutex_exit(&mcmutex);
}
/* Error injection interface */
static void
mc_lock_va(uint64_t pa, caddr_t new_va)
{
tte_t tte;
vtag_flushpage(new_va, (uint64_t)ksfmmup);
sfmmu_memtte(&tte, pa >> PAGESHIFT,
PROC_DATA|HAT_NOSYNC, TTE8K);
tte.tte_intlo |= TTE_LCK_INT;
sfmmu_dtlb_ld_kva(new_va, &tte);
}
static void
mc_unlock_va(caddr_t va)
{
vtag_flushpage(va, (uint64_t)ksfmmup);
}
/* ARGSUSED */
int
mc_inject_error(int error_type, uint64_t pa, uint32_t flags)
{
mc_opl_t *mcp;
int bank;
uint32_t dimm_addr;
uint32_t cntl;
mc_rsaddr_info_t rsaddr;
uint32_t data, stat;
int both_sides = 0;
uint64_t pa0;
int extra_injection_needed = 0;
extern void cpu_flush_ecache(void);
MC_LOG("HW mc_inject_error(%x, %lx, %x)\n", error_type, pa, flags);
mutex_enter(&mcmutex);
if ((mcp = mc_pa_to_mcp(pa)) == NULL) {
mutex_exit(&mcmutex);
MC_LOG("mc_inject_error: invalid pa\n");
return (ENOTSUP);
}
mutex_enter(&mcp->mc_lock);
mutex_exit(&mcmutex);
if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
mutex_exit(&mcp->mc_lock);
MC_LOG("mc-opl has been suspended. No error injection.\n");
return (EBUSY);
}
/* convert pa to offset within the board */
MC_LOG("pa %lx, offset %lx\n", pa, pa - mcp->mc_start_address);
if (!pa_is_valid(mcp, pa)) {
mutex_exit(&mcp->mc_lock);
return (EINVAL);
}
pa0 = pa - mcp->mc_start_address;
bank = pa_to_bank(mcp, pa0);
if (flags & MC_INJECT_FLAG_OTHER)
bank = bank ^ 1;
if (MC_INJECT_MIRROR(error_type) && !IS_MIRROR(mcp, bank)) {
mutex_exit(&mcp->mc_lock);
MC_LOG("Not mirror mode\n");
return (EINVAL);
}
dimm_addr = pa_to_dimm(mcp, pa0);
MC_LOG("injecting error to /LSB%d/B%d/%x\n",
mcp->mc_board_num, bank, dimm_addr);
switch (error_type) {
case MC_INJECT_INTERMITTENT_MCE:
case MC_INJECT_PERMANENT_MCE:
case MC_INJECT_MUE:
both_sides = 1;
}
if (flags & MC_INJECT_FLAG_RESET)
ST_MAC_REG(MAC_EG_CNTL(mcp, bank), 0);
ST_MAC_REG(MAC_EG_ADD(mcp, bank), dimm_addr & MAC_EG_ADD_MASK);
if (both_sides) {
ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), 0);
ST_MAC_REG(MAC_EG_ADD(mcp, bank^1),
dimm_addr & MAC_EG_ADD_MASK);
}
switch (error_type) {
case MC_INJECT_SUE:
extra_injection_needed = 1;
/*FALLTHROUGH*/
case MC_INJECT_UE:
case MC_INJECT_MUE:
if (flags & MC_INJECT_FLAG_PATH) {
cntl = MAC_EG_ADD_FIX
|MAC_EG_FORCE_READ00|MAC_EG_FORCE_READ16
|MAC_EG_RDERR_ONCE;
} else {
cntl = MAC_EG_ADD_FIX|MAC_EG_FORCE_DERR00
|MAC_EG_FORCE_DERR16|MAC_EG_DERR_ONCE;
}
flags |= MC_INJECT_FLAG_ST;
break;
case MC_INJECT_INTERMITTENT_CE:
case MC_INJECT_INTERMITTENT_MCE:
if (flags & MC_INJECT_FLAG_PATH) {
cntl = MAC_EG_ADD_FIX
|MAC_EG_FORCE_READ00
|MAC_EG_RDERR_ONCE;
} else {
cntl = MAC_EG_ADD_FIX
|MAC_EG_FORCE_DERR16
|MAC_EG_DERR_ONCE;
}
extra_injection_needed = 1;
flags |= MC_INJECT_FLAG_ST;
break;
case MC_INJECT_PERMANENT_CE:
case MC_INJECT_PERMANENT_MCE:
if (flags & MC_INJECT_FLAG_PATH) {
cntl = MAC_EG_ADD_FIX
|MAC_EG_FORCE_READ00
|MAC_EG_RDERR_ALWAYS;
} else {
cntl = MAC_EG_ADD_FIX
|MAC_EG_FORCE_DERR16
|MAC_EG_DERR_ALWAYS;
}
flags |= MC_INJECT_FLAG_ST;
break;
case MC_INJECT_CMPE:
data = 0xabcdefab;
stphys(pa, data);
cpu_flush_ecache();
MC_LOG("CMPE: writing data %x to %lx\n", data, pa);
ST_MAC_REG(MAC_MIRR(mcp, bank), MAC_MIRR_BANK_EXCLUSIVE);
stphys(pa, data ^ 0xffffffff);
membar_sync();
cpu_flush_ecache();
ST_MAC_REG(MAC_MIRR(mcp, bank), 0);
MC_LOG("CMPE: write new data %xto %lx\n", data, pa);
cntl = 0;
break;
case MC_INJECT_NOP:
cntl = 0;
break;
default:
MC_LOG("mc_inject_error: invalid option\n");
cntl = 0;
}
if (cntl) {
ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl & MAC_EG_SETUP_MASK);
ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
if (both_sides) {
ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
MAC_EG_SETUP_MASK);
ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
}
}
/*
* For all injection cases except compare error, we
* must write to the PA to trigger the error.
*/
if (flags & MC_INJECT_FLAG_ST) {
data = 0xf0e0d0c0;
MC_LOG("Writing %x to %lx\n", data, pa);
stphys(pa, data);
cpu_flush_ecache();
}
if (flags & MC_INJECT_FLAG_LD) {
if (flags & MC_INJECT_FLAG_PREFETCH) {
/*
* Use strong prefetch operation to
* inject MI errors.
*/
page_t *pp;
extern void mc_prefetch(caddr_t);
MC_LOG("prefetch\n");
pp = page_numtopp_nolock(pa >> PAGESHIFT);
if (pp != NULL) {
caddr_t va, va1;
va = ppmapin(pp, PROT_READ|PROT_WRITE,
(caddr_t)-1);
kpreempt_disable();
mc_lock_va((uint64_t)pa, va);
va1 = va + (pa & (PAGESIZE - 1));
mc_prefetch(va1);
mc_unlock_va(va);
kpreempt_enable();
ppmapout(va);
/*
* For MI errors, we need one extra
* injection for HW patrol to stop.
*/
extra_injection_needed = 1;
} else {
cmn_err(CE_WARN, "Cannot find page structure"
" for PA %lx\n", pa);
}
} else {
MC_LOG("Reading from %lx\n", pa);
data = ldphys(pa);
MC_LOG("data = %x\n", data);
}
if (extra_injection_needed) {
/*
* These are the injection cases where the
* requested injected errors will not cause the HW
* patrol to stop. For these cases, we need to inject
* an extra 'real' PTRL error to force the
* HW patrol to stop so that we can report the
* errors injected. Note that we cannot read
* and report error status while the HW patrol
* is running.
*/
ST_MAC_REG(MAC_EG_CNTL(mcp, bank),
cntl & MAC_EG_SETUP_MASK);
ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
if (both_sides) {
ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
MAC_EG_SETUP_MASK);
ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
}
data = 0xf0e0d0c0;
MC_LOG("Writing %x to %lx\n", data, pa);
stphys(pa, data);
cpu_flush_ecache();
}
}
if (flags & MC_INJECT_FLAG_RESTART) {
MC_LOG("Restart patrol\n");
rsaddr.mi_restartaddr.ma_bd = mcp->mc_board_num;
rsaddr.mi_restartaddr.ma_bank = bank;
rsaddr.mi_restartaddr.ma_dimm_addr = dimm_addr;
rsaddr.mi_valid = 1;
rsaddr.mi_injectrestart = 1;
restart_patrol(mcp, bank, &rsaddr);
}
if (flags & MC_INJECT_FLAG_POLL) {
int running;
int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
MC_LOG("Poll patrol error\n");
stat = LD_MAC_REG(MAC_PTRL_STAT(mcp, bank));
cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
running = cntl & MAC_CNTL_PTRL_START;
if (!running &&
(stat & (MAC_STAT_PTRL_ERRS|MAC_STAT_MI_ERRS))) {
/*
* HW patrol stopped and we have errors to
* report. Do it.
*/
mcp->mc_speedup_period[ebank] = 0;
rsaddr.mi_valid = 0;
rsaddr.mi_injectrestart = 0;
if (IS_MIRROR(mcp, bank)) {
mc_error_handler_mir(mcp, bank, &rsaddr);
} else {
mc_error_handler(mcp, bank, &rsaddr);
}
restart_patrol(mcp, bank, &rsaddr);
} else {
/*
* We are expecting to report injected
* errors but the HW patrol is still running.
* Speed up the scanning
*/
mcp->mc_speedup_period[ebank] = 2;
MAC_CMD(mcp, bank, 0);
restart_patrol(mcp, bank, NULL);
}
}
mutex_exit(&mcp->mc_lock);
return (0);
}
void
mc_stphysio(uint64_t pa, uint32_t data)
{
MC_LOG("0x%x -> pa(%lx)\n", data, pa);
stphysio(pa, data);
/* force the above write to be processed by mac patrol */
data = ldphysio(pa);
MC_LOG("pa(%lx) = 0x%x\n", pa, data);
}
uint32_t
mc_ldphysio(uint64_t pa)
{
uint32_t rv;
rv = ldphysio(pa);
MC_LOG("pa(%lx) = 0x%x\n", pa, rv);
return (rv);
}
#define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
/*
* parse_unum_memory -- extract the board number and the DIMM name from
* the unum.
*
* Return 0 for success and non-zero for a failure.
*/
int
parse_unum_memory(char *unum, int *board, char *dname)
{
char *c;
char x, y, z;
if ((c = strstr(unum, "CMU")) != NULL) {
/* DC Model */
c += 3;
*board = (uint8_t)stoi(&c);
if ((c = strstr(c, "MEM")) == NULL) {
return (1);
}
c += 3;
if (strlen(c) < 3) {
return (2);
}
if ((!isdigit(c[0])) || (!(isdigit(c[1]))) ||
((c[2] != 'A') && (c[2] != 'B'))) {
return (3);
}
x = c[0];
y = c[1];
z = c[2];
} else if ((c = strstr(unum, "MBU_")) != NULL) {
/* FF1/FF2 Model */
c += 4;
if ((c[0] != 'A') && (c[0] != 'B')) {
return (4);
}
if ((c = strstr(c, "MEMB")) == NULL) {
return (5);
}
c += 4;
x = c[0];
*board = ((uint8_t)stoi(&c)) / 4;
if ((c = strstr(c, "MEM")) == NULL) {
return (6);
}
c += 3;
if (strlen(c) < 2) {
return (7);
}
if ((!isdigit(c[0])) || ((c[1] != 'A') && (c[1] != 'B'))) {
return (8);
}
y = c[0];
z = c[1];
} else {
return (9);
}
if (*board < 0) {
return (10);
}
dname[0] = x;
dname[1] = y;
dname[2] = z;
dname[3] = '\0';
return (0);
}
/*
* mc_get_mem_sid_dimm -- Get the serial-ID for a given board and
* the DIMM name.
*/
int
mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
int buflen, int *lenp)
{
int ret = ENODEV;
mc_dimm_info_t *d = NULL;
if ((d = mcp->mc_dimm_list) == NULL)
return (ENOTSUP);
for (; d != NULL; d = d->md_next) {
if (strcmp(d->md_dimmname, dname) == 0) {
break;
}
}
if (d != NULL) {
*lenp = strlen(d->md_serial) + strlen(d->md_partnum);
if (buflen <= *lenp) {
cmn_err(CE_WARN, "mc_get_mem_sid_dimm: "
"buflen is smaller than %d\n", *lenp);
ret = ENOSPC;
} else {
snprintf(buf, buflen, "%s:%s",
d->md_serial, d->md_partnum);
ret = 0;
}
}
MC_LOG("mc_get_mem_sid_dimm: Ret=%d Name=%s Serial-ID=%s\n",
ret, dname, (ret == 0) ? buf : "");
return (ret);
}
int
mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int sb,
int bank, uint32_t mf_type, uint32_t d_slot)
{
int lenp = buflen;
int id;
int ret;
char *dimmnm;
if (mf_type == FLT_TYPE_PERMANENT_CE) {
if (plat_model == MODEL_DC) {
id = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
dimmnm = mc_dc_dimm_unum_table[id];
} else {
id = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
dimmnm = mc_ff_dimm_unum_table[id];
}
if ((ret = mc_get_mem_sid_dimm(mcp, dimmnm, buf, buflen,
&lenp)) != 0) {
return (ret);
}
} else {
return (1);
}
return (0);
}
/*
* mc_get_mem_sid -- get the DIMM serial-ID corresponding to the unum.
*/
int
mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp)
{
int i;
int ret = ENODEV;
int board;
char dname[MCOPL_MAX_DIMMNAME + 1];
mc_opl_t *mcp;
MC_LOG("mc_get_mem_sid: unum=%s buflen=%d\n", unum, buflen);
if ((ret = parse_unum_memory(unum, &board, dname)) != 0) {
MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
unum, ret);
return (EINVAL);
}
if (board < 0) {
MC_LOG("mc_get_mem_sid: Invalid board=%d dimm=%s\n",
board, dname);
return (EINVAL);
}
mutex_enter(&mcmutex);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
mutex_enter(&mcp->mc_lock);
if (mcp->mc_phys_board_num != board) {
mutex_exit(&mcp->mc_lock);
continue;
}
ret = mc_get_mem_sid_dimm(mcp, dname, buf, buflen, lenp);
if (ret == 0) {
mutex_exit(&mcp->mc_lock);
break;
}
mutex_exit(&mcp->mc_lock);
}
mutex_exit(&mcmutex);
return (ret);
}
/*
* mc_get_mem_offset -- get the offset in a DIMM for a given physical address.
*/
int
mc_get_mem_offset(uint64_t paddr, uint64_t *offp)
{
int i;
int ret = ENODEV;
mc_addr_t maddr;
mc_opl_t *mcp;
mutex_enter(&mcmutex);
for (i = 0; ((i < OPL_MAX_BOARDS) && (ret != 0)); i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
mutex_enter(&mcp->mc_lock);
if (!pa_is_valid(mcp, paddr)) {
mutex_exit(&mcp->mc_lock);
continue;
}
if (pa_to_maddr(mcp, paddr, &maddr) == 0) {
*offp = maddr.ma_dimm_addr;
ret = 0;
}
mutex_exit(&mcp->mc_lock);
}
mutex_exit(&mcmutex);
MC_LOG("mc_get_mem_offset: Ret=%d paddr=0x%lx offset=0x%lx\n",
ret, paddr, *offp);
return (ret);
}
/*
* dname_to_bankslot - Get the bank and slot number from the DIMM name.
*/
int
dname_to_bankslot(char *dname, int *bank, int *slot)
{
int i;
int tsz;
char **tbl;
if (plat_model == MODEL_DC) { /* DC */
tbl = mc_dc_dimm_unum_table;
tsz = OPL_MAX_DIMMS;
} else {
tbl = mc_ff_dimm_unum_table;
tsz = 2 * OPL_MAX_DIMMS;
}
for (i = 0; i < tsz; i++) {
if (strcmp(dname, tbl[i]) == 0) {
break;
}
}
if (i == tsz) {
return (1);
}
*bank = INDEX_TO_BANK(i);
*slot = INDEX_TO_SLOT(i);
return (0);
}
/*
* mc_get_mem_addr -- get the physical address of a DIMM corresponding
* to the unum and sid.
*/
int
mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr)
{
int board;
int bank;
int slot;
int i;
int ret = ENODEV;
char dname[MCOPL_MAX_DIMMNAME + 1];
mc_addr_t maddr;
mc_opl_t *mcp;
MC_LOG("mc_get_mem_addr: unum=%s sid=%s offset=0x%lx\n",
unum, sid, offset);
if (parse_unum_memory(unum, &board, dname) != 0) {
MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
unum, ret);
return (EINVAL);
}
if (board < 0) {
MC_LOG("mc_get_mem_addr: Invalid board=%d dimm=%s\n",
board, dname);
return (EINVAL);
}
mutex_enter(&mcmutex);
for (i = 0; i < OPL_MAX_BOARDS; i++) {
if ((mcp = mc_instances[i]) == NULL)
continue;
mutex_enter(&mcp->mc_lock);
if (mcp->mc_phys_board_num != board) {
mutex_exit(&mcp->mc_lock);
continue;
}
ret = dname_to_bankslot(dname, &bank, &slot);
MC_LOG("mc_get_mem_addr: bank=%d slot=%d\n", bank, slot);
if (ret != 0) {
MC_LOG("mc_get_mem_addr: dname_to_bankslot failed\n");
ret = ENODEV;
} else {
maddr.ma_bd = mcp->mc_board_num;
maddr.ma_bank = bank;
maddr.ma_dimm_addr = offset;
ret = mcaddr_to_pa(mcp, &maddr, paddr);
if (ret != 0) {
MC_LOG("mc_get_mem_addr: "
"mcaddr_to_pa failed\n");
ret = ENODEV;
}
mutex_exit(&mcp->mc_lock);
break;
}
mutex_exit(&mcp->mc_lock);
}
mutex_exit(&mcmutex);
MC_LOG("mc_get_mem_addr: Ret=%d, Paddr=0x%lx\n", ret, *paddr);
return (ret);
}
static void
mc_free_dimm_list(mc_dimm_info_t *d)
{
mc_dimm_info_t *next;
while (d != NULL) {
next = d->md_next;
kmem_free(d, sizeof (mc_dimm_info_t));
d = next;
}
}
/*
* mc_get_dimm_list -- get the list of dimms with serial-id info
* from the SP.
*/
mc_dimm_info_t *
mc_get_dimm_list(mc_opl_t *mcp)
{
uint32_t bufsz;
uint32_t maxbufsz;
int ret;
int sexp;
board_dimm_info_t *bd_dimmp;
mc_dimm_info_t *dimm_list = NULL;
maxbufsz = bufsz = sizeof (board_dimm_info_t) +
((MCOPL_MAX_DIMMNAME + MCOPL_MAX_SERIAL +
MCOPL_MAX_PARTNUM) * OPL_MAX_DIMMS);
bd_dimmp = (board_dimm_info_t *)kmem_alloc(bufsz, KM_SLEEP);
ret = scf_get_dimminfo(mcp->mc_board_num, (void *)bd_dimmp, &bufsz);
MC_LOG("mc_get_dimm_list: scf_service_getinfo returned=%d\n", ret);
if (ret == 0) {
sexp = sizeof (board_dimm_info_t) +
((bd_dimmp->bd_dnamesz + bd_dimmp->bd_serialsz +
bd_dimmp->bd_partnumsz) * bd_dimmp->bd_numdimms);
if ((bd_dimmp->bd_version == OPL_DIMM_INFO_VERSION) &&
(bd_dimmp->bd_dnamesz <= MCOPL_MAX_DIMMNAME) &&
(bd_dimmp->bd_serialsz <= MCOPL_MAX_SERIAL) &&
(bd_dimmp->bd_partnumsz <= MCOPL_MAX_PARTNUM) &&
(sexp <= bufsz)) {
#ifdef DEBUG
if (oplmc_debug)
mc_dump_dimm_info(bd_dimmp);
#endif
dimm_list = mc_prepare_dimmlist(bd_dimmp);
} else {
cmn_err(CE_WARN, "DIMM info version mismatch\n");
}
}
kmem_free(bd_dimmp, maxbufsz);
MC_LOG("mc_get_dimm_list: dimmlist=0x%p\n", dimm_list);
return (dimm_list);
}
/*
* mc_prepare_dimmlist - Prepare the dimm list from the infomation
* recieved from the SP.
*/
mc_dimm_info_t *
mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp)
{
char *dimm_name;
char *serial;
char *part;
int dimm;
int dnamesz = bd_dimmp->bd_dnamesz;
int sersz = bd_dimmp->bd_serialsz;
int partsz = bd_dimmp->bd_partnumsz;
mc_dimm_info_t *dimm_list = NULL;
mc_dimm_info_t *d;
dimm_name = (char *)(bd_dimmp + 1);
for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
d = (mc_dimm_info_t *)kmem_alloc(sizeof (mc_dimm_info_t),
KM_SLEEP);
snprintf(d->md_dimmname, dnamesz + 1, "%s", dimm_name);
serial = dimm_name + dnamesz;
snprintf(d->md_serial, sersz + 1, "%s", serial);
part = serial + sersz;
snprintf(d->md_partnum, partsz + 1, "%s", part);
d->md_next = dimm_list;
dimm_list = d;
dimm_name = part + partsz;
}
return (dimm_list);
}
#ifdef DEBUG
void
mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz)
{
char dname[MCOPL_MAX_DIMMNAME + 1];
char serial[MCOPL_MAX_SERIAL + 1];
char part[ MCOPL_MAX_PARTNUM + 1];
char *b;
b = buf;
snprintf(dname, dnamesz + 1, "%s", b);
b += dnamesz;
snprintf(serial, serialsz + 1, "%s", b);
b += serialsz;
snprintf(part, partnumsz + 1, "%s", b);
printf("DIMM=%s Serial=%s PartNum=%s\n", dname, serial, part);
}
void
mc_dump_dimm_info(board_dimm_info_t *bd_dimmp)
{
int dimm;
int dnamesz = bd_dimmp->bd_dnamesz;
int sersz = bd_dimmp->bd_serialsz;
int partsz = bd_dimmp->bd_partnumsz;
char *buf;
printf("Version=%d Board=%02d DIMMs=%d NameSize=%d "
"SerialSize=%d PartnumSize=%d\n", bd_dimmp->bd_version,
bd_dimmp->bd_boardnum, bd_dimmp->bd_numdimms, bd_dimmp->bd_dnamesz,
bd_dimmp->bd_serialsz, bd_dimmp->bd_partnumsz);
printf("======================================================\n");
buf = (char *)(bd_dimmp + 1);
for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
mc_dump_dimm(buf, dnamesz, sersz, partsz);
buf += dnamesz + sersz + partsz;
}
printf("======================================================\n");
}
/* ARGSUSED */
static int
mc_ioctl_debug(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
int *rvalp)
{
caddr_t buf;
uint64_t pa;
int rv = 0;
int i;
uint32_t flags;
static uint32_t offset = 0;
flags = (cmd >> 4) & 0xfffffff;
cmd &= 0xf;
MC_LOG("mc_ioctl(cmd = %x, flags = %x)\n", cmd, flags);
if (arg != NULL) {
if (ddi_copyin((const void *)arg, (void *)&pa,
sizeof (uint64_t), 0) < 0) {
rv = EFAULT;
return (rv);
}
buf = NULL;
} else {
buf = (caddr_t)kmem_alloc(PAGESIZE, KM_SLEEP);
pa = va_to_pa(buf);
pa += offset;
offset += 64;
if (offset >= PAGESIZE)
offset = 0;
}
switch (cmd) {
case MCI_CE:
mc_inject_error(MC_INJECT_INTERMITTENT_CE, pa,
flags);
break;
case MCI_PERM_CE:
mc_inject_error(MC_INJECT_PERMANENT_CE, pa,
flags);
break;
case MCI_UE:
mc_inject_error(MC_INJECT_UE, pa,
flags);
break;
case MCI_M_CE:
mc_inject_error(MC_INJECT_INTERMITTENT_MCE, pa,
flags);
break;
case MCI_M_PCE:
mc_inject_error(MC_INJECT_PERMANENT_MCE, pa,
flags);
break;
case MCI_M_UE:
mc_inject_error(MC_INJECT_MUE, pa,
flags);
break;
case MCI_CMP:
mc_inject_error(MC_INJECT_CMPE, pa,
flags);
break;
case MCI_NOP:
mc_inject_error(MC_INJECT_NOP, pa, flags);
break;
case MCI_SHOW_ALL:
mc_debug_show_all = 1;
break;
case MCI_SHOW_NONE:
mc_debug_show_all = 0;
break;
case MCI_ALLOC:
/*
* just allocate some kernel memory and never free it
* 512 MB seems to be the maximum size supported.
*/
cmn_err(CE_NOTE, "Allocating kmem %d MB\n", flags * 512);
for (i = 0; i < flags; i++) {
buf = kmem_alloc(512 * 1024 * 1024, KM_SLEEP);
cmn_err(CE_NOTE, "kmem buf %llx PA %llx\n",
(u_longlong_t)buf, (u_longlong_t)va_to_pa(buf));
}
break;
case MCI_SUSPEND:
(void) opl_mc_suspend();
break;
case MCI_RESUME:
(void) opl_mc_resume();
break;
default:
rv = ENXIO;
}
return (rv);
}
#endif /* DEBUG */