03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This file contains the Starcat Solaris Mailbox Client module. This module
03831d35f7499c87d51205817c93e9a8d42c4baestevel * handles mailbox messages from the SC to the OS (as opposed to messages sent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to specific drivers) and vice versa. Two task queues are created upon
03831d35f7499c87d51205817c93e9a8d42c4baestevel * startup; one handles reading and processing of all incoming messages, while
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the other handles transmission of all outgoing messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/param.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/systm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysmacros.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/condvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mutex.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/disp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/thread.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpu_sgnblk_defs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/machsystm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mboxsc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/uadmin.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cred.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/taskq.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/utsname.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_ecc_unum.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/fm/protocol.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/fm/util.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/starcat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_ecc_dimm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_datapath.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* mailbox keys */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_KEY 0x5343444d /* 'S', 'C', 'D', 'M' */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DMSC_KEY 0x444d5343 /* 'D', 'M', 'S', 'C' */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* mailbox commands */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_CMD ('S' << 8) /* generic SSP */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_CMD_SUCCESS (SCDM_CMD | 0x1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_GOTO_OBP (SCDM_CMD | 0x2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_GOTO_PANIC (SCDM_CMD | 0x3)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_ENVIRON (SCDM_CMD | 0x4) /* environmental intr */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_SHUTDOWN (SCDM_CMD | 0x5) /* setkeyswitch STANDBY */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_GET_NODENAME (SCDM_CMD | 0x6) /* get domain nodename */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_LOG_ECC_ERROR (SCDM_CMD | 0x7) /* ECC error logging */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_LOG_ECC_INDICTMENT (SCDM_CMD | 0x8) /* ECC indictment logging */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_LOG_ECC (SCDM_CMD | 0x9) /* ECC info */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_LOG_ECC_CAP_INIT (SCDM_CMD | 0xa) /* ECC Capability Init */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_LOG_ECC_CAP_RESP (SCDM_CMD | 0xb) /* ECC Capability Response */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_DIMM_SERIAL_ID (SCDM_CMD | 0xc) /* DIMM ser# req/resp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_DP_ERROR_MSG (SCDM_CMD | 0xd) /* datapath error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCDM_DP_FAULT_MSG (SCDM_CMD | 0xe) /* datapath fault */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* general constants */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define GETMSG_TIMEOUT_MS 500
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define PUTMSG_TIMEOUT_MS 6000
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MIN_INPUTQ_TASKS 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAX_INPUTQ_TASKS 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MIN_OUTPUTQ_TASKS 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAX_OUTPUTQ_TASKS 512
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef TRUE
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define TRUE 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef FALSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define FALSE 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelclock_t ecc_message_timeout_ms = PUTMSG_TIMEOUT_MS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When a message needs to be sent to the SC, an scosmb_msgdata_t should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * populated with the data to be used for the message, and a call to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_process_output should be dispatched on the scosmb_output_taskq, with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the address of the scosmb_msgdata_t structure as its arg. The "length" and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "data" fields can be used if the message needs to include data beyond the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * header fields (type, cmd, and transid) and that information must be recorded
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when the message is placed on the taskq. If appropriate for the message type
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (e.g. nodename info that should always be the most recent available), the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "data" field can be set to NULL and the additional data can be assembled
03831d35f7499c87d51205817c93e9a8d42c4baestevel * immediately prior to sending the message in scosmb_process_output().
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If log_error is set, any errors in delivering the message cause a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmn_err() message to be issued. If it is zero, the error is expressed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only through return values.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t cmd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int log_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} scosmb_msgdata_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Datapath error and fault messages arrive unsolicited. The message data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is contained in a plat_datapath_info_t structure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t type; /* CDS, DX, EX, CP */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t pad; /* for alignment */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t cpuid; /* Safari ID of base CPU */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t t_value; /* SERD timeout threshold (seconds) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel} plat_datapath_info_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* externally visible routines */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid scosmb_update_nodename(uint64_t transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* local routines */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scosmb_inbox_handler();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scosmb_process_input(void *unused);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scosmb_process_output(scosmb_msgdata_t *arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* local variables */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint8_t scosmb_mboxsc_failed = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint8_t scosmb_mboxsc_timedout = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint8_t scosmb_nodename_event_pending = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char scosmb_hdr[] = "SCOSMB:";
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t scosmb_mutex;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic taskq_t *scosmb_input_taskq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic taskq_t *scosmb_output_taskq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *dperrtype[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DP_ERROR_CDS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DP_ERROR_DX,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DP_ERROR_EX,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DP_ERROR_CP
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Structures from modctl.h used for loadable module support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCOSMB is a "miscellaneous" module.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_miscops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlmisc modlmisc = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_miscops,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Sun Fire 15000 OS Mbox Client v1.10",
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modlmisc,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _init
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine. Initializes mutex and condition variables
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and starts thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the mailboxes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mboxsc_init(SCDM_KEY, MBOXSC_MBOX_IN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_inbox_handler)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s mboxsc_init failed (0x%x)\n", scosmb_hdr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mboxsc_init(DMSC_KEY, MBOXSC_MBOX_OUT, NULL)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s mboxsc_init failed (0x%x)\n", scosmb_hdr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_fini(SCDM_KEY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the global lock
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&scosmb_mutex, NULL, MUTEX_DEFAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create the task queues used for processing input and output messages
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_input_taskq = taskq_create("scosmb_input_taskq", 1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel minclsyspri, MIN_INPUTQ_TASKS, MAX_INPUTQ_TASKS, TASKQ_PREPOPULATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_output_taskq = taskq_create("scosmb_output_taskq", 1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel minclsyspri, MIN_OUTPUTQ_TASKS, MAX_OUTPUTQ_TASKS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel TASKQ_PREPOPULATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to install the module. If unsuccessful, uninitialize
03831d35f7499c87d51205817c93e9a8d42c4baestevel * everything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mod_install(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel taskq_destroy(scosmb_output_taskq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel taskq_destroy(scosmb_input_taskq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&scosmb_mutex);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_fini(DMSC_KEY);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_fini(SCDM_KEY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _fini
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine. Since this routine shouldn't be unloaded (it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * provides a critical service, and its symbols may be referenced externally),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EBUSY is returned to prevent unloading.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _info
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mod_info(&modlinkage, modinfop);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_inbox_handler() - mbox API event handler.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine adds an entry to the scosmb_input_taskq that will cause the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_process_input() routine to be called to service the SCDM mailbox. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possibility that taskq_dispatch may fail when given KM_NOSLEEP is safely
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ignored because there can only be one message waiting in the mailbox at any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * given time, so the current message will end up being handled by one of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * previously queued jobs (and a previous message presumably timed out before we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * got around to reading it).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscosmb_inbox_handler()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) taskq_dispatch(scosmb_input_taskq, scosmb_process_input, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dp_get_cores()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Checks cpu implementation for the input cpuid and returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the number of cores.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If implementation cannot be determined, returns 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldp_get_cores(uint16_t cpuid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int exp, ii, impl = 0, nc, slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = STARCAT_CPUID_TO_EXPANDER(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = STARCAT_CPUID_TO_BOARDSLOT(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot == 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel nc = STARCAT_SLOT1_CPU_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel nc = plat_max_cpu_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find first with valid implementation */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (ii = 0; ii < nc; ii++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[MAKE_CPUID(exp, slot, ii)]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl = cpunodes[MAKE_CPUID(exp, slot, ii)].
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki implementation;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_JAGUAR(impl) || IS_PANTHER(impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dp_payload_add_cpus()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * From datapath mailbox message, determines the number of and safari IDs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for affected cpus, then adds this info to the datapath ereport.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Input maxcat (if set) is a count of maxcat cpus actually present - it is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a count of cpuids, which takes into account multi-core architecture.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldp_payload_add_cpus(plat_datapath_info_t *dpmsg, nvlist_t *erp, int maxcat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int jj = 0, numcpus = 0, nummaxcpus = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int count, exp, ii, num, ncores, ret, slot, port;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t *dparray, cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *snarray;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check for multiple core architectures */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ncores = dp_get_cores(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine the number of cpu cores impacted
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (dpmsg->type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CDS_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (maxcat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel nummaxcpus = ncores;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel numcpus = ncores;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_DX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (maxcat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel nummaxcpus = 2 * ncores;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel numcpus = 2 * ncores;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_EX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (maxcat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel nummaxcpus = STARCAT_SLOT1_CPU_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel numcpus = plat_max_cpu_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CP_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC-DE supplies the base cpuid affected, if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * maxcat id was given, there's no slot 0 board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * present.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!maxcat) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Slot 0 id was given - set numcpus */
03831d35f7499c87d51205817c93e9a8d42c4baestevel numcpus = plat_max_cpu_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* there may/may not be maxcats. set a count anyway */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nummaxcpus = STARCAT_SLOT1_CPU_MAX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Allocate space for cores */
03831d35f7499c87d51205817c93e9a8d42c4baestevel num = numcpus + nummaxcpus;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray = kmem_zalloc(num * sizeof (uint16_t *), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * populate dparray with impacted cores (only those present)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = STARCAT_CPUID_TO_EXPANDER(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = STARCAT_CPUID_TO_BOARDSLOT(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel port = STARCAT_CPUID_TO_LPORT(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (dpmsg->type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CDS_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For a CDS error, it's the reporting cpuid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and it's other core (if present)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid & 0xFFFB; /* core 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid | 0x4; /* core 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_DX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For a DX error, it's the reporting cpuid (all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cores), and the other CPU sharing the same
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DX<-->DCDS interface (all cores)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* reporting cpuid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid & 0xFFFB; /* core 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid | 0x4; /* core 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find partner cpuid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (port == 0 || port == 2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid | 0x1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = dpmsg->cpuid & 0xFFFE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* add partner cpuid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid &= 0xFFFB; /* core 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid |= 0x4; /* core 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_EX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For an EX error, it is all cpuids (all cores)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the reporting board
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot == 1) /* maxcat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel count = nummaxcpus;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel count = numcpus;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (ii = 0; ii < count; ii++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = MAKE_CPUID(exp, slot, ii);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CP_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For a CP error, it is all cpuids (all cores)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on both boards (SB & IO) in the boardset
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do slot 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (ii = 0; ii < numcpus; ii++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = MAKE_CPUID(exp, 0, ii);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do slot 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (ii = 0; ii < nummaxcpus; ii++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = MAKE_CPUID(exp, 1, ii);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid])
03831d35f7499c87d51205817c93e9a8d42c4baestevel dparray[jj++] = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The datapath message could not be associated with any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * configured CPU.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!jj) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(dparray, num * sizeof (uint16_t *));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = nvlist_add_uint32(erp, DP_LIST_SIZE, jj);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ret == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel snarray = kmem_zalloc(jj * sizeof (uint64_t *), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (ii = 0; ii < jj; ii++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel snarray[ii] = cpunodes[dparray[ii]].device_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = nvlist_add_uint32(erp, DP_LIST_SIZE, jj);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret |= nvlist_add_uint16_array(erp, DP_LIST, dparray, jj);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret |= nvlist_add_uint64_array(erp, SN_LIST, snarray, jj);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ret == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(dparray, num * sizeof (uint16_t *));
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(snarray, jj * sizeof (uint64_t *));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dp_trans_event() - datapath message handler.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process datapath error and fault messages received from the SC. Checks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for, and disregards, messages associated with I/O boards. Otherwise,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * extracts message info to produce a datapath ereport.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldp_trans_event(plat_datapath_info_t *dpmsg, int msgtype)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel nvlist_t *erp, *detector, *hcelem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[FM_MAX_CLASS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int exp, slot, i, maxcat = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check for I/O board message */
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = STARCAT_CPUID_TO_EXPANDER(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = STARCAT_CPUID_TO_BOARDSLOT(dpmsg->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_SLOT1_CPU_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[MAKE_CPUID(exp, slot, i)]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* maxcat cpu present */
03831d35f7499c87d51205817c93e9a8d42c4baestevel maxcat++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ignore I/O board msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (maxcat == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* allocate space for ereport */
03831d35f7499c87d51205817c93e9a8d42c4baestevel erp = fm_nvlist_create(NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Member Name Data Type Comments
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ----------- --------- -----------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * version uint8 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * class string "asic"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENA uint64 ENA Format 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detector fmri aggregated ID data for SC-DE
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Datapath ereport subclasses and data payloads:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There will be two types of ereports (error and fault) which will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * identified by the "type" member.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ereport.asic.starcat.cds.cds-dp
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ereport.asic.starcat.dx.dx-dp
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ereport.asic.starcat.sdi.sdi-dp
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ereport.asic.starcat.cp.cp-dp
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Member Name Data Type Comments
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ----------- --------- -----------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * erptype uint16 derived from message type: error or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fault
03831d35f7499c87d51205817c93e9a8d42c4baestevel * t-value uint32 SC's datapath SERD timeout threshold
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dp-list-sz uint8 number of dp-list array elements
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dp-list array of uint16 Safari IDs of affected cpus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sn-list array of uint64 Serial numbers of affected cpus
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* compose common ereport elements */
03831d35f7499c87d51205817c93e9a8d42c4baestevel detector = fm_nvlist_create(NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create legacy FMRI for the detector
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (dpmsg->type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CDS_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_DX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot == 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "IO%d", exp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "SB%d", exp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_EX_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "EX%d", exp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DP_CP_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "CP");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "UNKNOWN");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hcelem = fm_nvlist_create(NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_string(hcelem, FM_FMRI_HC_NAME, FM_FMRI_LEGACY_HC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_string(hcelem, FM_FMRI_HC_ID, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_uint8(detector, FM_VERSION, FM_HC_SCHEME_VERSION);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_string(detector, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_string(detector, FM_FMRI_HC_ROOT, "");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_uint32(detector, FM_FMRI_HC_LIST_SZ, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nvlist_add_nvlist_array(detector, FM_FMRI_HC_LIST, &hcelem, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* build ereport class name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(buf, FM_MAX_CLASS, "asic.starcat.%s.%s-%s",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki dperrtype[dpmsg->type], dperrtype[dpmsg->type],
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki FM_ERROR_DATAPATH);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_ereport_set(erp, FM_EREPORT_VERSION, buf,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki fm_ena_generate(0, FM_ENA_FMT1), detector, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* add payload elements */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgtype == SCDM_DP_ERROR_MSG) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_payload_set(erp,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DP_EREPORT_TYPE, DATA_TYPE_UINT16, DP_ERROR, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_payload_set(erp,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DP_EREPORT_TYPE, DATA_TYPE_UINT16, DP_FAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_payload_set(erp, DP_TVALUE, DATA_TYPE_UINT32, dpmsg->t_value, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dp_payload_add_cpus(dpmsg, erp, maxcat) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* post ereport */
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_ereport_post(erp, EVCH_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* free ereport memory */
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_nvlist_destroy(erp, FM_NVA_FREE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fm_nvlist_destroy(detector, FM_NVA_FREE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_process_input() - incoming message processing routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this routine attempts to read a message from the SCDM mailbox and, if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * successful, processes the command. if an unrecoverable error is encountered,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the scosmb_task thread will be terminated.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscosmb_process_input(void *unused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_msgdata_t msg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_t *initpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_capability_data_t *cap; /* capability msg contents ptr */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cap_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cap_ver_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_msgdata_t *cap_msgdatap; /* capability msg response */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int max_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to read a message from the SCDM mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Setup a local buffer to read incoming messages from the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_ver_len = strlen(utsname.release) + strlen(utsname.version) + 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_size = sizeof (plat_capability_data_t) + cap_ver_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_size = MAX(cap_size, sizeof (plat_dimm_sid_board_data_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.type = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.cmd = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.length = max_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.data = kmem_zalloc(max_size, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_getmsg(SCDM_KEY, &msg.type, &msg.cmd, &msg.transid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &msg.length, msg.data, GETMSG_TIMEOUT_MS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If EAGAIN or ETIMEDOUT was received, give up. The SC can just try
03831d35f7499c87d51205817c93e9a8d42c4baestevel * again if it was important. If any other non-zero error was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * encountered, the mailbox service is broken, and there's nothing more
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we can do.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == EAGAIN) || (error == ETIMEDOUT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mailbox service appears to be badly broken. If it was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * working previously, generate a warning and set a flag to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * avoid repeating the warning on subsequent failures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scosmb_mboxsc_failed) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_mboxsc_failed = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s mboxsc error (0x%x)\n", scosmb_hdr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the mailbox module failed previously, it appears to have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * recovered, so we'll want to generate a warning if it fails
03831d35f7499c87d51205817c93e9a8d42c4baestevel * again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_mboxsc_failed = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A message was successfully received, so go ahead and process it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msg.cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_GOTO_OBP: /* jump to OBP */
03831d35f7499c87d51205817c93e9a8d42c4baestevel debug_enter("SC requested jump to OBP");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_GOTO_PANIC: /* Panic the domain */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_PANIC, "%s SC requested PANIC\n", scosmb_hdr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_SHUTDOWN: /* graceful shutdown */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s SC requested a shutdown ", scosmb_hdr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) kadmin(A_SHUTDOWN, AD_HALT, NULL, kcred);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the event kadmin does not bring down the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domain, environmental shutdown is forced
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_ENVIRON: /* environmental shutdown */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send SIGPWR to init(1) it will run rc0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which will uadmin to power down.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&pidlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel initpp = prfind(P_INITPID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&pidlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're still booting and init(1) isn't set up yet,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * simply halt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (initpp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void halt(char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s Environmental Interrupt",
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_hdr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel power_down((char *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel halt("Power off the System!\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * else, graceful shutdown with inittab and all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * getting involved
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel psignal(initpp, SIGPWR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_GET_NODENAME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_update_nodename(msg.transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_LOG_ECC_CAP_RESP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SC has responded to our initiator capability message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * issued during the boot flow via scosmb_update_nodename().
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Parse the incoming data, and appropriately set SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * capabilities...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap = (plat_capability_data_t *)msg.data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_ecc_capability_sc_set(cap->capd_capability);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_LOG_ECC_CAP_INIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SC has initiated a capability messaging exchange with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the OS.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We start out just as we do for an SC response capability
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message, a parse of incoming data to appropriately set SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * described capabilities...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap = (plat_capability_data_t *)msg.data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_ecc_capability_sc_set(cap->capd_capability);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The next step is setting up our Response to the SC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate memory for message data, initialize appropriately,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and place a new job on the scosmb_output_taskq for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCDM_LOG_ECC_CAP_RESP, our OS capability messaging response
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the SC initiated sequence detected here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap = kmem_zalloc(sizeof (scosmb_msgdata_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->type = MBOXSC_MSG_EVENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->cmd = SCDM_LOG_ECC_CAP_RESP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) taskq_dispatch(scosmb_output_taskq,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (task_func_t *)scosmb_process_output, cap_msgdatap,
03831d35f7499c87d51205817c93e9a8d42c4baestevel KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_DP_ERROR_MSG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_DP_FAULT_MSG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_trans_event(msg.data, msg.cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_DIMM_SERIAL_ID:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) plat_store_mem_sids(msg.data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s invalid command (0x%x)\n", scosmb_hdr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free up buffer for incoming messasge data that we allocated earlier
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(msg.data, max_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_process_output() - outgoing message processing routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine handles jobs that are queued on the scosmb_output_taskq, or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sent directly from scosmb_log_ecc_error. Each job corresponds to a single
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mailbox message that needs to be sent to the SC via the DMSC mailbox. Some
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing of the message may be performed before it is sent to the SC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * depending on the value of the command field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscosmb_process_output(scosmb_msgdata_t *msgdatap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char nodename[_SYS_NMLN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *free_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int free_data_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cap_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cap_ver_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_capability_data_t *cap = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This shouldn't ever happen, but it can't hurt to check anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgdatap == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If data was passed in, we'll need to free it before returning.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_data = msgdatap->data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_data_len = msgdatap->length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Some commands may need additional processing prior to transmission.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msgdatap->cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since the SC is only interested in the most recent value of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * utsname.nodename, we wait until now to collect that data. We
03831d35f7499c87d51205817c93e9a8d42c4baestevel * also use a global flag to prevent multiple event-type
03831d35f7499c87d51205817c93e9a8d42c4baestevel * nodename messages from being queued at the same time for the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * same reason.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_GET_NODENAME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel length = strlen(utsname.nodename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(length < _SYS_NMLN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (length == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->length = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->data = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(utsname.nodename, nodename, length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodename[length++] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->data = nodename;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->length = length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgdatap->transid == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_nodename_event_pending = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCDM_LOG_ECC_CAP_INIT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initiator Capability message from OS to SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We construct and send an initiator capability message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * every time we go through scosmb_update_nodename(), which
03831d35f7499c87d51205817c93e9a8d42c4baestevel * works out to getting an "initiator" capability message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sent from the OS to the SC during the OS boot flow.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SC also issues a request to scosmb_update_nodename()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * during an SC reboot. Which results in an additional
03831d35f7499c87d51205817c93e9a8d42c4baestevel * capability message exchange during SC reboot scenarios.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCDM_LOG_ECC_CAP_RESP
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Response Capability message from SC to OS
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In certain scenarios, the SC could initiate a capability
03831d35f7499c87d51205817c93e9a8d42c4baestevel * messaging exchange with the OS. Processing starts in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_process_input(), where we detect an incoming
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initiator capability message from the SC. We finish
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing here, by sending a response capability message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * back to the SC that reflects OS capabilities.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_LOG_ECC_CAP_INIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCDM_LOG_ECC_CAP_RESP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_ver_len = strlen(utsname.release) +
03831d35f7499c87d51205817c93e9a8d42c4baestevel strlen(utsname.version) + 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_size = sizeof (plat_capability_data_t) +
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_ver_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap = kmem_zalloc(cap_size, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap->capd_major_version = PLAT_ECC_CAP_VERSION_MAJOR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap->capd_minor_version = PLAT_ECC_CAP_VERSION_MINOR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap->capd_msg_type = PLAT_ECC_CAPABILITY_MESSAGE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap->capd_msg_length = cap_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap->capd_capability =
03831d35f7499c87d51205817c93e9a8d42c4baestevel PLAT_ECC_CAPABILITY_DOMAIN_DEFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build the capability solaris_version string:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * utsname.release + " " + utsname.version
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(cap->capd_solaris_version,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_ver_len, "%s %s", utsname.release,
03831d35f7499c87d51205817c93e9a8d42c4baestevel utsname.version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The capability message is constructed, now plug it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * into the starcat msgdatap:
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->data = (plat_capability_data_t *)cap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->length = cap_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Finished with initiator/response capability
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message set up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that after sending an "initiator" capability
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message, we can expect a subsequent "response"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * capability message from the SC, which we will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pick up and minimally handle later,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in scosmb_process_input().
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're sending a "response" capability message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the SC, then we're done once the message is sent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgdatap->transid == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_nodename_event_pending = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to send the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_putmsg(DMSC_KEY, msgdatap->type, msgdatap->cmd,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &msgdatap->transid, msgdatap->length, msgdatap->data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ecc_message_timeout_ms);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free any allocated memory that was passed in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (free_data != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(free_data, free_data_len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cap != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(cap, cap_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(msgdatap, sizeof (scosmb_msgdata_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If EAGAIN or ETIMEDOUT was received, give up. The sender can try
03831d35f7499c87d51205817c93e9a8d42c4baestevel * again if it was important. If any other non-zero error was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * encountered, the mailbox service is broken, and there's nothing more
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we can do.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == EAGAIN) || (error == ETIMEDOUT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgdatap->log_error && !scosmb_mboxsc_timedout) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Indictment mailbox messages use the return value to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * indicate a problem in the mailbox. For Error
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mailbox messages, we'll have to use a syslog message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_mboxsc_timedout = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!Solaris failed to send a message "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "(0x%x/0x%x) to the System Controller. Error: %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->type, msgdatap->cmd, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mailbox service appears to be badly broken. If it was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * working previously, generate a warning and set a flag to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * avoid repeating the warning on subsequent failures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgdatap->log_error && !scosmb_mboxsc_failed) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_mboxsc_failed = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!An internal error (%d) occurred "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "while processing this message (0x%x/0x%x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error, msgdatap->type, msgdatap->cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the mailbox module failed previously, it appears to have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * recovered, so we'll want to generate a warning if it fails
03831d35f7499c87d51205817c93e9a8d42c4baestevel * again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_mboxsc_failed = scosmb_mboxsc_timedout = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_update_nodename() - nodename update routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this routine, which may be invoked from outside of the scosmb module, will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cause the current nodename to be sent to the SC. The mailbox message sent to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SC will use the indicated transaction ID, and will either be a reply
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message if the ID is non-zero or an event message if it is 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Capability messaging enhancements:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Every time we move through this code flow, we put an "initiator
03831d35f7499c87d51205817c93e9a8d42c4baestevel * capability message" on the message output taskq. This action will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get a capability message sent to the SC from the OS during boot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scenarios. A capability message exchange will also happen for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC reboot scenarios, as the SC will initiate a nodename update
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as a matter of course while coming back up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We'll also get an extraneous capability message sent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the SC from time to time, but that won't hurt anything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelscosmb_update_nodename(uint64_t transid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_msgdata_t *msgdatap, *cap_msgdatap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're generating an unsolicited nodename update (presumably having
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been called from platmod:plat_nodename_set()), there's no need to add
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a new job to the queue if there is already one on it that will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sending the latest nodename data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (transid == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scosmb_nodename_event_pending) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_nodename_event_pending = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scosmb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate memory for the message data, initialize it, and place a new
03831d35f7499c87d51205817c93e9a8d42c4baestevel * job on the scosmb_output_taskq for SCDM_GET_NODENAME.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap = (scosmb_msgdata_t *)kmem_zalloc(sizeof (scosmb_msgdata_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->type = (transid == 0) ? MBOXSC_MSG_EVENT : MBOXSC_MSG_REPLY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->cmd = SCDM_GET_NODENAME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->transid = transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgdatap->log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) taskq_dispatch(scosmb_output_taskq,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (task_func_t *)scosmb_process_output, msgdatap, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Next, allocate memory, initialize, and place a new job on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_output_taskq for SCDM_LOG_ECC_CAP_INIT. That's a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * capability message, where we're the initiator.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap = kmem_zalloc(sizeof (scosmb_msgdata_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->type = (transid == 0) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_MSG_EVENT : MBOXSC_MSG_REPLY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->cmd = SCDM_LOG_ECC_CAP_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->transid = transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cap_msgdatap->log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) taskq_dispatch(scosmb_output_taskq,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (task_func_t *)scosmb_process_output, cap_msgdatap, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scosmb_log_ecc_error() - Record ECC error information to SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For ECC error messages, send the messages through a taskq mechanism
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to prevent impaired system performance during ECC floods. Indictment
03831d35f7499c87d51205817c93e9a8d42c4baestevel * messages have already passed through a taskq, so directly call the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * output function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscosmb_log_ecc_error(plat_ecc_message_type_t msg_type, void *datap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scosmb_msgdata_t *msg_header_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t msg_cmd, msg_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int sleep_flag, log_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int do_queue; /* Set to 1 if taskq needed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set header type and length for message
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msg_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We do not want to sleep in an error logging thread. So,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we set the NOSLEEP flag and go through a taskq before we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_cmd = SCDM_LOG_ECC_ERROR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_length = sizeof (plat_ecc_error_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_NOSLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do_queue = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_ERROR2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_cmd = SCDM_LOG_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_length = sizeof (plat_ecc_error2_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_NOSLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do_queue = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For indictment messages, we're allowed to sleep, and we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can directly call the output function, since we've already
03831d35f7499c87d51205817c93e9a8d42c4baestevel * gone through a taskq
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_cmd = SCDM_LOG_ECC_INDICTMENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_length = sizeof (plat_ecc_indictment_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do_queue = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_INDICTMENT2_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For indictment2 messages, we're allowed to sleep, and we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can directly call the output function, since we've already
03831d35f7499c87d51205817c93e9a8d42c4baestevel * gone through a taskq
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_cmd = SCDM_LOG_ECC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_length = sizeof (plat_ecc_indictment2_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do_queue = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PLAT_ECC_DIMM_SID_MESSAGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For DIMM sid request messages, we're allowed to sleep, and we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can directly call the output function, since we've already
03831d35f7499c87d51205817c93e9a8d42c4baestevel * gone through a taskq
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_cmd = SCDM_DIMM_SERIAL_ID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_length = sizeof (plat_dimm_sid_request_data_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag = KM_SLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel log_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do_queue = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate memory for the mailbox message header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr =
03831d35f7499c87d51205817c93e9a8d42c4baestevel (scosmb_msgdata_t *)kmem_zalloc(sizeof (scosmb_msgdata_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msg_header_ptr == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to allocate space for scosmb "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "message header.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->type = MBOXSC_MSG_EVENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->cmd = msg_cmd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->log_error = log_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate memory for the mailbox message payload.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->length = msg_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg_header_ptr->data = kmem_zalloc((size_t)msg_length, sleep_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msg_header_ptr->data == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to allocate space for scosmb "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "message data.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(msg_header_ptr, sizeof (scosmb_msgdata_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(datap, msg_header_ptr->data, (size_t)msg_length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Based on our earlier look at the message type, we either go through
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a taskq or directly call the output function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (do_queue != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Place a new job on the scosmb_output_taskq.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (taskq_dispatch(scosmb_output_taskq,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (task_func_t *)scosmb_process_output,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)msg_header_ptr, TQ_NOSLEEP) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to dispatch a task to send "
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "ECC mailbox message.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(msg_header_ptr->data, msg_header_ptr->length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(msg_header_ptr, sizeof (scosmb_msgdata_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (scosmb_process_output(msg_header_ptr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}