29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER START
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The contents of this file are subject to the terms of the
29949e866e40b95795203f3ee46f44a197c946e4stevel * Common Development and Distribution License (the "License").
29949e866e40b95795203f3ee46f44a197c946e4stevel * You may not use this file except in compliance with the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
29949e866e40b95795203f3ee46f44a197c946e4stevel * or http://www.opensolaris.org/os/licensing.
29949e866e40b95795203f3ee46f44a197c946e4stevel * See the License for the specific language governing permissions
29949e866e40b95795203f3ee46f44a197c946e4stevel * and limitations under the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * When distributing Covered Code, include this CDDL HEADER in each
29949e866e40b95795203f3ee46f44a197c946e4stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
29949e866e40b95795203f3ee46f44a197c946e4stevel * If applicable, add the following below this CDDL HEADER, with the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fields enclosed by brackets "[]" replaced with your own identifying
29949e866e40b95795203f3ee46f44a197c946e4stevel * information: Portions Copyright [yyyy] [name of copyright owner]
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER END
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
85f5803819bea86c07827a9544494e4ad327d95ddp * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use is subject to license terms.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#pragma ident "%Z%%M% %I% %E% SMI"
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/types.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/systm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sunddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_impldefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/obpdefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/errno.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/debug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sysmacros.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machsystm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machparam.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/modctl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fhc.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ac.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpu_module.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/seg_kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/hat_sfmmu.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/mem_config.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/mem_cage.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelextern ac_err_t ac_kpm_err_cvt(int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_del_clean = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Default timeout, in seconds, for delete.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Time is counted when no progress is being made.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_del_timeout = 60;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define DEL_PAGESIZE MMU_PAGESIZE
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstruct del_status {
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *next;
29949e866e40b95795203f3ee46f44a197c946e4stevel memhandle_t handle;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile int its_done;
29949e866e40b95795203f3ee46f44a197c946e4stevel int done_error;
29949e866e40b95795203f3ee46f44a197c946e4stevel kcondvar_t ac_del_cv;
29949e866e40b95795203f3ee46f44a197c946e4stevel int del_timeout;
29949e866e40b95795203f3ee46f44a197c946e4stevel int del_noprogress;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_err_t cancel_code;
29949e866e40b95795203f3ee46f44a197c946e4stevel timeout_id_t to_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel pgcnt_t last_collected;
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct del_status *ac_del_list;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kmutex_t ac_del_mutex;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct del_status *
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_alloc_status()
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *dsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp = (struct del_status *)kmem_zalloc(sizeof (*dsp), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->next = ac_del_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_list = dsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_free_status(struct del_status *dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status **dspp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel dspp = &ac_del_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel while (*dspp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (*dspp == dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel dspp = &(*dspp)->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(*dspp == dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (*dspp == dsp) {
29949e866e40b95795203f3ee46f44a197c946e4stevel *dspp = dsp->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free((void *)dsp, sizeof (*dsp));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4steveldel_comp(void *arg, int error)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *dsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp = (struct del_status *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel {
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *adsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel for (adsp = ac_del_list; adsp != NULL; adsp = adsp->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (adsp == dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(adsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->its_done = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->done_error = error;
29949e866e40b95795203f3ee46f44a197c946e4stevel cv_signal(&dsp->ac_del_cv);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*ARGSUSED*/
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4steveldel_to_scan(void *arg)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *dsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int do_cancel;
29949e866e40b95795203f3ee46f44a197c946e4stevel memdelstat_t dstat;
29949e866e40b95795203f3ee46f44a197c946e4stevel int err;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp = arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel {
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *adsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel for (adsp = ac_del_list; adsp != NULL; adsp = adsp->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (adsp == dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(adsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel do_cancel = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel err = kphysm_del_status(dsp->handle, &dstat);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->its_done) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((err == KPHYSM_OK) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (dsp->last_collected != dstat.collected)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->del_noprogress = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->last_collected = dstat.collected;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->del_noprogress++;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->del_noprogress >= dsp->del_timeout) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->cancel_code == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->cancel_code = AC_ERR_TIMEOUT;
29949e866e40b95795203f3ee46f44a197c946e4stevel do_cancel = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!do_cancel)
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->to_id = timeout(del_to_scan, arg, hz);
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->to_id = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (do_cancel)
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) kphysm_del_cancel(dsp->handle);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4steveldel_to_start(struct del_status *dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->del_timeout != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->to_id = timeout(del_to_scan, dsp, hz);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4steveldel_to_stop(struct del_status *dsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel timeout_id_t tid;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel while ((tid = dsp->to_id) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->to_id = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) untimeout(tid);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_bank_add_span(
29949e866e40b95795203f3ee46f44a197c946e4stevel memhandle_t handle,
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_cfga_pkt_t *pkt)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t decode;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t bank_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t base;
29949e866e40b95795203f3ee46f44a197c946e4stevel pgcnt_t npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel int errs;
29949e866e40b95795203f3ee46f44a197c946e4stevel int ret;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *asp = pkt->softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t ilv;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Cannot delete interleaved banks at the moment.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ilv = (pkt->bank == Bank0) ?
29949e866e40b95795203f3ee46f44a197c946e4stevel INTLV0(*asp->ac_memctl) : INTLV1(*asp->ac_memctl);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ilv != 1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_MEM_DEINTLV);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Determine the physical location of the selected bank
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel decode = (pkt->bank == Bank0) ?
29949e866e40b95795203f3ee46f44a197c946e4stevel *asp->ac_memdecode0 : *asp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel bank_size = GRP_UK2SPAN(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel base = base_pa >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel npgs = bank_size >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Delete the pages from the cage growth list.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = kcage_range_delete(base, npgs);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ret != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TODO: Should this be a separate error? */
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_KPM_NONRELOC);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Add to delete memory list.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((errs = kphysm_del_span(handle, base, npgs)) != KPHYSM_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(errs));
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Restore the pages to the cage growth list.
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO: We should not unconditionally add back
29949e866e40b95795203f3ee46f44a197c946e4stevel * if we conditionally add at memory add time.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
85f5803819bea86c07827a9544494e4ad327d95ddp errs = kcage_range_add(base, npgs, KCAGE_DOWN);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TODO: deal with error return. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errs != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(errs));
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "ac_del_bank_add_span(): "
29949e866e40b95795203f3ee46f44a197c946e4stevel "board %d, bank %d, "
29949e866e40b95795203f3ee46f44a197c946e4stevel "kcage_range_add() returned %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->softsp->board, pkt->bank, errs);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_bank_add_cage(
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *del,
29949e866e40b95795203f3ee46f44a197c946e4stevel enum ac_bank_id bank)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t decode;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t bank_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t base;
29949e866e40b95795203f3ee46f44a197c946e4stevel pgcnt_t npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel int errs;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *asp = (struct ac_soft_state *)(del->ac_softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Determine the physical location of the selected bank
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel decode = (bank == Bank0) ? *asp->ac_memdecode0 : *asp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel bank_size = GRP_UK2SPAN(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel base = base_pa >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel npgs = bank_size >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Restore the pages to the cage growth list.
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO: We should not unconditionally add back
29949e866e40b95795203f3ee46f44a197c946e4stevel * if we conditionally add at memory add time.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
85f5803819bea86c07827a9544494e4ad327d95ddp errs = kcage_range_add(base, npgs, KCAGE_DOWN);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TODO: deal with error return. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errs != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "ac_del_bank_add_cage(): "
29949e866e40b95795203f3ee46f44a197c946e4stevel "board %d, bank %d, "
29949e866e40b95795203f3ee46f44a197c946e4stevel "kcage_range_add() returned %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel del->sc.board, bank, errs);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_bank_run(struct del_status *dsp, ac_cfga_pkt_t *pkt)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int errs;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->its_done = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((errs = kphysm_del_start(dsp->handle, del_comp, (void *)dsp)) !=
29949e866e40b95795203f3ee46f44a197c946e4stevel KPHYSM_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(errs));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Wait for it to complete. */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel del_to_start(dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel while (!dsp->its_done) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!cv_wait_sig(&dsp->ac_del_cv, &ac_del_mutex)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->cancel_code == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->cancel_code = AC_ERR_INTR;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel errs = kphysm_del_cancel(dsp->handle);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errs != KPHYSM_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(errs == KPHYSM_ENOTRUNNING);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the loop exited due to a signal, we must continue to wait
29949e866e40b95795203f3ee46f44a197c946e4stevel * using cv_wait() as the signal is pending until syscall exit.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel while (!dsp->its_done) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cv_wait(&dsp->ac_del_cv, &ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->done_error != KPHYSM_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(dsp->done_error));
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((dsp->done_error == KPHYSM_ECANCELLED) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (dsp->done_error == KPHYSM_EREFUSED)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel errs = EINTR;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dsp->cancel_code != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, dsp->cancel_code);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel errs = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel errs = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel del_to_stop(dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_del_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (errs);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * set the memory to known state for debugging
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_bank_write_pattern(struct bd_list *del, enum ac_bank_id bank)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t decode;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t limit_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t bank_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t current_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t base_va;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t fill_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *asp = (struct ac_soft_state *)(del->ac_softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel int linesize;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Determine the physical location of the selected bank
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel decode = (bank == Bank0) ? *asp->ac_memdecode0 : *asp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel bank_size = GRP_UK2SPAN(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel limit_pa = base_pa + bank_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel linesize = cpunodes[CPU->cpu_id].ecache_linesize;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We need a page_va and a fill buffer for this operation
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel base_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel fill_buf = kmem_zalloc(DEL_PAGESIZE, KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel {
29949e866e40b95795203f3ee46f44a197c946e4stevel typedef uint32_t patt_t;
29949e866e40b95795203f3ee46f44a197c946e4stevel patt_t *bf, *bfe, patt;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel bf = (patt_t *)fill_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel bfe = (patt_t *)((char *)fill_buf + DEL_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel patt = 0xbeaddeed;
29949e866e40b95795203f3ee46f44a197c946e4stevel while (bf < bfe)
29949e866e40b95795203f3ee46f44a197c946e4stevel *bf++ = patt;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * 'empty' the memory
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_disable();
29949e866e40b95795203f3ee46f44a197c946e4stevel for (current_pa = base_pa; current_pa < limit_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel current_pa += DEL_PAGESIZE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map current pa */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mapin(current_pa, base_va);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill the target page */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_blkcopy(fill_buf, base_va,
29949e866e40b95795203f3ee46f44a197c946e4stevel DEL_PAGESIZE/linesize, linesize);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* tear down translation */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_unmap(base_va);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel kpreempt_enable();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * clean up temporary resources
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Distinguish the fill buf from memory deleted! */
29949e866e40b95795203f3ee46f44a197c946e4stevel typedef uint32_t patt_t;
29949e866e40b95795203f3ee46f44a197c946e4stevel patt_t *bf, *bfe, patt;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel bf = (patt_t *)fill_buf;
29949e866e40b95795203f3ee46f44a197c946e4stevel bfe = (patt_t *)((char *)fill_buf + DEL_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel patt = 0xbeadfeed;
29949e866e40b95795203f3ee46f44a197c946e4stevel while (bf < bfe)
29949e866e40b95795203f3ee46f44a197c946e4stevel *bf++ = patt;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(fill_buf, DEL_PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel vmem_free(heap_arena, base_va, PAGESIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_memory(ac_cfga_pkt_t *pkt)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *board;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_mem_info *mem_info;
29949e866e40b95795203f3ee46f44a197c946e4stevel int busy_set;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct del_status *dsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel memdelstat_t dstat;
29949e866e40b95795203f3ee46f44a197c946e4stevel int retval;
29949e866e40b95795203f3ee46f44a197c946e4stevel int r_errs;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *asp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!kcage_on) {
29949e866e40b95795203f3ee46f44a197c946e4stevel static int cage_msg_done = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!cage_msg_done) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cage_msg_done = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "ac: memory delete"
29949e866e40b95795203f3ee46f44a197c946e4stevel " refused: cage is off");
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(KPHYSM_ENONRELOC));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp = ac_del_alloc_status();
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((retval = kphysm_del_gethandle(&dsp->handle)) != KPHYSM_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_free_status(dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, ac_kpm_err_cvt(retval));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel busy_set = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bdlist_lock(pkt->softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (board == NULL || board->ac_softsp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto out;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(pkt->softsp == board->ac_softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel asp = pkt->softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the board is of the correct type */
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (board->sc.type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case MEM_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD_TYPE);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto out;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify the memory condition is acceptable */
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info = &asp->bank[pkt->bank];
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!MEM_BOARD_VISIBLE(board) || mem_info->busy ||
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_busy(pkt->softsp->board) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->rstate != SYSC_CFGA_RSTATE_CONNECTED ||
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->ostate != SYSC_CFGA_OSTATE_CONFIGURED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_ERR_SET(pkt, AC_ERR_BD_STATE);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto out;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((dsp->del_timeout = pkt->cmd_cfga.arg) == -1)
29949e866e40b95795203f3ee46f44a197c946e4stevel dsp->del_timeout = ac_del_timeout;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * at this point, we have an available bank to del.
29949e866e40b95795203f3ee46f44a197c946e4stevel * mark it busy and initiate the del function.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->busy = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel busy_set = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_del_bank_add_span(dsp->handle, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevelout:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (retval != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel r_errs = kphysm_del_release(dsp->handle);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(r_errs == KPHYSM_OK);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (busy_set) {
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bdlist_lock(pkt->softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(board != NULL && board->ac_softsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(board->sc.type == CPU_BOARD ||
29949e866e40b95795203f3ee46f44a197c946e4stevel board->sc.type == MEM_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(asp ==
29949e866e40b95795203f3ee46f44a197c946e4stevel (struct ac_soft_state *)(board->ac_softsp));
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info = &asp->bank[pkt->bank];
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(mem_info->busy != FALSE);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(mem_info->ostate == SYSC_CFGA_OSTATE_CONFIGURED);
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->busy = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_free_status(dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) kphysm_del_status(dsp->handle, &dstat);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_del_bank_run(dsp, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel r_errs = kphysm_del_release(dsp->handle);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(r_errs == KPHYSM_OK);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bdlist_lock(pkt->softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(board != NULL && board->ac_softsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(board->sc.type == CPU_BOARD || board->sc.type == MEM_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(asp == (struct ac_soft_state *)(board->ac_softsp));
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info = &asp->bank[pkt->bank];
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(mem_info->busy != FALSE);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(mem_info->ostate == SYSC_CFGA_OSTATE_CONFIGURED);
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->busy = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (retval == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->status_change = ddi_get_time();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_del_clean) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* DEBUG - set memory to known state */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_bank_write_pattern(board, pkt->bank);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Restore the pages to the cage growth list.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_bank_add_cage(board, pkt->bank);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_free_status(dsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel}