25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER START
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * or http://www.opensolaris.org/os/licensing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * See the License for the specific language governing permissions
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and limitations under the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When distributing Covered Code, include this CDDL HEADER in each
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If applicable, add the following below this CDDL HEADER, with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fields enclosed by brackets "[]" replaced with your own identifying
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information: Portions Copyright [yyyy] [name of copyright owner]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER END
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Use is subject to license terms.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/debug.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/types.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/varargs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/errno.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cred.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/dditypes.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/devops.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/modctl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/poll.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/conf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunddi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sunndi.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ndi_impldefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/stat.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/kmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/vmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/opl_olympus_regs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cpuvar.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cpupart.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/mem_config.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ddi_impldefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/systm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/machsystm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/autoconf.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cmn_err.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sysmacros.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/x_call.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/promif.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/prom_plat.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/membar.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <vm/seg_kmem.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/mem_cage.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/stack.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/archsystm.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <vm/hat_sfmmu.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/pte.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/mmu.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cpu_module.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/obpdefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/note.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/ontrap.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/cpu_sgnblk_defs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/opl.h>
e98fafb9956429b59c817d4fbd27720c73879203jl#include <sys/cpu_impl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/promimpl.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/prom_plat.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/kobj.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sysevent.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sysevent/dr.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/sysevent/eventdefs.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/drmach.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/dr_util.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/fcode.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#include <sys/opl_cfg.h>
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern void bcopy32_il(uint64_t, uint64_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern void flush_cache_il(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern void drmach_sleep_il(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_node *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *data;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_node_walk_args_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct drmach_node {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *here;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pnode_t (*get_dnode)(struct drmach_node *node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*walk)(struct drmach_node *node, void *data,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb)(drmach_node_walk_args_t *args));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *(*n_getdip)(struct drmach_node *node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*n_getproplen)(struct drmach_node *node, char *name,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int *len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*n_getprop)(struct drmach_node *node, char *name,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *buf, int len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*get_parent)(struct drmach_node *node,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_node *pnode);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_node_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int min_index;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int max_index;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int arr_sz;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t *arr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_array_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *isa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void (*dispose)(drmachid_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*release)(drmachid_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*status)(drmachid_t, drmach_status_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[MAXNAMELEN];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_common_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t core_present;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t core_hotadded;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t core_started;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_cmp_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_common_t cm;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int assigned;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int connected;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int cond;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *tree;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_t *devices;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int boot_board; /* if board exists on bootup */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cmp_t cores[OPL_MAX_COREID_PER_BOARD];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_board_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_common_t cm;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int unum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int busy;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl const char *type;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_device_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct drmach_cpu {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t dev;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl processorid_t cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int sb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int chipid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int coreid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int strandid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define OPL_CPU_HOTADDED 1
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_cpu_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct drmach_mem {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t dev;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t slice_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t base_pa; /* lowest installed memory base */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t nbytes; /* size of installed memory */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *memlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_mem_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct drmach_io {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t dev;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int channel;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int leaf;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_io_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct drmach_domain_info {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint32_t floating;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int allow_dr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_domain_info_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_domain_info_t drmach_domain;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int flags;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_config_args_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *obj;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int ndevs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void *a;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*found)(void *a, const char *, int, drmachid_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_board_cb_data_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_array_t *drmach_boards;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_device_new(drmach_node_t *,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *, int, drmachid_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_cpu_new(drmach_device_t *, drmachid_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_mem_new(drmach_device_t *, drmachid_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_io_new(drmach_device_t *, drmachid_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic dev_info_t *drmach_node_ddi_get_dip(drmach_node_t *np);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_node_ddi_get_prop(drmach_node_t *np,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name, void *buf, int len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_node_ddi_get_proplen(drmach_node_t *np,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name, int *len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_get_portid(drmach_node_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_i_status(drmachid_t, drmach_status_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int opl_check_dr_status();
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void drmach_io_dispose(drmachid_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_io_release(drmachid_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *drmach_io_status(drmachid_t, drmach_status_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_init(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void drmach_fini(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void drmach_swap_pa(drmach_mem_t *, drmach_mem_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_board_t *drmach_get_board_by_bnum(int);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_board_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_board_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void drmach_cpu_dispose(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_cpu_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_cpu_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void drmach_mem_dispose(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_mem_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_mem_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* options for the second argument in drmach_add_remove_cpu() */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HOTADD_CPU 1
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define HOTREMOVE_CPU 2
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define ON_BOARD_CORE_NUM(x) (((uint_t)(x) / OPL_MAX_STRANDID_PER_CORE) & \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (OPL_MAX_COREID_PER_BOARD - 1))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern struct cpu *SIGBCPU;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_name2type_idx(char *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_board_t *drmach_board_new(int, int);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_PR if (drmach_debug) printf
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint drmach_debug = 1; /* set to non-zero to enable debug messages */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_PR _NOTE(CONSTANTCONDITION) if (0) printf
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif /* DEBUG */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_OBJ(id) ((drmach_common_t *)id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
ddf956352ca0c49668d26125f3ff6d6461809ca8bm#define DRMACH_NULL_ID(id) ((id) == 0)
ddf956352ca0c49668d26125f3ff6d6461809ca8bm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_BOARD_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_board_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_CPU_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_MEM_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_mem_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_IO_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_DEVICE_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IS_ID(id) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ((id != 0) && \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DRMACH_OBJ(id)->isa == (void *)drmach_board_new || \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_INTERNAL_ERROR() \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drerr_new(1, EOPL_INTERNAL, drmach_ie_fmt, __LINE__)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic char *drmach_ie_fmt = "drmach.c %d";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl const char *name;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl const char *type;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*new)(drmach_device_t *, drmachid_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_name2type[] = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "cpu", DRMACH_DEVTYPE_CPU, drmach_cpu_new },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "pseudo-mc", DRMACH_DEVTYPE_MEM, drmach_mem_new },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "pci", DRMACH_DEVTYPE_PCI, drmach_io_new },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* utility */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define MBYTE (1048576ull)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach autoconfiguration data structures and interfaces
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern struct mod_ops mod_miscops;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modlmisc modlmisc = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl &mod_miscops,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "OPL DR 1.1"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct modlinkage modlinkage = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl MODREV_1,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void *)&modlmisc,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl NULL
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic krwlock_t drmach_boards_rwlock;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef const char *fn_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_init(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((err = drmach_init()) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((err = mod_install(&modlinkage)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_fini();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_fini(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((err = mod_remove(&modlinkage)) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_fini();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jl_info(struct modinfo *modinfop)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (mod_info(&modlinkage, modinfop));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct drmach_mc_lookup {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip; /* rv - set if found */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define _ptob64(p) ((uint64_t)(p) << PAGESHIFT)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define _b64top(b) ((pgcnt_t)((b) >> PAGESHIFT))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_setup_mc_info(dev_info_t *dip, drmach_mem_t *mp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t memory_ranges[128];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_sb_t *hwd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl hwd_memory_t *pm;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (memory_ranges);
e98fafb9956429b59c817d4fbd27720c73879203jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
e98fafb9956429b59c817d4fbd27720c73879203jl "sb-mem-ranges", (caddr_t)&memory_ranges[0], &len) !=
e98fafb9956429b59c817d4fbd27720c73879203jl DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->slice_base = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->slice_size = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->slice_base = memory_ranges[0];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->slice_size = memory_ranges[1];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!mp->dev.bp->boot_board) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = opl_read_hwd(mp->dev.bp->bnum, NULL, NULL, NULL, &hwd);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pm = &hwd->sb_cmu.cmu_memory;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < HWD_MAX_MEM_CHUNKS; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pm->mem_chunks[i].chnk_size > 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = memlist_add_span(ml,
e98fafb9956429b59c817d4fbd27720c73879203jl pm->mem_chunks[i].chnk_start_address,
e98fafb9956429b59c817d4fbd27720c73879203jl pm->mem_chunks[i].chnk_size);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we intersect phys_install to get base_pa.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This only works at bootup time.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_lock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = memlist_dup(phys_install);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_unlock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = memlist_del_span(ml, 0ull, mp->slice_base);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ml) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t basepa, endpa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl endpa = _ptob64(physmax + 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl basepa = mp->slice_base + mp->slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = memlist_del_span(ml, basepa, endpa - basepa);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ml) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t nbytes = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *p;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (p = ml; p; p = p->ml_next) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes += p->ml_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((mp->nbytes = nbytes) > 0)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mp->base_pa = ml->ml_address;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->base_pa = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->memlist = ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->base_pa = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->nbytes = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct drmach_hotcpu {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int core_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int option;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_cb(dev_info_t *dip, void *arg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_hotcpu *p = (struct drmach_hotcpu *)arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len = OBP_MAXDRVNAME;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum, core_id, strand_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (dip == ddi_root_node()) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "name",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)name, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* only cmp has board number */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, OBP_BOARDNUM,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)&bnum, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "cmp") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bnum != p->bnum)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* we have already pruned all unwanted cores and cpu's above */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "core") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "cpu") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl processorid_t cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "cpuid",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)&cpuid, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core_id = p->core_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = LSB_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ON_BOARD_CORE_NUM(cpuid) != core_id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = p->bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(bnum == bp->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (p->option == HOTADD_CPU) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prom_hotaddcpu(cpuid) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cores[core_id].core_hotadded |= (1 << strand_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (p->option == HOTREMOVE_CPU) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prom_hotremovecpu(cpuid) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cores[core_id].core_hotadded &= ~(1 << strand_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_add_remove_cpu(int bnum, int core_id, int option)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_hotcpu arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = drmach_get_board_by_bnum(bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.bp = bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.bnum = bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.core_id = core_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.option = option;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_walk_devs(ddi_root_node(), drmach_cpu_cb, (void *)&arg);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (arg.rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct drmach_setup_core_arg {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_setup_core_cb(dev_info_t *dip, void *arg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_setup_core_arg *p = (struct drmach_setup_core_arg *)arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len = OBP_MAXDRVNAME;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int core_id, strand_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (dip == ddi_root_node()) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "name",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)name, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* only cmp has board number */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, OBP_BOARDNUM,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)&bnum, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "cmp") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bnum != p->bp->bnum)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* we have already pruned all unwanted cores and cpu's above */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "core") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, "cpu") == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl processorid_t cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, "cpuid",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)&cpuid, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = LSB_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(bnum == p->bp->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl core_id = ON_BOARD_CORE_NUM(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->bp->cores[core_id].core_present |= (1 << strand_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_setup_core_info(drmach_board_t *obj)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_setup_core_arg arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < OPL_MAX_COREID_PER_BOARD; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->cores[i].core_present = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->cores[i].core_hotadded = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->cores[i].core_started = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.bp = obj;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_walk_devs(ddi_root_node(), drmach_setup_core_cb, (void *)&arg);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < OPL_MAX_COREID_PER_BOARD; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (obj->boot_board) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->cores[i].core_hotadded =
e98fafb9956429b59c817d4fbd27720c73879203jl obj->cores[i].core_started =
e98fafb9956429b59c817d4fbd27720c73879203jl obj->cores[i].core_present;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_node_* routines serve the purpose of separating the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * rest of the code from the device tree and OBP. This is necessary
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * because of In-Kernel-Probing. Devices probed after stod, are probed
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * by the in-kernel-prober, not OBP. These devices, therefore, do not
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * have dnode ids.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jltypedef struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_walk_args_t *nwargs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb)(drmach_node_walk_args_t *args);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_node_ddi_walk_args_t;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_walk_cb(dev_info_t *dip, void *arg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_ddi_walk_args_t *nargs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs = (drmach_node_ddi_walk_args_t *)arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * dip doesn't have to be held here as we are called
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * from ddi_walk_devs() which holds the dip.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs->nwargs->node->here = (void *)dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs->err = nargs->cb(nargs->nwargs);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Set "here" to NULL so that unheld dip is not accessible
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * outside ddi_walk_devs()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs->nwargs->node->here = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (nargs->err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_walk(drmach_node_t *np, void *data,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb)(drmach_node_walk_args_t *args))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_walk_args_t args;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_ddi_walk_args_t nargs;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* initialized args structure for callback */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl args.node = np;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl args.data = data;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs.nwargs = &args;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs.cb = cb;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nargs.err = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Root node doesn't have to be held in any way.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
e98fafb9956429b59c817d4fbd27720c73879203jl ddi_walk_devs(ddi_root_node(), drmach_node_ddi_walk_cb, (void *)&nargs);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (nargs.err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_get_parent(drmach_node_t *np, drmach_node_t *pp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *ndip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl static char *fn = "drmach_node_ddi_get_parent";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndip = np->n_getdip(np);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndip == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s: NULL dip", fn);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy(np, pp, sizeof (drmach_node_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pp->here = (void *)ddi_get_parent(ndip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pp->here == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s: NULL parent dip", fn);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pnode_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_get_dnode(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((pnode_t)NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_node_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_new(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *np;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np = kmem_zalloc(sizeof (drmach_node_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->get_dnode = drmach_node_ddi_get_dnode;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->walk = drmach_node_ddi_walk;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->n_getdip = drmach_node_ddi_get_dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->n_getproplen = drmach_node_ddi_get_proplen;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->n_getprop = drmach_node_ddi_get_prop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np->get_parent = drmach_node_ddi_get_parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (np);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_dispose(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(np, sizeof (*np));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic dev_info_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_get_dip(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((dev_info_t *)np->here);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_walk(drmach_node_t *np, void *param,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*cb)(drmach_node_walk_args_t *args))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (np->walk(np, param, cb));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_get_prop(drmach_node_t *np, char *name, void *buf, int len)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *ndip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl static char *fn = "drmach_node_ddi_get_prop";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndip = np->n_getdip(np);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndip == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "%s: NULL dip", fn);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ndip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DDI_PROP_DONTPASS, name,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)buf, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_ddi_get_proplen(drmach_node_t *np, char *name, int *len)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *ndip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndip = np->n_getdip(np);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ndip == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
e98fafb9956429b59c817d4fbd27720c73879203jl } else if (ddi_getproplen(DDI_DEV_T_ANY, ndip, DDI_PROP_DONTPASS, name,
e98fafb9956429b59c817d4fbd27720c73879203jl len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmachid_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_dup(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *dup;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup = drmach_node_new();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->here = np->here;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->get_dnode = np->get_dnode;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->walk = np->walk;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->n_getdip = np->n_getdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->n_getproplen = np->n_getproplen;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->n_getprop = np->n_getprop;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dup->get_parent = np->get_parent;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (dup);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_array provides convenient array construction, access,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bounds checking and array destruction logic.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_array_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_new(int min_index, int max_index)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_t *arr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr = kmem_zalloc(sizeof (drmach_array_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr->arr_sz = (max_index - min_index + 1) * sizeof (void *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (arr->arr_sz > 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr->min_index = min_index;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr->max_index = max_index;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr->arr = kmem_zalloc(arr->arr_sz, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (arr);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(arr, sizeof (*arr));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_set(drmach_array_t *arr, int idx, drmachid_t val)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (idx < arr->min_index || idx > arr->max_index)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arr->arr[idx - arr->min_index] = val;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*NOTREACHED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_get(drmach_array_t *arr, int idx, drmachid_t *val)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (idx < arr->min_index || idx > arr->max_index)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *val = arr->arr[idx - arr->min_index];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*NOTREACHED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_first(drmach_array_t *arr, int *idx, drmachid_t *val)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idx = arr->min_index;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idx += 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_next(drmach_array_t *arr, int *idx, drmachid_t *val)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idx += 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idx += 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_array_dispose(drmach_array_t *arr, void (*disposer)(drmachid_t))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t val;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int idx;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_array_first(arr, &idx, &val);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (rv == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (*disposer)(val);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_array_next(arr, &idx, &val);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(arr->arr, arr->arr_sz);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(arr, sizeof (*arr));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_board_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_get_board_by_bnum(int bnum)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_array_get(drmach_boards, bnum, &id) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((drmach_board_t *)id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic pnode_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_node_get_dnode(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (np->get_dnode(np));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_configure(drmachid_t id, int flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *rdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *fdip = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (DRMACH_IS_CPU_ID(id)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_DEVICE_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rdip = dp->node->n_getdip(dp->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(e_ddi_branch_held(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e_ddi_branch_configure(rdip, &fdip, 0) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip = (fdip != NULL) ? fdip : rdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ddi_pathname(dip, path);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(1, EOPL_DRVFAIL, path);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(path, MAXPATHLEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* If non-NULL, fdip is returned held and must be released */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fdip != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_release_devi(fdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_device_new(drmach_node_t *node,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp, int portid, drmachid_t *idp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t proto;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* every node is expected to have a name */
e98fafb9956429b59c817d4fbd27720c73879203jl err = drerr_new(1, EOPL_GETPROP, "device node %s: property %s",
e98fafb9956429b59c817d4fbd27720c73879203jl ddi_node_name(node->n_getdip(node)), "name");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The node currently being examined is not listed in the name2type[]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * array. In this case, the node is no interest to drmach. Both
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * dp and err are initialized here to yield nothing (no device or
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * error structure) for this case.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i = drmach_name2type_idx(name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (i < 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idp = (drmachid_t)0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* device specific new function will set unum */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bzero(&proto, sizeof (proto));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto.type = drmach_name2type[i].type;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto.bp = bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto.node = node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto.portid = portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drmach_name2type[i].new(&proto, idp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_device_dispose(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *self = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl self->cm.dispose(id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic drmach_board_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_new(int bnum, int boot_board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = kmem_zalloc(sizeof (drmach_board_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cm.isa = (void *)drmach_board_new;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cm.release = drmach_board_release;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cm.status = drmach_board_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) drmach_board_name(bnum, bp->cm.name, sizeof (bp->cm.name));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->bnum = bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->devices = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->connected = boot_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->tree = drmach_node_new();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->assigned = boot_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->powered = boot_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->boot_board = boot_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If this is not bootup initialization, we have to wait till
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IKP sets up the device nodes in drmach_board_connect().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (boot_board)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_setup_core_info(bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) drmach_array_set(drmach_boards, bnum, bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_dispose(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_BOARD_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->tree)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_dispose(bp->tree);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->devices)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_dispose(bp->devices, drmach_device_dispose);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(bp, sizeof (*bp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->assigned = bp->assigned;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->powered = bp->powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->busy = 0; /* assume not busy */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->configured = 0; /* assume not configured */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->empty = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->cond = bp->cond = SBD_COND_OK;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, "System Brd", sizeof (stat->type));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->info[0] = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->devices) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int d_idx;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t d_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_array_first(bp->devices, &d_idx, &d_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (rv == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_status_t d_stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drmach_i_status(d_id, &d_stat);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->busy |= d_stat.busy;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->configured |= d_stat.configured;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_array_next(bp->devices, &d_idx, &d_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_is_floating(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return ((drmach_domain.floating & (1 << bp->bnum)) ? 1 : 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_init(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *rdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, rv, len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int *floating;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_init(&drmach_boards_rwlock, NULL, RW_DEFAULT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_boards = drmach_array_new(0, MAX_BOARDS - 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rdip = ddi_root_node();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ddi_getproplen(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
e98fafb9956429b59c817d4fbd27720c73879203jl "floating-boards", &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "Cannot get floating-boards proplen\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl floating = (int *)kmem_alloc(len, KM_SLEEP);
e98fafb9956429b59c817d4fbd27720c73879203jl rv = ddi_prop_op(DDI_DEV_T_ANY, rdip, PROP_LEN_AND_VAL_BUF,
e98fafb9956429b59c817d4fbd27720c73879203jl DDI_PROP_DONTPASS, "floating-boards", (caddr_t)floating,
e98fafb9956429b59c817d4fbd27720c73879203jl &len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "Cannot get floating-boards prop\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_domain.floating = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < len / sizeof (int); i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_domain.floating |= (1 << floating[i]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(floating, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_domain.allow_dr = opl_check_dr_status();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rdip = ddi_get_child(ddi_root_node());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl do {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = -1;
e98fafb9956429b59c817d4fbd27720c73879203jl bnum = ddi_getprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
e98fafb9956429b59c817d4fbd27720c73879203jl OBP_BOARDNUM, -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bnum == -1)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_array_get(drmach_boards, bnum, &id) == -1) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "Device node 0x%p has invalid "
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "property value, %s=%d", (void *)rdip,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki OBP_BOARDNUM, bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto error;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (id == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) drmach_board_new(bnum, 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } while ((rdip = ddi_get_next_sibling(rdip)) != NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_hold_devtree();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize the IKP feature.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This can be done only after DR has acquired a hold on all the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * device nodes that are interesting to IKP.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (opl_init_cfg() != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "DR - IKP initialization failed");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_release_devtree();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto error;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jlerror:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_dispose(drmach_boards, drmach_board_dispose);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_destroy(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (ENXIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_fini(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_enter(&drmach_boards_rwlock, RW_WRITER);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_dispose(drmach_boards, drmach_board_dispose);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_boards = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Walk immediate children of the root devinfo node
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * releasing holds acquired on branches in drmach_init()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl opl_release_devtree();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_destroy(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each system board contains 2 Oberon PCI bridge and
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 1 CMUCH.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each oberon has 2 channels.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each channel has 2 pci-ex leaf.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each CMUCH has 1 pci bus.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Device Path:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * /pci@<portid>,reg
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * where
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * portid[10] = 0
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * portid[9:0] = LLEAF_ID[9:0] of the Oberon Channel
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * LLEAF_ID[9:8] = 0
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * LLEAF_ID[8:4] = LSB_ID[4:0]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * LLEAF_ID[3:1] = IO Channel#[2:0] (0,1,2,3 for Oberon)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * channel 4 is pcicmu
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * LLEAF_ID[0] = PCI Leaf Number (0 for leaf-A, 1 for leaf-B)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Properties:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * name = pci
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * device_type = "pciex"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * board# = LSBID
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * reg = int32 * 2, Oberon CSR space of the leaf and the UBC space
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * portid = Jupiter Bus Device ID ((LSB_ID << 3)|pciport#)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_new(drmach_device_t *proto, drmachid_t *idp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_io_t *ip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = proto->portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(portid != -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto->unum = portid & (MAX_IO_UNITS_PER_BOARD - 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip = kmem_zalloc(sizeof (drmach_io_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy(proto, &ip->dev, sizeof (ip->dev));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->dev.node = drmach_node_dup(proto->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->dev.cm.isa = (void *)drmach_io_new;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->dev.cm.dispose = drmach_io_dispose;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->dev.cm.release = drmach_io_release;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->dev.cm.status = drmach_io_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->channel = (portid >> 1) & 0x7;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ip->leaf = (portid & 0x1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(ip->dev.cm.name, sizeof (ip->dev.cm.name), "%s%d",
e98fafb9956429b59c817d4fbd27720c73879203jl ip->dev.type, ip->dev.unum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idp = (drmachid_t)ip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_dispose(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_io_t *self;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_IO_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl self = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (self->dev.node)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_dispose(self->dev.node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(self, sizeof (*self));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_pre_op(int cmd, drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* allow status and ncm operations to always succeed */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((cmd == SBD_CMD_STATUS) || (cmd == SBD_CMD_GETNCM)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* check all other commands for the required option string */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((opts->size > 0) && (opts->copts != NULL)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("platform options: %s\n", opts->copts);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strstr(opts->copts, "opldr") == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(1, EOPL_SUPPORT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(1, EOPL_SUPPORT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!err && id && DRMACH_IS_BOARD_ID(id)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case SBD_CMD_TEST:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case SBD_CMD_STATUS:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case SBD_CMD_GETNCM:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case SBD_CMD_CONNECT:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->connected)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(0, ESBD_STATE, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (!drmach_domain.allow_dr)
e98fafb9956429b59c817d4fbd27720c73879203jl err = drerr_new(1, EOPL_SUPPORT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl case SBD_CMD_DISCONNECT:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!bp->connected)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(0, ESBD_STATE, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (!drmach_domain.allow_dr)
e98fafb9956429b59c817d4fbd27720c73879203jl err = drerr_new(1, EOPL_SUPPORT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl default:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!drmach_domain.allow_dr)
e98fafb9956429b59c817d4fbd27720c73879203jl err = drerr_new(1, EOPL_SUPPORT, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_post_op(int cmd, drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_assign(int bnum, drmachid_t *id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_enter(&drmach_boards_rwlock, RW_WRITER);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_array_get(drmach_boards, bnum, id) == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(1, EOPL_BNUM, "%d", bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (*id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_downgrade(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = *id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!(*id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = *id =
e98fafb9956429b59c817d4fbd27720c73879203jl (drmachid_t)drmach_board_new(bnum, 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->assigned = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_connect(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
e98fafb9956429b59c817d4fbd27720c73879203jl extern int cpu_alljupiter;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *obj = (drmach_board_t *)id;
e98fafb9956429b59c817d4fbd27720c73879203jl unsigned cpu_impl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl if (opl_probe_sb(obj->bnum, &cpu_impl) != 0)
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_PROBE, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl if (cpu_alljupiter) {
8a040953a18c6073d14e66681d8823d3fd7bce15wh if (cpu_impl & (1 << OLYMPUS_C_IMPL)) {
8a040953a18c6073d14e66681d8823d3fd7bce15wh (void) opl_unprobe_sb(obj->bnum);
e98fafb9956429b59c817d4fbd27720c73879203jl return (drerr_new(1, EOPL_MIXED_CPU, NULL));
8a040953a18c6073d14e66681d8823d3fd7bce15wh }
e98fafb9956429b59c817d4fbd27720c73879203jl }
e98fafb9956429b59c817d4fbd27720c73879203jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) prom_attach_notice(obj->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_setup_core_info(obj);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->connected = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int drmach_cache_flush_flag[NCPU];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_flush_cache(uint64_t id, uint64_t dummy)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void cpu_flush_ecache(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu_flush_ecache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cache_flush_flag[id] = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_flush_all()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuset_t xc_cpuset;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl xc_cpuset = cpu_ready_set;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(xc_cpuset, i)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cache_flush_flag[i] = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl xc_one(i, drmach_flush_cache, i, 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (drmach_cache_flush_flag[i]) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DELAY(1000);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_disconnect_cpus(drmach_board_t *bp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i, bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = bp->bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < OPL_MAX_COREID_PER_BOARD; i++) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (bp->cores[i].core_present) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (bp->cores[i].core_started)
e98fafb9956429b59c817d4fbd27720c73879203jl return (-1);
e98fafb9956429b59c817d4fbd27720c73879203jl if (bp->cores[i].core_hotadded) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (drmach_add_remove_cpu(bnum, i,
e98fafb9956429b59c817d4fbd27720c73879203jl HOTREMOVE_CPU)) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "Failed to remove "
e98fafb9956429b59c817d4fbd27720c73879203jl "CMP %d on board %d\n", i, bnum);
e98fafb9956429b59c817d4fbd27720c73879203jl return (-1);
e98fafb9956429b59c817d4fbd27720c73879203jl }
e98fafb9956429b59c817d4fbd27720c73879203jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_disconnect(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *obj;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
ddf956352ca0c49668d26125f3ff6d6461809ca8bm if (DRMACH_NULL_ID(id))
ddf956352ca0c49668d26125f3ff6d6461809ca8bm return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_disconnect_cpus(obj)) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_DEPROBE, obj->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = opl_unprobe_sb(obj->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv == 0) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_detach_notice(obj->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl obj->connected = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_DEPROBE, obj->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_get_portid(drmach_node_t *np)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char type[OBP_MAXPROPNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (np->n_getprop(np, "portid", &portid, sizeof (portid)) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Get the device_type property to see if we should
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * continue processing this node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (np->n_getprop(np, "device_type", &type, sizeof (type)) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(type, OPL_CPU_NODE) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We return cpuid because it has no portid
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (np->n_getprop(np, "cpuid", &portid, sizeof (portid)) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (portid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This is a helper function to determine if a given
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * node should be considered for a dr operation according
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to predefined dr type nodes and the node's name.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Formal Parameter : The name of a device node.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return Value: -1, name does not map to a valid dr type.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * A value greater or equal to 0, name is a valid dr type.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_name2type_idx(char *name)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int index, ntypes;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (name == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Determine how many possible types are currently supported
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for dr.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ntypes = sizeof (drmach_name2type) / sizeof (drmach_name2type[0]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Determine if the node's name correspond to a predefined type. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (index = 0; index < ntypes; index++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(drmach_name2type[index].name, name) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* The node is an allowed type for dr. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (index);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the name of the node does not map to any of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * types in the array drmach_name2type then the node is not of
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * interest to dr.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * there is some complication on OPL:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * - pseudo-mc nodes do not have portid property
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * - portid[9:5] of cmp node is LSB #, portid[7:3] of pci is LSB#
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * - cmp has board#
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * - core and cpu nodes do not have portid and board# properties
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * starcat uses portid to derive the board# but that does not work
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for us. starfire reads board# property to filter the devices.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * That does not work either. So for these specific device,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we use specific hard coded methods to get the board# -
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * cpu: LSB# = CPUID[9:5]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_find_devices_cb(drmach_node_walk_args_t *args)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *node = args->node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_cb_data_t *data = args->data;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *obj = data->obj;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv, portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmachid_t id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *device;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = drmach_get_portid(node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * core, cpu and pseudo-mc do not have portid
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we use cpuid as the portid of the cpu node
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for pseudo-mc, we do not use portid info.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = node->n_getprop(node, OBP_BOARDNUM, &bnum, sizeof (bnum));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * cpu does not have board# property. We use
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPUID[9:5]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp("cpu", name) == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = (portid >> 5) & 0x1f;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bnum != obj->bnum)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_name2type_idx(name) < 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Create a device data structure from this node data.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The call may yield nothing if the node is not of interest
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to drmach.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data->err = drmach_device_new(node, obj, portid, &id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (data->err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else if (!id) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_device_new examined the node we passed in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and determined that it was one not of interest to
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach. So, it is skipped.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_array_set(obj->devices, data->ndevs++, id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data->err = DRMACH_INTERNAL_ERROR();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl device = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data->err = (*data->found)(data->a, device->type, device->unum, id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (data->err == NULL ? 0 : -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_find_devices(drmachid_t id, void *a,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*found)(void *a, const char *, int, drmachid_t))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int max_devices;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_cb_data_t data;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl max_devices = MAX_CPU_UNITS_PER_BOARD;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl max_devices += MAX_MEM_UNITS_PER_BOARD;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl max_devices += MAX_IO_UNITS_PER_BOARD;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->devices = drmach_array_new(0, max_devices);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->tree == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->tree = drmach_node_new();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data.obj = bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data.ndevs = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data.found = found;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data.a = a;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl data.err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_node_walk(bp->tree, &data, drmach_board_find_devices_cb);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_dispose(bp->devices, drmach_device_dispose);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->devices = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (data.err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = data.err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = DRMACH_INTERNAL_ERROR();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_lookup(int bnum, drmachid_t *id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_enter(&drmach_boards_rwlock, RW_READER);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_array_get(drmach_boards, bnum, id)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *id = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_name(int bnum, char *buf, int buflen)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(buf, buflen, "SB%d", bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_poweroff(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_status_t stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
ddf956352ca0c49668d26125f3ff6d6461809ca8bm if (DRMACH_NULL_ID(id))
ddf956352ca0c49668d26125f3ff6d6461809ca8bm return (NULL);
ddf956352ca0c49668d26125f3ff6d6461809ca8bm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drmach_board_status(id, &stat);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!err) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (stat.configured || stat.busy)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(0, EOPL_CONFIGBUSY, bp->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->powered = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_poweron(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->powered = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_test(drmachid_t id, drmach_opts_t *opts, int force)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_unassign(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_status_t stat;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
ddf956352ca0c49668d26125f3ff6d6461809ca8bm if (DRMACH_NULL_ID(id))
ddf956352ca0c49668d26125f3ff6d6461809ca8bm return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_enter(&drmach_boards_rwlock, RW_WRITER);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drmach_board_status(id, &stat);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (stat.configured || stat.busy) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(0, EOPL_CONFIGBUSY, bp->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_array_set(drmach_boards, bp->bnum, 0) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = DRMACH_INTERNAL_ERROR();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_dispose(bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We have to do more on OPL - e.g. set up sram tte, read cpuid, strand id,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * implementation #, etc
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_new(drmach_device_t *proto, drmachid_t *idp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cpu_t *cp = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* portid is CPUID of the node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl portid = proto->portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(portid != -1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* unum = (CMP/CHIP ID) + (ON_BOARD_CORE_NUM * MAX_CMPID_PER_BOARD) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto->unum = ((portid/OPL_MAX_CPUID_PER_CMP) &
e98fafb9956429b59c817d4fbd27720c73879203jl (OPL_MAX_CMPID_PER_BOARD - 1)) +
e98fafb9956429b59c817d4fbd27720c73879203jl ((portid & (OPL_MAX_CPUID_PER_CMP - 1)) *
e98fafb9956429b59c817d4fbd27720c73879203jl (OPL_MAX_CMPID_PER_BOARD));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp = kmem_zalloc(sizeof (drmach_cpu_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy(proto, &cp->dev, sizeof (cp->dev));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->dev.node = drmach_node_dup(proto->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->dev.cm.isa = (void *)drmach_cpu_new;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->dev.cm.dispose = drmach_cpu_dispose;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->dev.cm.release = drmach_cpu_release;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->dev.cm.status = drmach_cpu_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(cp->dev.cm.name, sizeof (cp->dev.cm.name), "%s%d",
e98fafb9956429b59c817d4fbd27720c73879203jl cp->dev.type, cp->dev.unum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPU ID representation
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPUID[9:5] = SB#
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPUID[4:3] = Chip#
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPUID[2:1] = Core# (Only 2 core for OPL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CPUID[0:0] = Strand#
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * reg property of the strand contains strand ID
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * reg property of the parent node contains core ID
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We should use them.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->cpuid = portid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->sb = (portid >> 5) & 0x1f;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->chipid = (portid >> 3) & 0x3;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->coreid = (portid >> 1) & 0x3;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->strandid = portid & 0x1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *idp = (drmachid_t)cp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_dispose(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cpu_t *self;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_CPU_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl self = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (self->dev.node)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_dispose(self->dev.node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(self, sizeof (*self));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_start(struct cpu *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int cpuid = cp->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern int restart_other_cpu(int);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&cpu_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(cpunodes[cpuid].nodeid != (pnode_t)0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->cpu_flags &= ~CPU_POWEROFF;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * NOTE: restart_other_cpu pauses cpus during the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * slave cpu start. This helps to quiesce the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bus traffic a bit which makes the tick sync
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * routine in the prom more robust.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("COLD START for cpu (%d)\n", cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) restart_other_cpu(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_CPU_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cpu_t *cp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_CPU_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp = (drmach_cpu_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = &cp->dev;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->assigned = dp->bp->assigned;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->powered = dp->bp->powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_enter(&cpu_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->configured = (cpu_get(cp->cpuid) != NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_exit(&cpu_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->busy = dp->busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, dp->type, sizeof (stat->type));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->info[0] = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_disconnect(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_CPU_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_get_id(drmachid_t id, processorid_t *cpuid)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_cpu_t *cpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_CPU_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu = (drmach_cpu_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* get from cpu directly on OPL */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *cpuid = cpu->cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_get_impl(drmachid_t id, int *ip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *cpu;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t *np;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_t pp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int impl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char type[OBP_MAXPROPNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_CPU_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl np = cpu->node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (np->get_parent(np, &pp) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DRMACH_INTERNAL_ERROR());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* the parent should be core */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pp.n_getprop(&pp, "device_type", &type, sizeof (type)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_GETPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(type, OPL_CORE_NODE) == 0) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (pp.n_getprop(&pp, "implementation#", &impl,
e98fafb9956429b59c817d4fbd27720c73879203jl sizeof (impl)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_GETPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DRMACH_INTERNAL_ERROR());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *ip = impl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_get_dip(drmachid_t id, dev_info_t **dip)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_DEVICE_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *dip = dp->node->n_getdip(dp->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_is_attached(drmachid_t id, int *yes)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int state;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_IO_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = dp->node->n_getdip(dp->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (dip == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *yes = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl state = ddi_get_devstate(dip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *yes = ((i_ddi_node_state(dip) >= DS_ATTACHED) ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (state == DDI_DEVSTATE_UP));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstruct drmach_io_cb {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *name; /* name of the node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*func)(dev_info_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl dev_info_t *dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IO_POST_ATTACH 0
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DRMACH_IO_PRE_RELEASE 1
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_cb_check(dev_info_t *dip, void *arg)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_io_cb *p = (struct drmach_io_cb *)arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len = OBP_MAXDRVNAME;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "name",
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (caddr_t)name, &len) != DDI_PROP_SUCCESS) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_PRUNECHILD);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strcmp(name, p->name) == 0) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ndi_hold_devi(dip);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl p->dip = dip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DDI_WALK_CONTINUE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_console_ops(drmachid_t *id, int state)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_io_t *obj = (drmach_io_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct drmach_io_cb arg;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*msudetp)(dev_info_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*msuattp)(dev_info_t *);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip, *pdip;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int circ;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* 4 is pcicmu channel */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (obj->channel != 4)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.name = "serial";
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.func = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (state == DRMACH_IO_PRE_RELEASE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl msudetp = (int (*)(dev_info_t *))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("oplmsu_dr_detach", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (msudetp != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.func = msudetp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (state == DRMACH_IO_POST_ATTACH) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl msuattp = (int (*)(dev_info_t *))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("oplmsu_dr_attach", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (msuattp != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.func = msuattp;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (arg.func == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl arg.rv = 0;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl arg.dip = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = obj->dev.node->n_getdip(obj->dev.node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (pdip = ddi_get_parent(dip)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_hold_devi(pdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_devi_enter(pdip, &circ);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* this cannot happen unless something bad happens */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (-1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ddi_walk_devs(dip, drmach_io_cb_check, (void *)&arg);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ndi_devi_exit(pdip, circ);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ndi_rele_devi(pdip);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (arg.dip) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl arg.rv = (*arg.func)(arg.dip);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl ndi_rele_devi(arg.dip);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl } else {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl arg.rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (arg.rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_pre_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_IO_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_console_ops(id, DRMACH_IO_PRE_RELEASE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IO callback failed in pre-release\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_IO_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_unrelease(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_IO_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_post_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_post_attach(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_IO_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = drmach_console_ops(id, DRMACH_IO_POST_ATTACH);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "IO callback failed in post-attach\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_io_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int configured;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_IO_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drmach_io_is_attached(id, &configured);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (err)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->assigned = dp->bp->assigned;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->powered = dp->bp->powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->configured = (configured != 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->busy = dp->busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, dp->type, sizeof (stat->type));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->info[0] = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_new(drmach_device_t *proto, drmachid_t *idp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *dip;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl rv = 0;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if ((proto->node->n_getproplen(proto->node, "mc-addr", &rv) < 0) ||
e98fafb9956429b59c817d4fbd27720c73879203jl (rv <= 0)) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl *idp = (drmachid_t)0;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl return (NULL);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp = kmem_zalloc(sizeof (drmach_mem_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl proto->unum = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy(proto, &mp->dev, sizeof (mp->dev));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->dev.node = drmach_node_dup(proto->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->dev.cm.isa = (void *)drmach_mem_new;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->dev.cm.dispose = drmach_mem_dispose;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->dev.cm.release = drmach_mem_release;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->dev.cm.status = drmach_mem_status;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(mp->dev.cm.name, sizeof (mp->dev.cm.name), "%s",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki mp->dev.type);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dip = mp->dev.node->n_getdip(mp->dev.node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_setup_mc_info(dip, mp) != 0) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_MC_SETUP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /* make sure we do not create memoryless nodes */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (mp->nbytes == 0) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl *idp = (drmachid_t)NULL;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(mp, sizeof (drmach_mem_t));
68ac2337c38c8af06edcf32a72e42de36ec72a9djl } else
68ac2337c38c8af06edcf32a72e42de36ec72a9djl *idp = (drmachid_t)mp;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_dispose(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_MEM_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mp->dev.node)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_dispose(mp->dev.node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mp->memlist) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_delete(mp->memlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp->memlist = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(mp, sizeof (*mp));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_add_span(drmachid_t id, uint64_t basepa, uint64_t size)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(size != 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
85f5803819bea86c07827a9544494e4ad327d95ddp rv = kcage_range_add(basepfn, npages, KCAGE_DOWN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv == ENOMEM) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_WARN, "%lu megabytes not available to kernel cage",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (ulong_t)(size == 0 ? 0 : size / MBYTE));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else if (rv != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* catch this in debug kernels */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "unexpected kcage_range_add return value %d",
e98fafb9956429b59c817d4fbd27720c73879203jl rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DRMACH_INTERNAL_ERROR());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_del_span(drmachid_t id, uint64_t basepa, uint64_t size)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (size > 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = kcage_range_delete_post_mem_del(basepfn, npages);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "unexpected kcage_range_delete_post_mem_del"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl " return value %d", rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DRMACH_INTERNAL_ERROR());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_disable(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_flush_all();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_enable(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_get_info(drmachid_t id, drmach_mem_info_t *mem)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp = (drmach_mem_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This is only used by dr to round up/down the memory
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * for copying. Our unit of memory isolation is 64 MB.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mi_alignment_mask = (64 * 1024 * 1024 - 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mi_basepa = mp->base_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mi_size = mp->nbytes;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem->mi_slice_size = mp->slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_get_base_physaddr(drmachid_t id, uint64_t *pa)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp = (drmach_mem_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *pa = mp->base_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_get_memlist(drmachid_t id, struct memlist **ml)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mem;
b307f191031b69156225d50e36c406311441051abm#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
b307f191031b69156225d50e36c406311441051abm#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem = (drmach_mem_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mlist = memlist_dup(mem->memlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#ifdef DEBUG
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Make sure the incoming memlist doesn't already
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * intersect with what's present in the system (phys_install).
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_lock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = memlist_intersect(phys_install, mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_unlock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
e98fafb9956429b59c817d4fbd27720c73879203jl DRMACH_PR("Derived memlist intersects with phys_install\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_dump(mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("phys_install memlist:\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_dump(phys_install);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_delete(mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (DRMACH_INTERNAL_ERROR());
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("Derived memlist:");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_dump(mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#endif
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *ml = mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_get_slice_size(drmachid_t id, uint64_t *bytes)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mem = (drmach_mem_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *bytes = mem->slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlprocessorid_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_cpu_affinity(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (CPU_CURRENT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_mem_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t pa, slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(DRMACH_IS_MEM_ID(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* get starting physical address of target memory */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pa = dp->base_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* round down to slice boundary */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl slice_size = dp->slice_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pa &= ~(slice_size - 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* stop at first span that is in slice */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_lock();
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = phys_install; ml; ml = ml->ml_next)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams if (ml->ml_address >= pa && ml->ml_address < pa + slice_size)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_unlock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->assigned = dp->dev.bp->assigned;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->powered = dp->dev.bp->powered;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->configured = (ml != NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->busy = dp->dev.busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, dp->dev.type, sizeof (stat->type));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl stat->info[0] = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_board_deprobe(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl cmn_err(CE_CONT, "DR: detach board %d\n", bp->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->tree) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_node_dispose(bp->tree);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->tree = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->devices) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_array_dispose(bp->devices, drmach_device_dispose);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->devices = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->boot_board = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_pt_ikprobe(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
e98fafb9956429b59c817d4fbd27720c73879203jl unsigned cpu_impl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("calling opl_probe_board for bnum=%d\n", bp->bnum);
e98fafb9956429b59c817d4fbd27720c73879203jl rv = opl_probe_sb(bp->bnum, &cpu_impl);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_PROBE, bp->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_pt_ikdeprobe(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_BOARD_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = (drmach_board_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_CONT, "DR: in-kernel unprobe board %d\n", bp->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = opl_unprobe_sb(bp->bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv != 0) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_DEPROBE, bp->cm.name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_pt_readmem(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t src_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t dst_pa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t dst;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dst_pa = va_to_pa(&dst);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_lock();
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = phys_install; ml; ml = ml->ml_next) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t nbytes;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams src_pa = ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (nbytes != 0ull) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* copy 32 bytes at arc_pa to dst_pa */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy32_il(src_pa, dst_pa);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* increment by 32 bytes */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl src_pa += (4 * sizeof (uint64_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* decrement by 32 bytes */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nbytes -= (4 * sizeof (uint64_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_read_unlock();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl const char *name;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *(*handler)(drmachid_t id, drmach_opts_t *opts);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl} drmach_pt_arr[] = {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "readmem", drmach_pt_readmem },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "ikprobe", drmach_pt_ikprobe },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { "ikdeprobe", drmach_pt_ikdeprobe },
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* the following line must always be last */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { NULL, NULL }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl};
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_passthru(drmachid_t id, drmach_opts_t *opts)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (drmach_pt_arr[i].name != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int len = strlen(drmach_pt_arr[i].name);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (strncmp(drmach_pt_arr[i].name, opts->copts, len) == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl i += 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_pt_arr[i].name == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(0, EOPL_UNKPTCMD, opts->copts);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl else
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = (*drmach_pt_arr[i].handler)(id, opts);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_release(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_common_t *cp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_DEVICE_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (cp->release(id));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_common_t *cp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_enter(&drmach_boards_rwlock, RW_READER);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_ID(id)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_NOTID, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp = (drmach_common_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = cp->status(id, stat);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_exit(&drmach_boards_rwlock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic sbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_i_status(drmachid_t id, drmach_status_t *stat)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_common_t *cp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_NOTID, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (cp->status(id, stat));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_unconfigure(drmachid_t id, int flags)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dev_info_t *rdip, *fdip = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char name[OBP_MAXDRVNAME];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (DRMACH_IS_CPU_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_DEVICE_ID(id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl dp = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rdip = dp->node->n_getdip(dp->node);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(rdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = dp->node->n_getprop(dp->node, "name", name, OBP_MAXDRVNAME);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Note: FORCE flag is no longer necessary under devfs
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(e_ddi_branch_held(rdip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (e_ddi_branch_unconfigure(rdip, &fdip, 0)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If non-NULL, fdip is returned held and must be released.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (fdip != NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ddi_pathname(fdip, path);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ndi_rele_devi(fdip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ddi_pathname(rdip, path);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl err = drerr_new(1, EOPL_DRVFAIL, path);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(path, MAXPATHLEN);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_poweron(struct cpu *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum, cpuid, onb_core_num, strand_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("drmach_cpu_poweron: starting cpuid %d\n", cp->cpu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuid = cp->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = LSB_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl onb_core_num = ON_BOARD_CORE_NUM(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = drmach_get_board_by_bnum(bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->cores[onb_core_num].core_hotadded == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_add_remove_cpu(bnum, onb_core_num,
e98fafb9956429b59c817d4fbd27720c73879203jl HOTADD_CPU) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "Failed to add CMP %d on board %d\n",
e98fafb9956429b59c817d4fbd27720c73879203jl onb_core_num, bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&cpu_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_cpu_start(cp) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->cores[onb_core_num].core_started == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we must undo the hotadd or no one will do that
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If this fails, we will do this again in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_board_disconnect.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_add_remove_cpu(bnum, onb_core_num,
e98fafb9956429b59c817d4fbd27720c73879203jl HOTREMOVE_CPU) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "Failed to remove CMP %d "
e98fafb9956429b59c817d4fbd27720c73879203jl "on board %d\n", onb_core_num, bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EBUSY);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cores[onb_core_num].core_started |= (1 << strand_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_cpu_poweroff(struct cpu *cp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl processorid_t cpuid = cp->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("drmach_cpu_poweroff: stopping cpuid %d\n", cp->cpu_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(MUTEX_HELD(&cpu_lock));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Capture all CPUs (except for detaching proc) to prevent
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * crosscalls to the detaching proc until it has cleared its
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bit in cpu_ready_set.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The CPU's remain paused and the prom_mutex is known to be free.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This prevents the x-trap victim from blocking when doing prom
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IEEE-1275 calls at a high PIL level.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl promsafe_pause_cpus();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Quiesce interrupts on the target CPU. We do this by setting
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * prevent it from receiving cross calls and cross traps.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This prevents the processor from receiving any new soft interrupts.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mp_cpu_quiesce(cp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = prom_stopcpu_bycpuid(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv == 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl start_cpus();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int bnum, onb_core_num, strand_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bnum = LSB_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl onb_core_num = ON_BOARD_CORE_NUM(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = drmach_get_board_by_bnum(bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(bp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp->cores[onb_core_num].core_started &= ~(1 << strand_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->cores[onb_core_num].core_started == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_add_remove_cpu(bnum, onb_core_num,
e98fafb9956429b59c817d4fbd27720c73879203jl HOTREMOVE_CPU) != 0) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "Failed to remove CMP %d LSB "
e98fafb9956429b59c817d4fbd27720c73879203jl "%d\n", onb_core_num, bnum);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (EIO);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_verify_sr(dev_info_t *dip, int sflag)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_suspend_last(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_resume_first(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Log a DR sysevent.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Return value: 0 success, non-zero failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_log_sysevent(int board, char *hint, int flag, int verbose)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_t *ev;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_id_t eid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv, km_flag;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_value_t evnt_val;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_attr_list_t *evnt_attr_list = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char attach_pnt[MAXNAMELEN];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl km_flag = (flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl attach_pnt[0] = '\0';
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_board_name(board, attach_pnt, MAXNAMELEN)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto logexit;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
b307f191031b69156225d50e36c406311441051abm if (verbose) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("drmach_log_sysevent: %s %s, flag: %d, verbose: %d\n",
e98fafb9956429b59c817d4fbd27720c73879203jl attach_pnt, hint, flag, verbose);
b307f191031b69156225d50e36c406311441051abm }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE,
e98fafb9956429b59c817d4fbd27720c73879203jl SUNW_KERN_PUB"dr", km_flag)) == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = -2;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto logexit;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl evnt_val.value_type = SE_DATA_TYPE_STRING;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl evnt_val.value.sv_string = attach_pnt;
e98fafb9956429b59c817d4fbd27720c73879203jl if ((rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID, &evnt_val,
e98fafb9956429b59c817d4fbd27720c73879203jl km_flag)) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto logexit;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl evnt_val.value_type = SE_DATA_TYPE_STRING;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl evnt_val.value.sv_string = hint;
e98fafb9956429b59c817d4fbd27720c73879203jl if ((rv = sysevent_add_attr(&evnt_attr_list, DR_HINT, &evnt_val,
e98fafb9956429b59c817d4fbd27720c73879203jl km_flag)) != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_free_attr(evnt_attr_list);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto logexit;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) sysevent_attach_attributes(ev, evnt_attr_list);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Log the event but do not sleep waiting for its
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * delivery. This provides insulation from syseventd.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = log_sysevent(ev, SE_NOSLEEP, &eid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jllogexit:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ev)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sysevent_free(ev);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((rv != 0) && verbose)
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "drmach_log_sysevent failed (rv %d) for %s "
e98fafb9956429b59c817d4fbd27720c73879203jl " %s\n", rv, attach_pnt, hint);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define OPL_DR_STATUS_PROP "dr-status"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jlopl_check_dr_status()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl pnode_t node;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rtn, len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl char *str;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl node = prom_rootnode();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (node == OBP_BADNODE) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = prom_getproplen(node, OPL_DR_STATUS_PROP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (len == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * dr-status doesn't exist when DR is activated and
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * any warning messages aren't needed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl str = (char *)kmem_zalloc(len+1, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rtn = prom_getprop(node, OPL_DR_STATUS_PROP, str);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(str, len + 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rtn == -1) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* we are allocating memlist from TLB locked pages to avoid tlbmisses */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic struct memlist *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_memlist_add_span(drmach_copy_rename_program_t *p,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *mlist, uint64_t base, uint64_t len)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml, *tl, *nl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (len == 0ull)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mlist == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mlist = p->free_mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mlist == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams p->free_mlist = mlist->ml_next;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mlist->ml_address = base;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mlist->ml_size = len;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams mlist->ml_next = mlist->ml_prev = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams if (base < ml->ml_address) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams if ((base + len) < ml->ml_address) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nl = p->free_mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (nl == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams p->free_mlist = nl->ml_next;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_address = base;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_size = len;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_next = ml;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams if ((nl->ml_prev = ml->ml_prev) != NULL)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_prev->ml_next = nl;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_prev = nl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mlist == ml)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mlist = nl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_size = MAX((base + len),
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams (ml->ml_address + ml->ml_size)) - base;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_address = base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams } else if (base <= (ml->ml_address + ml->ml_size)) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_size =
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams MAX((base + len), (ml->ml_address + ml->ml_size)) -
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams MIN(ml->ml_address, base);
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_address = MIN(ml->ml_address, base);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (ml == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nl = p->free_mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (nl == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams p->free_mlist = nl->ml_next;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_address = base;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_size = len;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_next = NULL;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nl->ml_prev = tl;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams tl->ml_next = nl;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (mlist);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The routine performs the necessary memory COPY and MC adr SWITCH.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Both operations MUST be at the same "level" so that the stack is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * maintained correctly between the copy and switch. The switch
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * portion implements a caching mechanism to guarantee the code text
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is cached prior to execution. This is to guard against possible
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * memory access while the MC adr's are being modified.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IMPORTANT: The _drmach_copy_rename_end() function must immediately
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * follow drmach_copy_rename_prog__relocatable() so that the correct
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * "length" of the drmach_copy_rename_prog__relocatable can be
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * calculated. This routine MUST be a LEAF function, i.e. it can
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * make NO function calls, primarily for two reasons:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 1. We must keep the stack consistent across the "switch".
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 2. Function calls are compiled to relative offsets, and
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we execute this function we'll be executing it from
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * a copied version in a different area of memory, thus
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the relative offsets will be bogus.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Moreover, it must have the "__relocatable" suffix to inform DTrace
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * providers (and anything else, for that matter) that this
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * function's text is manually relocated elsewhere before it is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * executed. That is, it cannot be safely instrumented with any
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * methodology that is PC-relative.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We multiply this to system_clock_frequency so we
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * are setting a delay of fmem_timeout second for
b307f191031b69156225d50e36c406311441051abm * the rename command.
b307f191031b69156225d50e36c406311441051abm *
b307f191031b69156225d50e36c406311441051abm * FMEM command itself should complete within 15 sec.
b307f191031b69156225d50e36c406311441051abm * We add 2 more sec to be conservative.
b307f191031b69156225d50e36c406311441051abm *
b307f191031b69156225d50e36c406311441051abm * Note that there is also a SCF BUSY bit checking
b307f191031b69156225d50e36c406311441051abm * in drmach_asm.s right before FMEM command is
b307f191031b69156225d50e36c406311441051abm * issued. XSCF sets the SCF BUSY bit when the
b307f191031b69156225d50e36c406311441051abm * other domain on the same PSB reboots and it
b307f191031b69156225d50e36c406311441051abm * will not be able to service the FMEM command
b307f191031b69156225d50e36c406311441051abm * within 15 sec. After setting the SCF BUSY
b307f191031b69156225d50e36c406311441051abm * bit, XSCF will wait a while before servicing
b307f191031b69156225d50e36c406311441051abm * other reboot command so there is no race
b307f191031b69156225d50e36c406311441051abm * condition.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
b307f191031b69156225d50e36c406311441051abm
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int fmem_timeout = 17;
b307f191031b69156225d50e36c406311441051abm
b307f191031b69156225d50e36c406311441051abm/*
b307f191031b69156225d50e36c406311441051abm * The empirical data on some OPL system shows that
b307f191031b69156225d50e36c406311441051abm * we can copy 250 MB per second. We set it to
b307f191031b69156225d50e36c406311441051abm * 80 MB to be conservative. In normal case,
b307f191031b69156225d50e36c406311441051abm * this timeout does not affect anything.
b307f191031b69156225d50e36c406311441051abm */
b307f191031b69156225d50e36c406311441051abm
b307f191031b69156225d50e36c406311441051abmstatic int min_copy_size_per_sec = 80 * 1024 * 1024;
b307f191031b69156225d50e36c406311441051abm
b307f191031b69156225d50e36c406311441051abm/*
b307f191031b69156225d50e36c406311441051abm * This is the timeout value for the xcall synchronization
b307f191031b69156225d50e36c406311441051abm * to get all the CPU ready to do the parallel copying.
b307f191031b69156225d50e36c406311441051abm * Even on a fully loaded system, 10 sec. should be long
b307f191031b69156225d50e36c406311441051abm * enough.
b307f191031b69156225d50e36c406311441051abm */
b307f191031b69156225d50e36c406311441051abm
b307f191031b69156225d50e36c406311441051abmstatic int cpu_xcall_delay = 10;
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint drmach_disable_mcopy = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl/*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * The following delay loop executes sleep instruction to yield the
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * CPU to other strands. If this is not done, some strand will tie
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * up the CPU in busy loops while the other strand cannot do useful
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * work. The copy procedure will take a much longer time without this.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl#define DR_DELAY_IL(ms, freq) \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl { \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t start; \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t nstick; \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl volatile uint64_t now; \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nstick = ((uint64_t)ms * freq)/1000; \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl start = drmach_get_stick_il(); \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl now = start; \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while ((now - start) <= nstick) { \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_sleep_il(); \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl now = drmach_get_stick_il(); \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } \
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh/* Each loop is 2ms, timeout at 1000ms */
6534c6f0d5bc646e300a0609f2ce9ed145013b95whstatic int drmach_copy_rename_timeout = 500;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename_prog__relocatable(drmach_copy_rename_program_t *prog,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int cpuid)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl register int rtn;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int i;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl register uint64_t curr, limit;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern uint64_t drmach_get_stick_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void flush_instr_mem_il(void*);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl extern void flush_windows_il(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t copy_start;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * flush_windows is moved here to make sure all
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * registers used in the callers are flushed to
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * memory before the copy.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl *
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * If flush_windows() is called too early in the
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * calling function, the compiler might put some
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * data in the local registers after flush_windows().
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * After FMA, if there is any fill trap, the registers
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * will contain stale data.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl flush_windows_il();
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->stat[cpuid] = FMEM_LOOP_COPY_READY;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->cpuid == cpuid) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl limit = drmach_get_stick_il();
b307f191031b69156225d50e36c406311441051abm limit += cpu_xcall_delay * system_clock_freq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(prog->data->cpu_slave_set, i)) {
e98fafb9956429b59c817d4fbd27720c73879203jl /* wait for all CPU's to be ready */
e98fafb9956429b59c817d4fbd27720c73879203jl for (;;) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (prog->critical->stat[i] ==
e98fafb9956429b59c817d4fbd27720c73879203jl FMEM_LOOP_COPY_READY) {
e98fafb9956429b59c817d4fbd27720c73879203jl break;
e98fafb9956429b59c817d4fbd27720c73879203jl }
e98fafb9956429b59c817d4fbd27720c73879203jl DR_DELAY_IL(1, prog->data->stick_freq);
e98fafb9956429b59c817d4fbd27720c73879203jl }
e98fafb9956429b59c817d4fbd27720c73879203jl curr = drmach_get_stick_il();
e98fafb9956429b59c817d4fbd27720c73879203jl if (curr > limit) {
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->fmem_status.error =
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_XC_TIMEOUT;
e98fafb9956429b59c817d4fbd27720c73879203jl return (EOPL_FMEM_XC_TIMEOUT);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.stat = FMEM_LOOP_COPY_READY;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl copy_start = drmach_get_stick_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (;;) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->fmem_status.stat ==
e98fafb9956429b59c817d4fbd27720c73879203jl FMEM_LOOP_COPY_READY) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->fmem_status.error) {
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->error[cpuid] = EOPL_FMEM_TERMINATE;
b307f191031b69156225d50e36c406311441051abm return (EOPL_FMEM_TERMINATE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl DR_DELAY_IL(1, prog->data->stick_freq);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * DO COPY.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(prog->data->cpu_copy_set, cpuid)) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = prog->data->cpu_ml[cpuid]; ml; ml = ml->ml_next) {
e98fafb9956429b59c817d4fbd27720c73879203jl uint64_t s_pa, t_pa;
e98fafb9956429b59c817d4fbd27720c73879203jl uint64_t nbytes;
e98fafb9956429b59c817d4fbd27720c73879203jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams s_pa = prog->data->s_copybasepa + ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_pa = prog->data->t_copybasepa + ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl while (nbytes != 0ull) {
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * If the master has detected error, we just
e98fafb9956429b59c817d4fbd27720c73879203jl * bail out
e98fafb9956429b59c817d4fbd27720c73879203jl */
e98fafb9956429b59c817d4fbd27720c73879203jl if (prog->data->fmem_status.error !=
e98fafb9956429b59c817d4fbd27720c73879203jl ESBD_NOERROR) {
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->error[cpuid] =
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_TERMINATE;
e98fafb9956429b59c817d4fbd27720c73879203jl return (EOPL_FMEM_TERMINATE);
e98fafb9956429b59c817d4fbd27720c73879203jl }
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * This copy does NOT use an ASI
e98fafb9956429b59c817d4fbd27720c73879203jl * that avoids the Ecache, therefore
e98fafb9956429b59c817d4fbd27720c73879203jl * the dst_pa addresses may remain
e98fafb9956429b59c817d4fbd27720c73879203jl * in our Ecache after the dst_pa
e98fafb9956429b59c817d4fbd27720c73879203jl * has been removed from the system.
e98fafb9956429b59c817d4fbd27720c73879203jl * A subsequent write-back to memory
e98fafb9956429b59c817d4fbd27720c73879203jl * will cause an ARB-stop because the
e98fafb9956429b59c817d4fbd27720c73879203jl * physical address no longer exists
e98fafb9956429b59c817d4fbd27720c73879203jl * in the system. Therefore we must
e98fafb9956429b59c817d4fbd27720c73879203jl * flush out local Ecache after we
e98fafb9956429b59c817d4fbd27720c73879203jl * finish the copy.
e98fafb9956429b59c817d4fbd27720c73879203jl */
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl /* copy 32 bytes at src_pa to dst_pa */
e98fafb9956429b59c817d4fbd27720c73879203jl bcopy32_il(s_pa, t_pa);
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * increment the counter to signal that we are
e98fafb9956429b59c817d4fbd27720c73879203jl * alive
e98fafb9956429b59c817d4fbd27720c73879203jl */
e98fafb9956429b59c817d4fbd27720c73879203jl prog->stat->nbytes[cpuid] += 32;
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl /* increment by 32 bytes */
e98fafb9956429b59c817d4fbd27720c73879203jl s_pa += (4 * sizeof (uint64_t));
e98fafb9956429b59c817d4fbd27720c73879203jl t_pa += (4 * sizeof (uint64_t));
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl /* decrement by 32 bytes */
e98fafb9956429b59c817d4fbd27720c73879203jl nbytes -= (4 * sizeof (uint64_t));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
e98fafb9956429b59c817d4fbd27720c73879203jl prog->critical->stat[cpuid] = FMEM_LOOP_COPY_DONE;
e98fafb9956429b59c817d4fbd27720c73879203jl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Since bcopy32_il() does NOT use an ASI to bypass
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the Ecache, we need to flush our Ecache after
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the copy is complete.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl flush_cache_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_fmem_exec_script()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->cpuid == cpuid) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t last, now;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl limit = copy_start + prog->data->copy_delay;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (!CPU_IN_SET(prog->data->cpu_slave_set, i))
e98fafb9956429b59c817d4fbd27720c73879203jl continue;
e98fafb9956429b59c817d4fbd27720c73879203jl
e98fafb9956429b59c817d4fbd27720c73879203jl for (;;) {
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * we get FMEM_LOOP_FMEM_READY in
e98fafb9956429b59c817d4fbd27720c73879203jl * normal case
e98fafb9956429b59c817d4fbd27720c73879203jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->critical->stat[i] ==
e98fafb9956429b59c817d4fbd27720c73879203jl FMEM_LOOP_FMEM_READY) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* got error traps */
b307f191031b69156225d50e36c406311441051abm if (prog->data->error[i] ==
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_COPY_ERROR) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.error =
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_COPY_ERROR;
b307f191031b69156225d50e36c406311441051abm return (EOPL_FMEM_COPY_ERROR);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * if we have not reached limit, wait
e98fafb9956429b59c817d4fbd27720c73879203jl * more
e98fafb9956429b59c817d4fbd27720c73879203jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl curr = drmach_get_stick_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (curr <= limit)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->slowest_cpuid = i;
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->copy_wait_time = curr - copy_start;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* now check if slave is alive */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl last = prog->stat->nbytes[i];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DR_DELAY_IL(1, prog->data->stick_freq);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl now = prog->stat->nbytes[i];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (now <= last) {
e98fafb9956429b59c817d4fbd27720c73879203jl /*
e98fafb9956429b59c817d4fbd27720c73879203jl * no progress, perhaps just
e98fafb9956429b59c817d4fbd27720c73879203jl * finished
e98fafb9956429b59c817d4fbd27720c73879203jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DR_DELAY_IL(1, prog->data->stick_freq);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->critical->stat[i] ==
e98fafb9956429b59c817d4fbd27720c73879203jl FMEM_LOOP_FMEM_READY)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* copy error */
b307f191031b69156225d50e36c406311441051abm if (prog->data->error[i] ==
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_COPY_ERROR) {
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data-> fmem_status.error =
e98fafb9956429b59c817d4fbd27720c73879203jl EOPL_FMEM_COPY_ERROR;
b307f191031b69156225d50e36c406311441051abm return (EOPL_FMEM_COPY_ERROR);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh prog->data->copy_rename_count++;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if (prog->data->copy_rename_count
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh < drmach_copy_rename_timeout) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh continue;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh } else {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh prog->data->fmem_status.error =
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh EOPL_FMEM_COPY_TIMEOUT;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh return (EOPL_FMEM_COPY_TIMEOUT);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
b307f191031b69156225d50e36c406311441051abm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->stat[cpuid] = FMEM_LOOP_FMEM_READY;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.stat = FMEM_LOOP_FMEM_READY;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl flush_instr_mem_il((void*) (prog->critical));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_fmem_exec_script()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rtn = prog->critical->fmem((void *)prog->critical, PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (rtn);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl flush_instr_mem_il((void*) (prog->critical));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * drmach_fmem_loop_script()
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
e98fafb9956429b59c817d4fbd27720c73879203jl rtn = prog->critical->loop((void *)(prog->critical), PAGESIZE,
e98fafb9956429b59c817d4fbd27720c73879203jl (void *)&(prog->critical->stat[cpuid]));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->error[cpuid] = rtn;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* slave thread does not care the rv */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename_end(void)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IMPORTANT: This function's location MUST be located immediately
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * following drmach_copy_rename_prog__relocatable to
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * accurately estimate its size. Note that this assumes
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the compiler keeps these functions in the order in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * which they appear :-o
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
6534c6f0d5bc646e300a0609f2ce9ed145013b95whstatic int
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_setup_memlist(drmach_copy_rename_program_t *p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t buf;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh int nbytes, s, n_elements;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nbytes = PAGESIZE;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh n_elements = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s = roundup(sizeof (struct memlist), sizeof (void *));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->free_mlist = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl buf = p->memlist_buffer;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (nbytes >= sizeof (struct memlist)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ml = (struct memlist *)buf;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_next = p->free_mlist;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl p->free_mlist = ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl buf += s;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh n_elements++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl nbytes -= s;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh return (n_elements);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djlstatic void
68ac2337c38c8af06edcf32a72e42de36ec72a9djldrmach_lock_critical(caddr_t va, caddr_t new_va)
68ac2337c38c8af06edcf32a72e42de36ec72a9djl{
68ac2337c38c8af06edcf32a72e42de36ec72a9djl tte_t tte;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl int i;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kpreempt_disable();
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl for (i = 0; i < DRMACH_FMEM_LOCKED_PAGES; i++) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl vtag_flushpage(new_va, (uint64_t)ksfmmup);
e98fafb9956429b59c817d4fbd27720c73879203jl sfmmu_memtte(&tte, va_to_pfn(va), PROC_DATA|HAT_NOSYNC, TTE8K);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl tte.tte_intlo |= TTE_LCK_INT;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl sfmmu_dtlb_ld_kva(new_va, &tte);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl sfmmu_itlb_ld_kva(new_va, &tte);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl va += PAGESIZE;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl new_va += PAGESIZE;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl}
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djlstatic void
68ac2337c38c8af06edcf32a72e42de36ec72a9djldrmach_unlock_critical(caddr_t va)
68ac2337c38c8af06edcf32a72e42de36ec72a9djl{
68ac2337c38c8af06edcf32a72e42de36ec72a9djl int i;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl for (i = 0; i < DRMACH_FMEM_LOCKED_PAGES; i++) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl vtag_flushpage(va, (uint64_t)ksfmmup);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl va += PAGESIZE;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kpreempt_enable();
68ac2337c38c8af06edcf32a72e42de36ec72a9djl}
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename_init(drmachid_t t_id, drmachid_t s_id,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *c_ml, drmachid_t *pgm_id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *s_mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_mem_t *t_mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *x_ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t s_copybasepa, t_copybasepa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint_t len;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl caddr_t bp, wp;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh int s_bd, t_bd, cpuid, active_cpus, i;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh int max_elms, mlist_size, rv;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh uint64_t c_addr;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh size_t c_size, copy_sz, sz;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh extern void drmach_fmem_loop_script();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh extern void drmach_fmem_loop_script_rtn();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh extern int drmach_fmem_exec_script();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh extern void drmach_fmem_exec_script_end();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_copy_rename_program_t *prog = NULL;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_copy_rename_program_t *prog_kmem = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void (*mc_suspend)(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl void (*mc_resume)(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*scf_fmem_start)(int, int);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*scf_fmem_end)(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int (*scf_fmem_cancel)(void);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl uint64_t (*scf_get_base_addr)(void);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(s_id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!DRMACH_IS_MEM_ID(t_id))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (drerr_new(0, EOPL_INAPPROP, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int lsb_id, onb_core_num, strand_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * this kind of CPU will spin in cache
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(cpu_ready_set, i))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Now check for any inactive CPU's that
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * have been hotadded. This can only occur in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * error condition in drmach_cpu_poweron().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl lsb_id = LSB_ID(i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl onb_core_num = ON_BOARD_CORE_NUM(i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl strand_id = STRAND_ID(i);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = drmach_get_board_by_bnum(lsb_id);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp == NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (bp->cores[onb_core_num].core_hotadded &
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (1 << strand_id)) {
e98fafb9956429b59c817d4fbd27720c73879203jl if (!(bp->cores[onb_core_num].core_started &
e98fafb9956429b59c817d4fbd27720c73879203jl (1 << strand_id))) {
e98fafb9956429b59c817d4fbd27720c73879203jl return (drerr_new(1, EOPL_CPU_STATE, NULL));
e98fafb9956429b59c817d4fbd27720c73879203jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mc_suspend = (void (*)(void))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("opl_mc_suspend", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mc_resume = (void (*)(void))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("opl_mc_resume", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (mc_suspend == NULL || mc_resume == NULL) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_MC_OPL, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl scf_fmem_start = (int (*)(int, int))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("scf_fmem_start", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (scf_fmem_start == NULL) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_SCF_FMEM, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl scf_fmem_end = (int (*)(void))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("scf_fmem_end", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (scf_fmem_end == NULL) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_SCF_FMEM, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl scf_fmem_cancel = (int (*)(void))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl modgetsymvalue("scf_fmem_cancel", 0);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (scf_fmem_cancel == NULL) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_SCF_FMEM, NULL));
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl scf_get_base_addr = (uint64_t (*)(void))
68ac2337c38c8af06edcf32a72e42de36ec72a9djl modgetsymvalue("scf_get_base_addr", 0);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (scf_get_base_addr == NULL) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm return (drerr_new(1, EOPL_SCF_FMEM, NULL));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_mem = s_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_mem = t_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_bd = s_mem->dev.bp->bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_bd = t_mem->dev.bp->bnum;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* calculate source and target base pa */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_copybasepa = s_mem->slice_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_copybasepa = t_mem->slice_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* adjust copy memlist addresses to be relative to copy base pa */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl x_ml = c_ml;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh mlist_size = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (x_ml != NULL) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml->ml_address -= s_copybasepa;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml = x_ml->ml_next;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh mlist_size++;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * bp will be page aligned, since we're calling
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * kmem_zalloc() with an exact multiple of PAGESIZE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog_kmem = (drmach_copy_rename_program_t *)kmem_zalloc(
e98fafb9956429b59c817d4fbd27720c73879203jl DRMACH_FMEM_LOCKED_PAGES * PAGESIZE, KM_SLEEP);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog_kmem->prog = prog_kmem;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * To avoid MTLB hit, we allocate a new VM space and remap
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * the kmem_alloc buffer to that address. This solves
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * 2 problems we found:
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * - the kmem_alloc buffer can be just a chunk inside
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * a much larger, e.g. 4MB buffer and MTLB will occur
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * if there are both a 4MB and a 8K TLB mapping to
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * the same VA range.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * - the kmem mapping got dropped into the TLB by other
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * strands, unintentionally.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * Note that the pointers like data, critical, memlist_buffer,
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * and stat inside the copy rename structure are mapped to this
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * alternate VM space so we must make sure we lock the TLB mapping
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * whenever we access data pointed to by these pointers.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog = prog_kmem->locked_prog = vmem_alloc(heap_arena,
e98fafb9956429b59c817d4fbd27720c73879203jl DRMACH_FMEM_LOCKED_PAGES * PAGESIZE, VM_SLEEP);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl wp = bp = (caddr_t)prog;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /* Now remap prog_kmem to prog */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_lock_critical((caddr_t)prog_kmem, (caddr_t)prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /* All pointers in prog are based on the alternate mapping */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data = (drmach_copy_rename_data_t *)roundup(((uint64_t)prog +
e98fafb9956429b59c817d4fbd27720c73879203jl sizeof (drmach_copy_rename_program_t)), sizeof (void *));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ASSERT(((uint64_t)prog->data + sizeof (drmach_copy_rename_data_t))
e98fafb9956429b59c817d4fbd27720c73879203jl <= ((uint64_t)prog + PAGESIZE));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical = (drmach_copy_rename_critical_t *)
e98fafb9956429b59c817d4fbd27720c73879203jl (wp + DRMACH_FMEM_CRITICAL_PAGE * PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl prog->memlist_buffer = (caddr_t)(wp + DRMACH_FMEM_MLIST_PAGE *
e98fafb9956429b59c817d4fbd27720c73879203jl PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
e98fafb9956429b59c817d4fbd27720c73879203jl prog->stat = (drmach_cr_stat_t *)(wp + DRMACH_FMEM_STAT_PAGE *
e98fafb9956429b59c817d4fbd27720c73879203jl PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* LINTED */
e98fafb9956429b59c817d4fbd27720c73879203jl ASSERT(sizeof (drmach_cr_stat_t) <= ((DRMACH_FMEM_LOCKED_PAGES -
e98fafb9956429b59c817d4fbd27720c73879203jl DRMACH_FMEM_STAT_PAGE) * PAGESIZE));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->scf_reg_base = (uint64_t)-1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->scf_td[0] = (s_bd & 0xff);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->scf_td[1] = (t_bd & 0xff);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 2; i < 15; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->scf_td[i] = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->scf_td[15] = ((0xaa + s_bd + t_bd) & 0xff);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = (caddr_t)prog->critical;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (drmach_copy_rename_critical_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = (caddr_t)roundup((uint64_t)bp + len, sizeof (void *));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (uint_t)((ulong_t)drmach_copy_rename_end -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_copy_rename_prog__relocatable);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * We always leave 1K nop's to prevent the processor from
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * speculative execution that causes memory access
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = wp + len + 1024;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (uint_t)((ulong_t)drmach_fmem_exec_script_end -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_exec_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* this is the entry point of the loop script */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = wp + len + 1024;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (uint_t)((ulong_t)drmach_fmem_exec_script -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_loop_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = wp + len + 1024;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* now we make sure there is 1K extra */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((wp - bp) > PAGESIZE) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_FMEM_SETUP, NULL);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl goto out;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bp = (caddr_t)prog->critical;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (drmach_copy_rename_critical_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = (caddr_t)roundup((uint64_t)bp + len, sizeof (void *));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->run = (int (*)())(wp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (uint_t)((ulong_t)drmach_copy_rename_end -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_copy_rename_prog__relocatable);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy((caddr_t)drmach_copy_rename_prog__relocatable, wp, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = (caddr_t)roundup((uint64_t)wp + len, 1024);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->fmem = (int (*)())(wp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (int)((ulong_t)drmach_fmem_exec_script_end -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_exec_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy((caddr_t)drmach_fmem_exec_script, wp, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (int)((ulong_t)drmach_fmem_exec_script_end -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_exec_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl wp = (caddr_t)roundup((uint64_t)wp + len, 1024);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->loop = (int (*)())(wp);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (int)((ulong_t)drmach_fmem_exec_script -
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_loop_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl bcopy((caddr_t)drmach_fmem_loop_script, (void *)wp, len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = (int)((ulong_t)drmach_fmem_loop_script_rtn-
e98fafb9956429b59c817d4fbd27720c73879203jl (ulong_t)drmach_fmem_loop_script);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->loop_rtn = (void (*)()) (wp+len);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
b307f191031b69156225d50e36c406311441051abm prog->data->fmem_status.error = ESBD_NOERROR;
b307f191031b69156225d50e36c406311441051abm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* now we are committed, call SCF, soft suspend mac patrol */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((*scf_fmem_start)(s_bd, t_bd)) {
8eafe49b0ded7a20fe5889318c469380e618fe25bm err = drerr_new(1, EOPL_SCF_FMEM_START, NULL);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl goto out;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->scf_fmem_end = scf_fmem_end;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->scf_fmem_cancel = scf_fmem_cancel;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog->data->scf_get_base_addr = scf_get_base_addr;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.op |= OPL_FMEM_SCF_START;
b307f191031b69156225d50e36c406311441051abm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* soft suspend mac patrol */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (*mc_suspend)();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.op |= OPL_FMEM_MC_SUSPEND;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->mc_resume = mc_resume;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->inst_loop_ret =
e98fafb9956429b59c817d4fbd27720c73879203jl *(uint64_t *)(prog->critical->loop_rtn);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 0x30800000 is op code "ba,a +0"
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *(uint_t *)(prog->critical->loop_rtn) = (uint_t)(0x30800000);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * set the value of SCF FMEM TIMEOUT
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->delay = fmem_timeout * system_clock_freq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->s_mem = (drmachid_t)s_mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->t_mem = (drmachid_t)t_mem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuid = CPU->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->cpuid = cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->cpu_ready_set = cpu_ready_set;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->cpu_slave_set = cpu_ready_set;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->slowest_cpuid = (processorid_t)-1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->copy_wait_time = 0;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh prog->data->copy_rename_count = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl CPUSET_DEL(prog->data->cpu_slave_set, cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->cpu_ml[i] = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh /*
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * max_elms - max number of memlist structures that
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * may be allocated for the CPU memory list.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * If there are too many memory span (because
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * of fragmentation) than number of memlist
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * available, we should return error.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh */
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh max_elms = drmach_setup_memlist(prog);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if (max_elms < mlist_size) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh err = drerr_new(1, EOPL_FMEM_SETUP, NULL);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh goto err_out;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
25cf1a301a396c38e8adf52c15f537b80d2483f7jl active_cpus = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (drmach_disable_mcopy) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl active_cpus = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl CPUSET_ADD(prog->data->cpu_copy_set, cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh int max_cpu_num;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh /*
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * The parallel copy procedure is going to split some
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * of the elements of the original memory copy list.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * The number of added elements can be up to
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * (max_cpu_num - 1). It means that max_cpu_num
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * should satisfy the following condition:
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * (max_cpu_num - 1) + mlist_size <= max_elms.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh */
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh max_cpu_num = max_elms - mlist_size + 1;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(cpu_ready_set, i) &&
e98fafb9956429b59c817d4fbd27720c73879203jl CPU_ACTIVE(cpu[i])) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh /*
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * To reduce the level-2 cache contention only
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * one strand per core will participate
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * in the copy. If the strand with even cpu_id
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * number is present in the ready set, we will
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * include this strand in the copy set. If it
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * is not present in the ready set, we check for
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * the strand with the consecutive odd cpu_id
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * and include it, provided that it is
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * present in the ready set.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh */
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if (!(i & 0x1) ||
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh !CPU_IN_SET(prog->data->cpu_copy_set,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh i - 1)) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh CPUSET_ADD(prog->data->cpu_copy_set, i);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh active_cpus++;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh /*
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * We cannot have more than
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * max_cpu_num CPUs in the copy
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * set, because each CPU has to
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * have at least one element
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh * long memory copy list.
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh */
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if (active_cpus >= max_cpu_num)
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh break;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl x_ml = c_ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sz = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (x_ml != NULL) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams sz += x_ml->ml_size;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml = x_ml->ml_next;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl copy_sz = sz/active_cpus;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl copy_sz = roundup(copy_sz, MMU_PAGESIZE4M);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (sz > copy_sz*active_cpus) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl copy_sz += MMU_PAGESIZE4M;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->stick_freq = system_clock_freq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->copy_delay = ((copy_sz / min_copy_size_per_sec) + 2) *
e98fafb9956429b59c817d4fbd27720c73879203jl system_clock_freq;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl x_ml = c_ml;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams c_addr = x_ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams c_size = x_ml->ml_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < NCPU; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->stat->nbytes[i] = 0;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!CPU_IN_SET(prog->data->cpu_copy_set, i)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sz = copy_sz;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while (sz) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (c_size > sz) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if ((prog->data->cpu_ml[i] =
e98fafb9956429b59c817d4fbd27720c73879203jl drmach_memlist_add_span(prog,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh prog->data->cpu_ml[i],
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh c_addr, sz)) == NULL) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh cmn_err(CE_WARN,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh "Unexpected drmach_memlist_add_span"
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh " failure.");
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh err = drerr_new(1, EOPL_FMEM_SETUP,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh NULL);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh mc_resume();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh goto out;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl c_addr += sz;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl c_size -= sz;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sz -= c_size;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if ((prog->data->cpu_ml[i] =
e98fafb9956429b59c817d4fbd27720c73879203jl drmach_memlist_add_span(prog,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh prog->data->cpu_ml[i],
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh c_addr, c_size)) == NULL) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh cmn_err(CE_WARN,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh "Unexpected drmach_memlist_add_span"
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh " failure.");
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh err = drerr_new(1, EOPL_FMEM_SETUP,
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh NULL);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh mc_resume();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh goto out;
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml = x_ml->ml_next;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (x_ml != NULL) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams c_addr = x_ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams c_size = x_ml->ml_size;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto end;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jlend:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->s_copybasepa = s_copybasepa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->t_copybasepa = t_copybasepa;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->c_ml = c_ml;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl *pgm_id = prog_kmem;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /* Unmap the alternate space. It will have to be remapped again */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_unlock_critical((caddr_t)prog);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (NULL);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh
6534c6f0d5bc646e300a0609f2ce9ed145013b95wherr_out:
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh mc_resume();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh rv = (*prog->data->scf_fmem_cancel)();
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh if (rv) {
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh cmn_err(CE_WARN, "scf_fmem_cancel() failed rv=0x%x", rv);
6534c6f0d5bc646e300a0609f2ce9ed145013b95wh }
68ac2337c38c8af06edcf32a72e42de36ec72a9djlout:
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (prog != NULL) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_unlock_critical((caddr_t)prog);
e98fafb9956429b59c817d4fbd27720c73879203jl vmem_free(heap_arena, prog, DRMACH_FMEM_LOCKED_PAGES *
e98fafb9956429b59c817d4fbd27720c73879203jl PAGESIZE);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (prog_kmem != NULL) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl kmem_free(prog_kmem, DRMACH_FMEM_LOCKED_PAGES * PAGESIZE);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsbd_error_t *
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename_fini(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_copy_rename_program_t *prog = id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl sbd_error_t *err = NULL;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int rv;
b307f191031b69156225d50e36c406311441051abm uint_t fmem_error;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Note that we have to delay calling SCF to find out the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * status of the FMEM operation here because SCF cannot
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * respond while it is suspended.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This create a small window when we are sure about the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * base address of the system board.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If there is any call to mc-opl to get memory unum,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * mc-opl will return UNKNOWN as the unum.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * we have to remap again because all the pointer like data,
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * critical in prog are based on the alternate vmem space.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (void) drmach_lock_critical((caddr_t)prog, (caddr_t)prog->locked_prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->c_ml != NULL)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl memlist_delete(prog->data->c_ml);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((prog->data->fmem_status.op &
e98fafb9956429b59c817d4fbd27720c73879203jl (OPL_FMEM_SCF_START | OPL_FMEM_MC_SUSPEND)) !=
e98fafb9956429b59c817d4fbd27720c73879203jl (OPL_FMEM_SCF_START | OPL_FMEM_MC_SUSPEND)) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_PANIC, "drmach_copy_rename_fini: invalid op "
e98fafb9956429b59c817d4fbd27720c73879203jl "code %x\n", prog->data->fmem_status.op);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
b307f191031b69156225d50e36c406311441051abm fmem_error = prog->data->fmem_status.error;
b307f191031b69156225d50e36c406311441051abm if (fmem_error != ESBD_NOERROR) {
b307f191031b69156225d50e36c406311441051abm err = drerr_new(1, fmem_error, NULL);
b307f191031b69156225d50e36c406311441051abm }
b307f191031b69156225d50e36c406311441051abm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* possible ops are SCF_START, MC_SUSPEND */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->critical->fmem_issued) {
b307f191031b69156225d50e36c406311441051abm if (fmem_error != ESBD_NOERROR) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_PANIC, "Irrecoverable FMEM error %d\n",
e98fafb9956429b59c817d4fbd27720c73879203jl fmem_error);
b307f191031b69156225d50e36c406311441051abm }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = (*prog->data->scf_fmem_end)();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl cmn_err(CE_PANIC, "scf_fmem_end() failed rv=%d", rv);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If we get here, rename is successful.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Do all the copy rename post processing.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_swap_pa((drmach_mem_t *)prog->data->s_mem,
e98fafb9956429b59c817d4fbd27720c73879203jl (drmach_mem_t *)prog->data->t_mem);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rv = (*prog->data->scf_fmem_cancel)();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rv) {
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_WARN, "scf_fmem_cancel() failed rv=0x%x",
e98fafb9956429b59c817d4fbd27720c73879203jl rv);
e98fafb9956429b59c817d4fbd27720c73879203jl if (!err) {
e98fafb9956429b59c817d4fbd27720c73879203jl err = drerr_new(1, EOPL_SCF_FMEM_CANCEL,
e98fafb9956429b59c817d4fbd27720c73879203jl "scf_fmem_cancel() failed. rv = 0x%x", rv);
e98fafb9956429b59c817d4fbd27720c73879203jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* soft resume mac patrol */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (*prog->data->mc_resume)();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_unlock_critical((caddr_t)prog->locked_prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl vmem_free(heap_arena, prog->locked_prog,
e98fafb9956429b59c817d4fbd27720c73879203jl DRMACH_FMEM_LOCKED_PAGES * PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kmem_free(prog, DRMACH_FMEM_LOCKED_PAGES * PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return (err);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/*ARGSUSED*/
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename_slave(struct regs *rp, drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_copy_rename_program_t *prog =
e98fafb9956429b59c817d4fbd27720c73879203jl (drmach_copy_rename_program_t *)id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl register int cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void drmach_flush();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void drmach_flush_icache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl on_trap_data_t otd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuid = CPU->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (on_trap(&otd, OT_DATA_EC)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_trap();
b307f191031b69156225d50e36c406311441051abm prog->data->error[cpuid] = EOPL_FMEM_COPY_ERROR;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->stat[cpuid] = FMEM_LOOP_EXIT;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_flush_icache();
68ac2337c38c8af06edcf32a72e42de36ec72a9djl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * jmp drmach_copy_rename_prog().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_flush(prog->critical, PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) prog->critical->run(prog, cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_flush_icache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_trap();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->stat[cpuid] = FMEM_LOOP_EXIT;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl membar_sync_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlstatic void
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_swap_pa(drmach_mem_t *s_mem, drmach_mem_t *t_mem)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t s_base, t_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_board_t *s_board, *t_board;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl struct memlist *ml;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_board = s_mem->dev.bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_board = t_mem->dev.bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (s_board == NULL || t_board == NULL) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "Cannot locate source or target board\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_base = s_mem->slice_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_base = t_mem->slice_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_mem->slice_base = t_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl s_mem->base_pa = (s_mem->base_pa - s_base) + t_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = s_mem->memlist; ml; ml = ml->ml_next) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_address = ml->ml_address - s_base + t_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_mem->slice_base = s_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl t_mem->base_pa = (t_mem->base_pa - t_base) + s_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = t_mem->memlist; ml; ml = ml->ml_next) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ml->ml_address = ml->ml_address - t_base + s_base;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * IKP has to update the sb-mem-ranges for mac patrol driver
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * when it resumes, it will re-read the sb-mem-range property
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to get the new base address
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (oplcfg_pa_swap(s_board->bnum, t_board->bnum) != 0)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_PANIC, "Could not update device nodes\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jlvoid
25cf1a301a396c38e8adf52c15f537b80d2483f7jldrmach_copy_rename(drmachid_t id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl{
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_copy_rename_program_t *prog_kmem = id;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_copy_rename_program_t *prog;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuset_t cpuset;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int cpuid;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t inst;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl register int rtn;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern int in_sync;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl int old_in_sync;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void drmach_sys_trap();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void drmach_flush();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern void drmach_flush_icache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl extern uint64_t patch_inst(uint64_t *, uint64_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl on_trap_data_t otd;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
8eafe49b0ded7a20fe5889318c469380e618fe25bm
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog = prog_kmem->locked_prog;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
8eafe49b0ded7a20fe5889318c469380e618fe25bm
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * We must immediately drop in the TLB because all pointers
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * are based on the alternate vmem space.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (void) drmach_lock_critical((caddr_t)prog_kmem, (caddr_t)prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * we call scf to get the base address here becuase if scf
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * has not been suspended yet, the active path can be changing and
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * sometimes it is not even mapped. We call the interface when
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * the OS has been quiesced.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl prog->critical->scf_reg_base = (*prog->data->scf_get_base_addr)();
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (prog->critical->scf_reg_base == (uint64_t)-1 ||
e98fafb9956429b59c817d4fbd27720c73879203jl prog->critical->scf_reg_base == NULL) {
b307f191031b69156225d50e36c406311441051abm prog->data->fmem_status.error = EOPL_FMEM_SCF_ERR;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_unlock_critical((caddr_t)prog);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl return;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuset = prog->data->cpu_ready_set;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (cpuid = 0; cpuid < NCPU; cpuid++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (CPU_IN_SET(cpuset, cpuid)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->critical->stat[cpuid] = FMEM_LOOP_START;
b307f191031b69156225d50e36c406311441051abm prog->data->error[cpuid] = ESBD_NOERROR;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl old_in_sync = in_sync;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl in_sync = 1;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpuid = CPU->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl CPUSET_DEL(cpuset, cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl for (cpuid = 0; cpuid < NCPU; cpuid++) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (CPU_IN_SET(cpuset, cpuid)) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl xc_one(cpuid, (xcfunc_t *)drmach_lock_critical,
e98fafb9956429b59c817d4fbd27720c73879203jl (uint64_t)prog_kmem, (uint64_t)prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl cpuid = CPU->cpu_id;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl xt_some(cpuset, (xcfunc_t *)drmach_sys_trap,
e98fafb9956429b59c817d4fbd27720c73879203jl (uint64_t)drmach_copy_rename_slave, (uint64_t)prog);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl xt_sync(cpuset);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (on_trap(&otd, OT_DATA_EC)) {
b307f191031b69156225d50e36c406311441051abm rtn = EOPL_FMEM_COPY_ERROR;
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_flush_icache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl goto done;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * jmp drmach_copy_rename_prog().
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
8eafe49b0ded7a20fe5889318c469380e618fe25bm
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_flush(prog->critical, PAGESIZE);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rtn = prog->critical->run(prog, cpuid);
e98fafb9956429b59c817d4fbd27720c73879203jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_flush_icache();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jldone:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl no_trap();
b307f191031b69156225d50e36c406311441051abm if (rtn == EOPL_FMEM_HW_ERROR) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl kpreempt_enable();
e98fafb9956429b59c817d4fbd27720c73879203jl prom_panic("URGENT_ERROR_TRAP is detected during FMEM.\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * In normal case, all slave CPU's are still spinning in
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the assembly code. The master has to patch the instruction
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to get them out.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * In error case, e.g. COPY_ERROR, some slave CPU's might
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * have aborted and already returned and sset LOOP_EXIT status.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Some CPU might still be copying.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * In any case, some delay is necessary to give them
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * enough time to set the LOOP_EXIT status.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (;;) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl inst = patch_inst((uint64_t *)prog->critical->loop_rtn,
e98fafb9956429b59c817d4fbd27720c73879203jl prog->critical->inst_loop_ret);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->critical->inst_loop_ret == inst) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (cpuid = 0; cpuid < NCPU; cpuid++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl uint64_t last, now;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (!CPU_IN_SET(cpuset, cpuid)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl continue;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl last = prog->stat->nbytes[cpuid];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /*
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Wait for all CPU to exit.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * However we do not want an infinite loop
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * so we detect hangup situation here.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the slave CPU is still copying data,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * we will continue to wait.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * In error cases, the master has already set
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fmem_status.error to abort the copying.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 1 m.s delay for them to abort copying and
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * return to drmach_copy_rename_slave to set
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * FMEM_LOOP_EXIT status should be enough.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (;;) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->critical->stat[cpuid] == FMEM_LOOP_EXIT)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl break;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_sleep_il();
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drv_usecwait(1000);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl now = prog->stat->nbytes[cpuid];
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (now <= last) {
e98fafb9956429b59c817d4fbd27720c73879203jl drv_usecwait(1000);
e98fafb9956429b59c817d4fbd27720c73879203jl if (prog->critical->stat[cpuid] ==
e98fafb9956429b59c817d4fbd27720c73879203jl FMEM_LOOP_EXIT)
e98fafb9956429b59c817d4fbd27720c73879203jl break;
e98fafb9956429b59c817d4fbd27720c73879203jl cmn_err(CE_PANIC, "CPU %d hang during Copy "
e98fafb9956429b59c817d4fbd27720c73879203jl "Rename", cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl last = now;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
b307f191031b69156225d50e36c406311441051abm if (prog->data->error[cpuid] == EOPL_FMEM_HW_ERROR) {
e98fafb9956429b59c817d4fbd27720c73879203jl prom_panic("URGENT_ERROR_TRAP is detected during "
e98fafb9956429b59c817d4fbd27720c73879203jl "FMEM.\n");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * This must be done after all strands have exit.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * Removing the TLB entry will affect both strands
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * in the same core.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl for (cpuid = 0; cpuid < NCPU; cpuid++) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl if (CPU_IN_SET(cpuset, cpuid)) {
68ac2337c38c8af06edcf32a72e42de36ec72a9djl xc_one(cpuid, (xcfunc_t *)drmach_unlock_critical,
e98fafb9956429b59c817d4fbd27720c73879203jl (uint64_t)prog, 0);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl }
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl in_sync = old_in_sync;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * we should unlock before the following lock to keep the kpreempt
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * count correct.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (void) drmach_unlock_critical((caddr_t)prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl /*
68ac2337c38c8af06edcf32a72e42de36ec72a9djl * we must remap again. TLB might have been removed in above xcall.
68ac2337c38c8af06edcf32a72e42de36ec72a9djl */
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
68ac2337c38c8af06edcf32a72e42de36ec72a9djl (void) drmach_lock_critical((caddr_t)prog_kmem, (caddr_t)prog);
68ac2337c38c8af06edcf32a72e42de36ec72a9djl
b307f191031b69156225d50e36c406311441051abm if (prog->data->fmem_status.error == ESBD_NOERROR)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl prog->data->fmem_status.error = rtn;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (prog->data->copy_wait_time > 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DRMACH_PR("Unexpected long wait time %ld seconds "
e98fafb9956429b59c817d4fbd27720c73879203jl "during copy rename on CPU %d\n",
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->copy_wait_time/prog->data->stick_freq,
e98fafb9956429b59c817d4fbd27720c73879203jl prog->data->slowest_cpuid);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl }
68ac2337c38c8af06edcf32a72e42de36ec72a9djl drmach_unlock_critical((caddr_t)prog);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl}