summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4u/starfire/io/idn_xf.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun4u/starfire/io/idn_xf.c')
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn_xf.c1694
1 files changed, 0 insertions, 1694 deletions
diff --git a/usr/src/uts/sun4u/starfire/io/idn_xf.c b/usr/src/uts/sun4u/starfire/io/idn_xf.c
deleted file mode 100644
index 797f2479a8..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn_xf.c
+++ /dev/null
@@ -1,1694 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- * Copyright (c) 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/open.h>
-#include <sys/param.h>
-#include <sys/vm_machparam.h>
-#include <sys/machparam.h>
-#include <sys/systm.h>
-#include <sys/signal.h>
-#include <sys/cred.h>
-#include <sys/user.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/poll.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
-#include <sys/x_call.h>
-#include <sys/cpuvar.h>
-#include <sys/machcpuvar.h>
-#include <sys/machsystm.h>
-
-#include <sys/pda.h>
-#include <sys/starfire.h>
-#include <sys/idn.h>
-#include <sys/idn_xf.h>
-
-kmutex_t idn_xf_mutex; /* to serialize hardware access */
-/*
- * This data structure is referenced during the cross-call
- * update of the CICs. The semaphore is used for synchronization
- * when waiting for completion of the respective operation.
- * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in
- * before we bail out and fail the operation.
- */
-#define IDNCIC_TIMEOUT (30*hz)
-#define IDNCIC_TIMECHK (hz/3)
-#define IDNCIC_UNKNOWN 0
-#define IDNCIC_OK 1 /* values for xf_errcic */
-#define IDNCIC_ERR 2
-#define IDNCIC_BUSY 3
-
-#ifdef DEBUG
-#define NCICREGS 3 /* smmask, smbar, smlar */
-#define CICREG_SMMASK 0
-#define CICREG_SMBAR 1
-#define CICREG_SMLAR 2
-
-#define RESET_CIC_HISTORY() \
- (xf_cicboards = xf_cicbuses = 0, \
- bzero(xf_cicregs, sizeof (xf_cicregs)))
-
-#define UPDATE_CIC_HISTORY(reg, brd, bus, val) \
- (BOARDSET_ADD(xf_cicboards, (brd)), \
- BOARDSET_ADD(xf_cicbuses, (bus)), \
- xf_cicregs[brd][bus][reg] = (val))
-
-#define DUMP_CIC_HISTORY() \
-{ \
- if (idn_debug & IDNDBG_XF) { \
- int _bd, _bs; \
- procname_t _proc = "dump_cic_history"; \
- for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \
- if (!BOARD_IN_SET(xf_cicboards, _bd)) \
- continue; \
- for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \
- if (!BOARD_IN_SET(xf_cicbuses, _bs)) \
- continue; \
- printf("%s: (bd.bs = %d.%d) m/b/l = " \
- "%x/%x/%x\n", _proc, _bd, _bs, \
- xf_cicregs[_bd][_bs][CICREG_SMMASK], \
- xf_cicregs[_bd][_bs][CICREG_SMBAR], \
- xf_cicregs[_bd][_bs][CICREG_SMLAR]); \
- } \
- } \
- DEBUG_DELAY(); \
- } \
-}
-
-/*
- * Globally updated during CIC reg updates. Everybody has
- * a unique location, so no concern about updates stepping
- * on each other.
- */
-static ushort_t xf_cicboards, xf_cicbuses;
-static uint_t xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS];
-#else /* DEBUG */
-#define RESET_CIC_HISTORY()
-#define UPDATE_CIC_HISTORY(reg, brd, bus, val)
-#define DUMP_CIC_HISTORY()
-#endif /* DEBUG */
-
-struct idnxf_cic_info { /* protected by idn_xf_mutex */
-/* 0 */ short xf_abus_mask;
-/* 2 */ boardset_t xf_boardset;
-/* 4 */ uint_t xf_smbase;
-/* 8 */ uint_t xf_smlimit;
-/* c */ int xf_doadd;
-
-/* 10 */ int xf_count; /* atomically updated */
-/* 14 */ time_t xf_start_time;
-/* 18 */ kcondvar_t xf_cv;
-/* 1a */ short xf_errtimer;
-/* 1c */ int xf_errcnt; /* atomically updated */
-
-/* 20 */ uchar_t xf_errcic[MAX_BOARDS][MAX_ABUSES];
-
-/* 60 */ kmutex_t xf_mutex;
-}; /* sizeof = 0x68 = 104 (26X) */
-
-static struct idnxf_cic_info idnxf_cic_info;
-#ifdef DEBUG
-static uint_t o_idn_debug;
-#endif /* DEBUG */
-
-int idn_check_cpu_per_board = 1;
-
-static int pc_prep_cic_buffer(int cpuid, uint_t cicdata);
-static int cic_write_sm_mask(int board, int bus, boardset_t sm_mask);
-static int cic_write_sm_bar(int board, int bus, uint_t sm_bar);
-static int cic_write_sm_lar(int board, int bus, uint_t sm_lar);
-static int cic_get_smmask_bit(void);
-static int pc_write_madr(pda_handle_t ph,
- int lboard, int rboard, uint_t madr);
-static boardset_t get_boardset(pda_handle_t ph, int *nboards);
-static int verify_smregs(int brd, int bus, boardset_t smmask,
- uint_t smbase, uint_t smlimit);
-static void idnxf_shmem_wakeup(void *arg);
-static void idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2);
-static int idnxf_shmem_update_all(pda_handle_t ph,
- boardset_t boardset, uint_t smbase,
- uint_t smlimit, int doadd);
-
-#define PHYSIO_ST(paddr, val) (stphysio((paddr), (val)))
-#define PHYSIO_LD(paddr) (ldphysio(paddr))
-#define PHYSIO_STH(paddr, val) (sthphysio((paddr), (val)))
-#define PHYSIO_LDH(paddr) (ldhphysio(paddr))
-
-#ifdef DEBUG
-#define DEBUG_DELAY() (drv_usecwait(5000)) /* 5 ms */
-#else /* DEBUG */
-#define DEBUG_DELAY()
-#endif /* DEBUG */
-
-
-/*
- * ---------------------------------------------------------------------
- */
-boardset_t
-cic_read_domain_mask(int board, int bus)
-{
- u_longlong_t csr_addr;
- boardset_t domain_mask;
- procname_t proc = "cic_read_domain_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_DOMAIN_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- domain_mask = (boardset_t)PHYSIO_LDH(csr_addr);
-
- return (domain_mask);
-}
-
-boardset_t
-cic_read_sm_mask(int board, int bus)
-{
- u_longlong_t csr_addr;
- boardset_t sm_mask;
- procname_t proc = "cic_read_sm_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_mask = (boardset_t)PHYSIO_LDH(csr_addr);
-
- return (sm_mask);
-}
-
-static int
-cic_write_sm_mask(int board, int bus, boardset_t sm_mask)
-{
- u_longlong_t csr_addr;
- int cnt;
- procname_t proc = "cic_write_sm_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_mask &= 0xffff;
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0)
- return (-1);
-
- /*
- * Now we can write to the CIC.
- */
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s: writing sm_mask = 0x%x\n",
- proc, (ushort_t)sm_mask);
-
- UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_mask);
- /*
- * Read back for verification.
- */
- for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++)
- ;
-
- return ((cnt == 10) ? -1 : 0);
-}
-
-uint_t
-cic_read_sm_bar(int board, int bus)
-{
- u_longlong_t csr_addr;
- uint_t sm_bar;
- procname_t proc = "cic_read_sm_bar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_bar = (uint_t)PHYSIO_LDH(csr_addr);
- sm_bar <<= 16;
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_bar |= (uint_t)PHYSIO_LDH(csr_addr);
-
- return (sm_bar);
-}
-
-static int
-cic_write_sm_bar(int board, int bus, uint_t sm_bar)
-{
- int cnt;
- u_longlong_t csr_addr;
- uint_t sm_bar_lsb, sm_bar_msb;
- procname_t proc = "cic_write_sm_bar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_bar_lsb = sm_bar & 0xffff;
- sm_bar_msb = (sm_bar >> 16) & 0xffff;
-
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n",
- proc, (ushort_t)sm_bar_msb);
-
- UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 500: failed to write sm_bar (msb) (0x%x)",
- (uint_t)sm_bar_msb);
- return (-1);
- }
-
- /*
- * Now to LSB portion.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n",
- proc, (ushort_t)sm_bar_lsb);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 500: failed to write sm_bar (lsb) (0x%x)",
- (uint_t)sm_bar_lsb);
- return (-1);
- }
-
- return (0);
-}
-
-uint_t
-cic_read_sm_lar(int board, int bus)
-{
- u_longlong_t csr_addr;
- uint_t sm_lar;
- procname_t proc = "cic_read_sm_lar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_lar = (uint_t)PHYSIO_LDH(csr_addr);
- sm_lar <<= 16;
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_lar |= (uint_t)PHYSIO_LDH(csr_addr);
-
- return (sm_lar);
-}
-
-static int
-cic_write_sm_lar(int board, int bus, uint_t sm_lar)
-{
- int cnt;
- u_longlong_t csr_addr;
- uint_t sm_lar_lsb, sm_lar_msb;
- procname_t proc = "cic_write_sm_lar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_lar_lsb = sm_lar & 0xffff;
- sm_lar_msb = (sm_lar >> 16) & 0xffff;
-
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n",
- proc, (ushort_t)sm_lar_msb);
-
- UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 501: failed to write sm_lar (msb) (0x%x)",
- (uint_t)sm_lar_msb);
- return (-1);
- }
-
- /*
- * Now to LSB portion.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n",
- proc, (ushort_t)sm_lar_lsb);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 501: failed to write sm_lar (lsb) (0x%x)",
- (uint_t)sm_lar_lsb);
- return (-1);
- }
-
- return (0);
-}
-
-static int
-cic_get_smmask_bit(void)
-{
- u_longlong_t csr_addr;
- int board;
- uint_t config1;
- procname_t proc = "cic_get_smmask_bit";
-
- affinity_set(CPU_CURRENT);
-
- board = CPUID_TO_BOARDID(CPU->cpu_id);
- /*
- * Now that I'm stuck on this cpu I can go look at this
- * board's CIC registers.
- */
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_CONFIG1_ADDR, 0);
- PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n",
- proc, board, csr_addr, (int)CPU->cpu_id);
-
- config1 = (uint_t)PHYSIO_LDH(csr_addr);
-
- config1 = CIC_CONFIG1_SMMASK_BIT(config1);
-
- affinity_clear();
-
- return (config1);
-}
-
-static int
-pc_prep_cic_buffer(int cpuid, uint_t cicdata)
-{
- int rv;
- int brd, port;
- u_longlong_t csr_addr;
- register int cnt;
- procname_t proc = "pc_prep_cic_buffer";
-
-
- ASSERT(CPU->cpu_id == cpuid);
-
- port = cpuid % plat_max_cpu_units_per_board();
- brd = CPUID_TO_BOARDID(cpuid);
-
- csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port);
-
- /*
- * csr_addr now points to CIC write buffer which resides
- * in PC register space.
- */
- PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr);
-
- PHYSIO_ST(csr_addr, cicdata);
-
- /*
- * Now we need to read back the data to guarantee
- * it got there. Part of the PC protocol.
- */
- for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10);
- cnt++)
- ;
-
- rv = 0;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 502: unable to store data (0x%x) to "
- "CIC buffer (0x%llx)",
- cicdata, csr_addr);
- rv = -1;
- } else if (cnt >= 1) {
- PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n",
- proc, cpuid, cnt);
- }
-
- return (rv);
-}
-
-/*
- * --------------------------------------------------
- * Write the given MC address decoding register contents (madr) of
- * the respective remote board (rboard) into all the PCs located on
- * the local board (lboard).
- * --------------------------------------------------
- */
-static int
-pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr)
-{
- u_longlong_t pc_madr_addr;
- register int p, ioc;
- register ushort_t procset, iocset;
- int rv = 0;
- uint_t rd_madr;
- board_desc_t *lbp;
- procname_t proc = "pc_write_madr";
-
- lbp = pda_get_board_info(ph, lboard);
-
- ASSERT(lbp);
- ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
-
- procset = lbp->bda_proc;
- iocset = lbp->bda_ioc;
-
- /*
- * Update the PCs for the cpus.
- */
- for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) {
- int i;
-
- if (!((procset & BDAN_MASK) == BDAN_GOOD))
- continue;
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
- rboard, p);
-
- /*
- * On this first iteration of updating the PC
- * we need to turn off the MADR VALID bit so that
- * there's no accidental usage of the entry before
- * all four bytes have been updated in the PC.
- */
- if (madr != 0) {
- /*
- * Need to clear valid bit on first
- * go around.
- */
- madr &= ~STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
- "[lb=%d, rb=%d, cpu=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, p);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (1) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 503: (invalidate) failed to update "
- "PC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- continue;
- }
- if (madr == 0) {
- continue;
- } else {
- /*
- * Turn the valid bit back on.
- */
- madr |= STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
- "[lb=%d, rb=%d, cpu=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, p);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (2) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 503: (validate) failed to update "
- "PC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- }
- }
- /*
- * Update the PCs for the iocs.
- */
- for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) {
- int i;
-
- if (!((iocset & BDAN_MASK) == BDAN_GOOD))
- continue;
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
- rboard, ioc + 4);
-
- if (madr != 0) {
- /*
- * Need to clear valid bit on first
- * go around.
- */
- madr &= ~STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
- "[lb=%d, rb=%d, ioc=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, ioc);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (3) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 504: (invalidate) failed to update "
- "IOPC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- continue;
- }
-
- if (madr == 0) {
- continue;
- } else {
- /*
- * Turn the valid bit back on.
- */
- madr |= STARFIRE_PC_MADR_VALIDBIT;
- }
-
- PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
- "[lb=%d, rb=%d, ioc=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, ioc);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (4) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 504: (validate) failed to update "
- "IOPC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * --------------------------------------------------
- * Read the array of MC address decoding registers from one of the
- * PCs on the local board (lboard) into the given in array (mc_adr).
- * --------------------------------------------------
- */
-void
-pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only)
-{
- u_longlong_t pc_madr_addr;
- register int p, ioc;
- register ushort_t procset, iocset;
- int brd;
- board_desc_t *lbp;
-
- lbp = pda_get_board_info(ph, lboard);
-
- ASSERT(lbp);
- ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
-
- procset = lbp->bda_proc;
- iocset = lbp->bda_ioc;
-
- for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++)
- if ((procset & BDAN_MASK) == BDAN_GOOD)
- break;
-
- if (p == MAX_PROCMODS) {
- /*
- * Couldn't find a PC off a cpu, let's check the
- * IOCs.
- */
- for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++)
- if ((iocset & BDAN_MASK) == BDAN_GOOD)
- break;
- if (ioc == MAX_IOCS) {
- cmn_err(CE_WARN,
- "IDN: 505: board %d missing any valid PCs",
- lboard);
- return;
- }
- p = ioc + 4;
- }
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p);
- /*
- * pc_madr_addr = Starts at entry for board 0.
- */
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- /*
- * It's possible our local PC may have old entries to
- * AWOL domains. Only want to pay attention to PC
- * entries corresponding to our boards.
- */
- lbp = pda_get_board_info(ph, brd);
- if (!local_only || ((lbp->bda_board & BDAN_MASK) == BDAN_GOOD))
- mc_adr[brd] = PHYSIO_LD(pc_madr_addr);
- else
- mc_adr[brd] = 0;
-
- pc_madr_addr += ((u_longlong_t)1 <<
- STARFIRE_PC_MADR_BOARD_SHIFT);
- }
-}
-
-/*
- * --------------------------------------------------
- * Read the MC address decoding register contents for all
- * possible boards and store the results in their respective
- * slot in mc_adr. Keep a count of non-zero MC ADRs and
- * return that.
- * --------------------------------------------------
- */
-void
-mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr)
-{
- int brd;
- uint_t madr[MAX_BOARDS];
-
- /*
- * Note that each PC has a complete copy of all MC contents
- * and so all we have to do is read one PC rather than
- * each of the MCs in the system.
- */
- brd = CPUID_TO_BOARDID(CPU->cpu_id);
- pc_read_madr(ph, brd, madr, 1);
-
- *nmcadr = 0;
- for (brd = 0; brd < MAX_BOARDS; brd++)
- if ((mc_adr[brd] = madr[brd]) != 0)
- (*nmcadr)++;
-}
-
-static boardset_t
-get_boardset(pda_handle_t ph, int *nboards)
-{
- int brd;
- int nbrds = 0;
- boardset_t bmask;
-
- if (nboards != NULL)
- *nboards = 0;
-
- bmask = 0;
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- if (pda_board_present(ph, brd)) {
- bmask |= 1 << brd;
- nbrds++;
- }
- }
- if (nboards != NULL)
- *nboards = (short)nbrds;
-
- return (bmask);
-}
-
-int
-update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw)
-{
- procname_t proc = "update_local_hw_config";
-
- ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid));
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(ldp == &idn_domain[idn.localid]);
-
- if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) {
- int c;
-
- PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, "
- "new_bset = 0x%x)\n",
- proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset);
-
- PR_PROTO("%s: clearing boardset 0x%x\n", proc,
- ldp->dhw.dh_boardset & ~loc_hw->dh_boardset);
- PR_PROTO("%s: setting boardset 0x%x\n", proc,
- loc_hw->dh_boardset & ~ldp->dhw.dh_boardset);
-
- idn.dc_boardset &= ~ldp->dhw.dh_boardset;
- idn.dc_boardset |= loc_hw->dh_boardset;
- for (c = 0; c < NCPU; c++) {
- if (CPU_IN_SET(ldp->dcpuset, c)) {
- CPUSET_DEL(idn.dc_cpuset, c);
- }
- }
- CPUSET_OR(idn.dc_cpuset, cpu_ready_set);
-
- bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw));
- ldp->dcpuset = cpu_ready_set;
- ldp->dcpu = cpu0.cpu_id;
- ldp->dncpus = (int)ncpus;
- ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1;
- ldp->dvote.v.ncpus = (int)ldp->dncpus - 1;
- ldp->dvote.v.board = CPUID_TO_BOARDID(CPU->cpu_id);
-
- return (1);
- } else {
- PR_PROTO("%s: NO change detected\n", proc);
- return (0);
- }
-}
-
-int
-get_hw_config(struct hwconfig *loc_hw)
-{
- pda_handle_t ph;
- boardset_t domainset;
- int bd;
- int nmcadr;
- int nboards;
- procname_t proc = "get_hw_config";
-
- ASSERT(loc_hw != NULL);
-
- bzero(loc_hw, sizeof (*loc_hw));
- /*
- * See if sm_mask is writable.
- * XXX - Should be the same for all CIC's. Do we
- * we need to verify?
- */
- if (cic_get_smmask_bit() == 0) {
- /*
- * If smmask is not writable, we can not allow
- * IDN operations.
- */
- cmn_err(CE_WARN,
- "IDN: 506: cic sm_mask is not writeable");
- return (-1);
- }
- /*
- * Map in the post2obp structure so we can find
- * valid boards and hardware asics.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- return (-1);
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- pda_close(ph);
- return (-1);
- }
- /*
- * Need to read the MC address decoding registers
- * so that they can be given to other domains.
- */
- loc_hw->dh_boardset = get_boardset(ph, &nboards);
- loc_hw->dh_nboards = (short)nboards;
- ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id)));
-
- mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr);
- loc_hw->dh_nmcadr = (short)nmcadr;
-
- affinity_set(CPU_CURRENT);
- /*
- * There will always be a bus 0 (logical).
- */
- bd = CPUID_TO_BOARDID(CPU->cpu_id);
- domainset = (boardset_t)cic_read_domain_mask(bd, 0);
- affinity_clear();
-
- if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) {
- pda_close(ph);
- return (-1);
- }
-
- pda_close(ph);
-
-
-#ifdef DEBUG
- {
- int brd;
-
- for (brd = 0; brd < MAX_BOARDS; brd++)
- if (loc_hw->dh_mcadr[brd] != 0) {
- PR_XF("%s: brd %d, mc = 0x%x\n",
- proc, brd, loc_hw->dh_mcadr[brd]);
- }
- }
-#endif /* DEBUG */
-
- if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1))
- return (-1);
- else
- return (0);
-}
-
-/*
- * Function called via timeout() to wakeup a possibly stuck
- * idnxf_shmem_update_all() should not all cpus check-in after a
- * x-call to update their respective CICs.
- */
-/*ARGSUSED0*/
-static void
-idnxf_shmem_wakeup(void *arg)
-{
- struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg;
- int count;
- int expired;
- procname_t proc = "idnxf_shmem_wakeup";
-
- expired = ((ddi_get_lbolt() - idnxfp->xf_start_time) >=
- IDNCIC_TIMEOUT) ? 1 : 0;
-
- if ((count = idnxfp->xf_count) == 0) {
- /*
- * Everybody has finished. Wakeup the requester.
- */
- mutex_enter(&idnxfp->xf_mutex);
- cv_signal(&idnxfp->xf_cv);
- mutex_exit(&idnxfp->xf_mutex);
-
- } else if ((count > 0) && expired) {
- /*
- * There are still active cic updaters and time
- * has expired. Bail on them.
- */
- idnxfp->xf_errtimer = 1;
-#ifdef DEBUG
- /*
- * Special debug case since idn_debug
- * may have been temporarily cleared
- * during xc_some.
- */
- if ((idn_debug | o_idn_debug) & IDNDBG_REGS)
- printf("%s: TIMEOUT...bailing on %d lost CIC "
- "updates...\n", proc, count);
-#endif /* DEBUG */
-
- ATOMIC_SUB(idnxfp->xf_count, count);
-
- mutex_enter(&idnxfp->xf_mutex);
- cv_signal(&idnxfp->xf_cv);
- mutex_exit(&idnxfp->xf_mutex);
-
- } else {
- (void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp,
- (clock_t)IDNCIC_TIMECHK);
- }
-}
-
-/*
- * Called indirectly from idnxf_shmem_update_all() via a xcall
- * for the recepient cpu to update the CICs on its respective
- * board.
- * IMPORTANT: NO console output from this routine!!
- */
-static void
-idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2)
-{
- struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg1;
- time_t start_time = (time_t)arg2;
- int rv, cpuid, brd, bus;
- boardset_t smmask;
-
-
- cpuid = CPU->cpu_id;
- brd = CPUID_TO_BOARDID(cpuid);
-
- if (idnxfp->xf_start_time != start_time) {
- /*
- * Ooops! Not my place to intrude.
- */
- idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY;
- ATOMIC_INC(idnxf_cic_info.xf_errcnt);
-
- goto done;
- }
-
- /*
- * We're executing out of the context of a cross-call
- * so we're effectively bound! :)
- */
- for (bus = 0; bus < MAX_ABUSES; bus++) {
- /*
- * XXX - need to worry about shuffle??
- */
- if (!(idnxfp->xf_abus_mask & (1 << bus)))
- continue;
- smmask = cic_read_sm_mask(brd, bus);
-
- if (idnxfp->xf_doadd) {
- smmask |= idnxfp->xf_boardset;
- (void) cic_write_sm_mask(brd, bus, smmask);
-
- if (idnxfp->xf_smbase != (uint_t)-1) {
- (void) cic_write_sm_bar(brd, bus,
- idnxfp->xf_smbase);
- (void) cic_write_sm_lar(brd, bus,
- idnxfp->xf_smlimit);
- }
- /*
- * Verify data got there!
- */
- rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase,
- idnxfp->xf_smlimit);
- } else {
- smmask &= ~idnxfp->xf_boardset;
- (void) cic_write_sm_mask(brd, bus, smmask);
-
- if (!smmask) {
- /*
- * Update the LAR first so that we effectively
- * disable the register without possibly
- * opening the window to transaction we
- * don't care about. Updating the LAR first
- * will guarantee we effectively turn it
- * off immediately.
- */
- (void) cic_write_sm_lar(brd, bus, 0);
- (void) cic_write_sm_bar(brd, bus, 1);
-
- rv = verify_smregs(brd, bus, smmask, 1, 0);
- } else {
- rv = verify_smregs(brd, bus, smmask,
- (uint_t)-1, (uint_t)-1);
- }
- }
- if (rv) {
- idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR;
- ATOMIC_INC(idnxf_cic_info.xf_errcnt);
- } else {
- idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK;
- }
- }
-
-done:
- ATOMIC_DEC(idnxf_cic_info.xf_count);
-}
-
-static int
-idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset,
- uint_t smbase, uint_t smlimit, int doadd)
-{
- cpuset_t target_cpuset;
- int target_count;
- int rv = 0;
- int c, brd, bus;
- short abus_mask;
- time_t start_time;
- procname_t proc = "idnxf_shmem_update_all";
-
-
- ASSERT(MUTEX_HELD(&idn_xf_mutex));
-
- pda_get_busmask(ph, &abus_mask, NULL);
-
- CPUSET_ZERO(target_cpuset);
- target_count = 0;
- /*
- * Build a cpuset of target cpus (one per board) to
- * be used to send the CIC update xcall.
- */
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- /*
- * Need to target an available cpu on the target board
- * so that we can look at the CICs on that board.
- */
- c = board_to_ready_cpu(brd, cpu_ready_set);
-
- if (c == -1) {
- /*
- * If there's no cpu on this board, no
- * need to update the CICs.
- */
- continue;
- }
- CPUSET_ADD(target_cpuset, c);
- target_count++;
- }
-
- if (CPUSET_ISNULL(target_cpuset)) {
- PR_REGS("%s: NO target cpus to update!!\n", proc);
- return (0);
- }
-
- RESET_CIC_HISTORY();
-
- /*
- * Broadcast out the CIC update request and then
- * sit back and wait for dinner to arrive!
- * Let's set up the global structure all the xcall
- * recepients will read.
- */
- start_time = ddi_get_lbolt();
- /*
- * Set the start time. Make sure it's different
- * then the previous run.
- */
- if (start_time <= idnxf_cic_info.xf_start_time)
- start_time++;
- idnxf_cic_info.xf_start_time = start_time;
-
- idnxf_cic_info.xf_abus_mask = abus_mask;
- idnxf_cic_info.xf_boardset = boardset;
- idnxf_cic_info.xf_smbase = smbase;
- idnxf_cic_info.xf_smlimit = smlimit;
- idnxf_cic_info.xf_doadd = doadd;
- idnxf_cic_info.xf_count = target_count;
- idnxf_cic_info.xf_errcnt = 0;
- idnxf_cic_info.xf_errtimer = 0;
- bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic));
-
- /*
- * Broadcast out the xcall to do the task.
- */
-#ifdef DEBUG
- {
- uint_t tu32, tl32;
-
- tu32 = UPPER32_CPUMASK(target_cpuset);
- tl32 = LOWER32_CPUMASK(target_cpuset);
- PR_REGS("%s: (start %ld) broadcasting CIC - "
- "%s to cpus 0x%x.%0x\n",
- proc, start_time, doadd ? "LINK" : "UNLINK",
- tu32, tl32);
- }
-
- /*
- * Can't dump debug during cross-calls.
- */
- o_idn_debug = idn_debug;
- idn_debug = 0;
-#endif /* DEBUG */
-
- xc_attention(target_cpuset);
-
- xc_some(target_cpuset, idnxf_shmem_update_one,
- (uint64_t)&idnxf_cic_info, (uint64_t)start_time);
-
- xc_dismissed(target_cpuset);
-
- ASSERT(idnxf_cic_info.xf_count == 0);
-
-#ifdef DEBUG
- idn_debug = o_idn_debug;
- o_idn_debug = 0;
-#endif /* DEBUG */
-
- PR_REGS("%s: waiting for completion of %d CIC - %s...\n",
- proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS");
- PR_REGS("%s: CIC - %s have checked IN.\n",
- proc, doadd ? "LINKS" : "UNLINKS");
-
- /*
- * Modifying xf_start_time effectively disables any
- * possible outstanding xcall's since they don't touch
- * idnxf_cic_info unless their given start_time matches
- * that in the idnxf_cic_info structure.
- */
- idnxf_cic_info.xf_start_time++;
-
- PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n",
- proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer);
- DUMP_CIC_HISTORY();
- /*
- * Should errors be fatal? (panic).
- */
- rv = 0;
- for (c = 0; c < NCPU; c++) {
- if (!CPU_IN_SET(target_cpuset, c))
- continue;
- brd = CPUID_TO_BOARDID(c);
-
- for (bus = 0; bus < MAX_ABUSES; bus++) {
-
- if (!(abus_mask & (1 << bus)))
- continue;
-
- switch (idnxf_cic_info.xf_errcic[brd][bus]) {
- case IDNCIC_UNKNOWN:
- /*
- * Unknown is only an error if the
- * timer expired.
- */
- if (!idnxf_cic_info.xf_errtimer)
- break;
- cmn_err(CE_WARN,
- "IDN: 509: CPU %d never responded "
- "to CIC update", c);
- /*FALLTHROUGH*/
-
- case IDNCIC_ERR:
- cmn_err(CE_WARN,
- "IDN: 510: failed write-smregs "
- "(bd=%d, bs=%d, sm(bar=0x%x, "
- "lar=0x%x))",
- brd, bus, smbase, smlimit);
- rv++;
- break;
-
- case IDNCIC_BUSY:
- cmn_err(CE_WARN, "IDN: 511: update-one "
- "(cpu=%d, bd=%d) time conflict",
- c, brd);
- /*
- * Should never occur. Not fatal,
- * just continue.
- */
- break;
-
- default:
- PR_REGS("%s: board %d, bus %d "
- "(bar=0x%x,lar=0x%x) - update OK\n",
- proc, brd, bus, smbase, smlimit);
- break;
- }
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * Add the respective boardset/base/limit/mcadr's to the local
- * domain's hardware configuration with respect to the SMR.
- *
- * is_master Indicates remote domain is a master.
- */
-int
-idnxf_shmem_add(int is_master, boardset_t boardset, pfn_t pfnbase,
- pfn_t pfnlimit, uint_t *mcadr)
-{
- int rv = 0;
- register int brd, rbrd;
- register boardset_t localboardset;
- uint_t madr;
- uint_t smbase, smlimit;
- pda_handle_t ph;
- procname_t proc = "idnxf_shmem_add";
-
-
- localboardset = idn_domain[idn.localid].dhw.dh_boardset;
-
- ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
- ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1);
-
- if (pfnbase != PFN_INVALID) {
- smbase = (uint_t)PFN_TO_SMADDR(pfnbase);
- smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit);
- } else {
- smbase = smlimit = (uint_t)-1;
- }
- PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n",
- proc, is_master, boardset, smbase, smlimit);
-
- /*
- * Need to serialize hardware access so we don't have multiple
- * threads attempting to access hardware regs simulataneously.
- * This should not be a significant performance penalty since
- * the hardware is only touched when domains are linking or
- * unlinking.
- */
- mutex_enter(&idn_xf_mutex);
-
- /*
- * Map in the post2obp structure so we can find
- * bus config information.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- rv = -1;
- goto done;
-
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- rv = -1;
- goto done;
- }
- /*
- * Take a checkpoint in bbsram for diagnostic purposes.
- */
- CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1);
-
- rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1);
-
- if (rv || (is_master == 0))
- goto done;
-
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to deprogram our PCs.
- */
- PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n",
- proc, localboardset, boardset);
-
- for (brd = 0; brd < MAX_BOARDS; brd++) {
-
- if (!BOARD_IN_SET(localboardset, brd))
- continue;
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to program our PCs.
- */
- for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
-
- if ((madr = mcadr[rbrd]) == 0)
- continue;
-
- ASSERT(BOARD_IN_SET(boardset, rbrd));
- /*
- * Write the MC adr for the respective
- * remote board (rbrd) into the PCs of
- * the given local board (brd).
- */
- if (pc_write_madr(ph, brd, rbrd, madr) < 0) {
- cmn_err(CE_WARN,
- "IDN: 512: failed [add] write-madr "
- "(bd=%d, rbd=%d, madr=0x%x)",
- brd, rbrd, madr);
- rv = -1;
- goto done;
- }
- }
- }
-
-done:
- if (ph)
- pda_close(ph);
-
- mutex_exit(&idn_xf_mutex);
- /*
- * XXX
- *
- * Failure here is fatal. Disable IDN?
- * NOn-zero return value will at least prevent
- * linkage with domain - probably sufficient.
- */
- return (rv);
-}
-
-/*
- * Remove the respective boardset from the local domain's
- * hardware configuration with respect to the SMR.
- *
- * is_master Indicates remote domain is a master.
- */
-int
-idnxf_shmem_sub(int is_master, boardset_t boardset)
-{
- int rv = 0;
- register int brd, rbrd;
- register boardset_t localboardset;
- pda_handle_t ph;
- procname_t proc = "idnxf_shmem_sub";
-
- localboardset = idn_domain[idn.localid].dhw.dh_boardset;
-
- ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
-
- PR_REGS("%s: is_master=%d, boardset=0x%x\n",
- proc, is_master, boardset);
-
- /*
- * Need to serialize hardware access so we don't have multiple
- * threads attempting to access hardware regs simulataneously.
- * This should not be a significant performance penalty since
- * the hardware is only touched when domains are linking or
- * unlinking.
- */
- mutex_enter(&idn_xf_mutex);
-
- /*
- * Map in the post2obp structure so we can find
- * bus config information.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- rv = -1;
- goto done;
-
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- rv = -1;
- goto done;
- }
- /*
- * Take a checkpoint in bbsram for diagnostic purposes.
- */
- CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2);
-
- rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0);
-
- if (rv || (is_master == 0))
- goto done;
-
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to deprogram our PCs.
- */
- PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n",
- proc, localboardset, boardset);
-
- for (brd = 0; brd < MAX_BOARDS; brd++) {
-
- if (!BOARD_IN_SET(localboardset, brd))
- continue;
-
- for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
-
- if (!BOARD_IN_SET(boardset, rbrd))
- continue;
- /*
- * Clear the MC adr for the respective
- * remote board (rbrd) into the PCs of
- * the given local board (brd).
- */
- if (pc_write_madr(ph, brd, rbrd, 0) < 0) {
- cmn_err(CE_WARN,
- "IDN: 512: failed [del] write-madr "
- "(bd=%d, rbd=%d, madr=0x%x)",
- brd, rbrd, 0);
- rv = -1;
- goto done;
- }
- }
- }
-
-done:
- if (ph)
- pda_close(ph);
- mutex_exit(&idn_xf_mutex);
-
- return (rv);
-}
-
-/*
- * We cannot cross-trap cpu_flush_ecache since it references
- * %g7 via CPU. It's possible that %g7 may not be set up
- * when the trap comes in, and could thus cause a crash.
- * Well...at least that's what has been happening when I
- * tried x-calls within an xc_attention (KMISS) panic.
- * Instead we use cross-calls. However, since we can't
- * xc_attention around a cross-call, we have not guaranteed
- * way of knowing the operation succeeded. To synchronize
- * this flush operation across cpus, we use a semaphore
- * which is V'd by the receiving cpus and P'd by the caller
- * initiating the all-cpus flush.
- */
-/*ARGSUSED0*/
-void
-idn_flush_ecache(uint64_t arg1, uint64_t arg2)
-{
- extern void cpu_flush_ecache(void);
-
- cpu_flush_ecache();
- /*
- * Paranoia...Give things a chance to drain.
- */
- drv_usecwait(500000); /* 500 msec */
-}
-/*
- * Flush the ecache's of all the cpus within this domain of
- * any possible SMR references.
- * This logic is borrowed from ecc.c:cpu_flush_ecache().
- */
-void
-idnxf_flushall_ecache()
-{
- cpuset_t local_cpuset;
- procname_t proc = "idnxf_flushall_ecache";
-
-
- PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n", proc,
- UPPER32_CPUMASK(cpu_ready_set), LOWER32_CPUMASK(cpu_ready_set));
-
- CHECKPOINT_CACHE_CLEAR_DEBUG(1);
- CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2);
-
- local_cpuset = cpu_ready_set;
-
- xc_attention(local_cpuset);
-
- /*
- * We tell each cpu to do a flush and then we hit
- * a semaphore to synchronize with all of them
- * to guarantee they have completed the flush before
- * we continue on. We have to do this type of
- * sychronization since we can't xc_attention around
- * a cross-call.
- */
- CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3);
-
- xc_all(idn_flush_ecache, 0, 0);
-
- CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4);
-
- xc_dismissed(local_cpuset);
-
- CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5);
-}
-
-/*
- * --------------------------------------------------
- */
-static int
-verify_smregs(int brd, int bus, boardset_t smmask, uint_t smbase, uint_t
- smlimit)
-{
- int rv = 0;
- uint_t smreg;
-
- if (smmask != (boardset_t)-1) {
- smreg = (uint_t)cic_read_sm_mask(brd, bus);
- if (smreg != (uint_t)smmask) {
- cmn_err(CE_WARN,
- "IDN: 513: sm-mask error "
- "(expected = 0x%x, actual = 0x%x)",
- (uint_t)smmask, smreg);
- rv++;
- }
- }
-
- if (smbase != (uint_t)-1) {
- smreg = cic_read_sm_bar(brd, bus);
- if (smreg != smbase) {
- cmn_err(CE_WARN,
- "IDN: 514: sm-base error "
- "(expected = 0x%x, actual = 0x%x)",
- smbase, smreg);
- rv++;
- }
- }
-
- if (smlimit != (uint_t)-1) {
- smreg = cic_read_sm_lar(brd, bus);
- if (smreg != smlimit) {
- cmn_err(CE_WARN,
- "IDN: 515: sm-limit error "
- "(expected = 0x%x, actual = 0x%x)",
- smlimit, smreg);
- rv++;
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * -------------------------------------------------------------
- */
-int
-idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp)
-{
- int b, err = 0;
- boardset_t bset, cpu_bset;
- board_desc_t *lbp;
-
- if (!idn_check_cpu_per_board)
- return (1);
-
- bset = hwp->dh_boardset;
- CPUSET_TO_BOARDSET(cset, cpu_bset);
-
- /*
- * Every board has at least one cpu, we're happy.
- */
- if (cpu_bset == bset)
- return (1);
-
- /*
- * Well, not all boards had cpus. That's okay so
- * long as they don't have memory also.
- * Get rid of the boards that have a cpu.
- */
- bset &= ~cpu_bset;
- /*
- * None of the remaining boards in the set shold have mem.
- */
- err = 0;
-
- /*
- * A NULL post2obp pointer indicates we're checking
- * the config of a remote domain. Since we can't
- * look at the post2obp of the remote domain, we'll
- * have to trust what it passed us in its config.
- */
- if (ph && !pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- return (0);
- }
-
- for (b = 0; b < MAX_BOARDS; b++) {
- if (!BOARD_IN_SET(bset, b))
- continue;
-
- lbp = ph ? pda_get_board_info(ph, b) : NULL;
-
- if ((lbp &&
- (BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) ||
- (!lbp && hwp->dh_mcadr[b])) {
- err++;
- cmn_err(CE_WARN,
- "IDN: 516: (%s) board %d has memory, "
- "but no CPUs - CPU per memory board REQUIRED",
- ph ? "local" : "remote", b);
- }
- }
-
- return (err ? 0 : 1);
-}