4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * CDDL HEADER START
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * The contents of this file are subject to the terms of the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Common Development and Distribution License (the "License").
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * You may not use this file except in compliance with the License.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * or http://www.opensolaris.org/os/licensing.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * See the License for the specific language governing permissions
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * and limitations under the License.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * When distributing Covered Code, include this CDDL HEADER in each
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * If applicable, add the following below this CDDL HEADER, with the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * fields enclosed by brackets "[]" replaced with your own identifying
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * information: Portions Copyright [yyyy] [name of copyright owner]
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * CDDL HEADER END
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Use is subject to license terms.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * IO Performance Counter Driver
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#include <sys/types.h>
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#include <sys/ddi.h>
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#include <sys/modctl.h>
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#include "iospc.h"
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/* Debugging level. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#ifdef DEBUG
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint iospc_debug = 0;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#endif /* DEBUG */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/* State structure anchor. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Luvoid *iospc_state_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int iospc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int iospc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int iospc_create_name_kstat(iospc_grp_t *grp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic void iospc_delete_name_kstats(kstat_t **name_kstats_pp,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int num_kstats);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic kstat_t *iospc_create_cntr_kstat(char *name, int dev_inst,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int (*update)(kstat_t *, int), iospc_ksinfo_t *ksinfop, int num_pics);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int iospc_kstat_update(kstat_t *ksp, int rw);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic kstat_t *iospc_create_picN_kstat(char *mod_name, int pic,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu uint64_t mask, int num_ev, iospc_event_t *ev_array);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_grp_t **iospc_leaf_grps = NULL;
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint iospc_kstat_inited = 0;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lukmutex_t iospc_mutex;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic struct dev_ops iospc_ops = {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu DEVO_REV,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu 0,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu nulldev,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu nulldev,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu nulldev,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_attach,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_detach,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu nodev,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu NULL,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu NULL,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu nodev
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu};
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Luextern struct mod_ops mod_driverops;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic struct modldrv md = {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu &mod_driverops,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "IO Perf Counter Driver",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu &iospc_ops,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu};
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic struct modlinkage ml = {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu MODREV_1,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void *)&md,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu NULL
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu};
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * One-time module-wide initialization.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu_init(void)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int rval;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Initialize per-leaf soft state pointer. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((rval = ddi_soft_state_init(&iospc_state_p,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu sizeof (iospc_t), 1)) != DDI_SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (rval);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* If all checks out, install the module. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((rval = mod_install(&ml)) != DDI_SUCCESS) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_soft_state_fini(&iospc_state_p);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (rval);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_init(&iospc_mutex, NULL, MUTEX_DRIVER, NULL);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * One-time module-wide cleanup, after last detach is done.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu_fini(void)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int rval;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Remove the module first as this operation is the only thing here
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * which can fail.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu rval = mod_remove(&ml);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (rval != DDI_SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (rval);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_leaf_grps != NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_fini();
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_enter(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_inited = 0;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void) rfios_unbind_group();
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_leaf_grps = NULL;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_exit(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_destroy(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Free px soft state */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_soft_state_fini(&iospc_state_p);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu_info(struct modinfo *modinfop)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (mod_info(&ml, modinfop));
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Per-instance initialization. Suspend/resume not supported.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_t *iospc_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int instance = ddi_get_instance(dip);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu char *ptr;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_attach: enter\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu switch (cmd) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu case DDI_RESUME:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu case DDI_ATTACH:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Initialize one-time kstat structures. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_enter(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (!iospc_kstat_inited) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu 0, "compatible", &ptr)) != DDI_PROP_SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto bad_property;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((strcmp(ptr, "SUNW,ktios-pr") == 0) ||
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (strcmp(ptr, "SUNW,rfios-pr") == 0)) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_leaf_grps = rfios_bind_group();
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu } else {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_prop_free(ptr);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto bad_property;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_prop_free(ptr);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_kstat_init() != DDI_SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto bad_kstat_init;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_inited++;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_exit(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (ddi_soft_state_zalloc(iospc_state_p, instance) !=
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu DDI_SUCCESS) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto bad_softstate;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_p = (iospc_t *)ddi_get_soft_state(iospc_state_p,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu instance);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_p->iospc_dip = dip;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Set up kstats. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_kstat_attach(iospc_p) != DDI_SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto bad_kstat_attach;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_attach: exit SUCCESS\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lubad_kstat_attach:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void) ddi_soft_state_free(iospc_state_p, instance);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lubad_softstate:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_fini();
4df55fde49134f9735f84011f23a767c75e393c7Janie Lubad_kstat_init:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lubad_property:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu mutex_enter(&iospc_mutex);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_attach: exit FAILURE\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu default:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Per-instance cleanup. Suspend/resume not supported.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int instance = ddi_get_instance(dip);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_detach: enter\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_t *iospc_p = (iospc_t *)ddi_get_soft_state(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_state_p, instance);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu switch (cmd) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu case DDI_SUSPEND:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu case DDI_DETACH:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_detach(iospc_p);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void) ddi_soft_state_free(iospc_state_p, instance);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_detach: exit - SUCCESS\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu default:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: iospc_detach: exit - FAILURE\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu#define PIC_STR_LEN 5 /* Size of a PICx name string. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * One-time initialization for this module.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_kstat_init()
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t **grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t *grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: kstat_init: enter\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Initialize the name kstats for each group, drawing upon the table
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * for values.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (grp_pp = iospc_leaf_grps; *grp_pp != NULL; grp_pp++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p = *grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("Setting up group for %s\n", grp_p->grp_name);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Create basic pic event-type pair. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->name_kstats_pp = kmem_zalloc((grp_p->num_counters *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu sizeof (kstat_t)), KM_SLEEP);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_create_name_kstat(grp_p) != DDI_SUCCESS) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_fini();
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1("iospc: init: failure exit\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: kstat_init: success exit\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Per-instance initialization for this module.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Luint
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_kstat_attach(iospc_t *iospc_p)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t **grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t *grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_ksinfo_t *ksinfo_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int i;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: kstat_attach %d: enter\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_get_instance(iospc_p->iospc_dip));
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Set up kstats for each group. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (i = 0, grp_pp = iospc_leaf_grps; *grp_pp != NULL; i++, grp_pp++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (i >= IOSPC_MAX_NUM_GRPS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto err;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p = *grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * ksinfo_p keeps all info needed by iospc_kstat_update,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * which is fired off asynchronously on demand by the kstat
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * framework.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ksinfo_p = (iospc_ksinfo_t *)kmem_zalloc(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu sizeof (iospc_ksinfo_t), KM_SLEEP);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ksinfo_p->iospc_p = iospc_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ksinfo_p->grp_p = grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Also save in state structure, for later cleanup. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_p->iospc_ksinfo_p[i] = ksinfo_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* Create counter kstats */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ksinfo_p->cntr_ksp = iospc_create_cntr_kstat(grp_p->grp_name,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ddi_get_instance(iospc_p->iospc_dip),
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_update, ksinfo_p, grp_p->num_counters);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (ksinfo_p->cntr_ksp == NULL)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto err;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->access_init(iospc_p, ksinfo_p) != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto err;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: kstat_attach: success exit\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Luerr:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_kstat_detach(iospc_p);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc: kstat_attach: failure exit\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Create the name kstats for each group.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_create_name_kstat(iospc_grp_t *grp_p)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int i;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (i = 0; i < grp_p->num_counters; i++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->name_kstats_pp[i] = iospc_create_picN_kstat(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->grp_name, i,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->fields_p[i].event_offset,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->fields_p[i].num_events,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->fields_p[i].events_p);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->name_kstats_pp[i] == NULL)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_FAILURE);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (DDI_SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Create the picN kstat. Returns a pointer to the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * kstat which the driver must store to allow it
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * to be deleted when necessary.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic kstat_t *
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_create_picN_kstat(char *mod_name, int pic, uint64_t ev_offset,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int num_ev, iospc_event_t *ev_array)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int event;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu char pic_name[PIC_STR_LEN];
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_t *picN_ksp = NULL;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu struct kstat_named *pic_named_data;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void) snprintf(pic_name, PIC_STR_LEN, "pic%1d", pic);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((picN_ksp = kstat_create(mod_name, 0, pic_name,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "bus", KSTAT_TYPE_NAMED, num_ev, NULL)) == NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (NULL);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* NOTE: Number of events is assumed to always be non-zero. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu pic_named_data = (struct kstat_named *)picN_ksp->ks_data;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Fill up data section of the kstat
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Write event names and their associated pcr masks.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * num_ev - 1 is because CLEAR_PIC is added separately.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (event = 0; event < num_ev - 1; event++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu pic_named_data[event].value.ui64 =
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ev_array[event].value << ev_offset;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_named_init(&pic_named_data[event],
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu ev_array[event].name, KSTAT_DATA_UINT64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * add the clear_pic entry
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu pic_named_data[event].value.ui64 =
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (uint64_t)~(ev_array[event].value << ev_offset);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_named_init(&pic_named_data[event], ev_array[event].name,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu KSTAT_DATA_UINT64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_install(picN_ksp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (picN_ksp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Create the "counters" kstat.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic kstat_t *
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_create_cntr_kstat(char *name, int dev_inst,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int (*update)(kstat_t *, int), iospc_ksinfo_t *ksinfop, int num_pics)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int i;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu char pic_str[PIC_STR_LEN];
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu struct kstat *counters_ksp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu struct kstat_named *counters_named_data;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc_create_cntr_kstat: name: %s instance: %d\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu name, dev_inst);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Size of kstat is num_pics + 1. extra one for pcr.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((counters_ksp = kstat_create(name, dev_inst, "counters", "bus",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu KSTAT_TYPE_NAMED, num_pics + 1, KSTAT_FLAG_WRITABLE)) == NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (NULL);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu counters_named_data = (struct kstat_named *)(counters_ksp->ks_data);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_named_init(&counters_named_data[0], "pcr", KSTAT_DATA_UINT64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (i = 0; i < num_pics; i++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (void) snprintf(pic_str, PIC_STR_LEN, "pic%1d", i);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_named_init(&counters_named_data[i+1], pic_str,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu KSTAT_DATA_UINT64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Store the reg type and other info. in the kstat's private field
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * so that they are available to the update function.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu counters_ksp->ks_private = (void *)ksinfop;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu counters_ksp->ks_update = update;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_install(counters_ksp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (counters_ksp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Program a performance counter.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu *
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * reggroup is which type of counter.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * counter is the counter number.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * event is the event to program for that counter.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_perfcnt_program(iospc_t *iospc_p, iospc_grp_t *grp_p,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_ksinfo_t *ksinfo_p, uint64_t new_events)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu uint64_t old_events;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int rval = SUCCESS;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu uint64_t event_mask;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int counter;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "iospc_perfcnt_program enter: new_events:0x%" PRIx64 "\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu new_events);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((rval = grp_p->access(iospc_p, ksinfo_p->arg, IOSPC_REG_READ,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->regoff, &old_events)) != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto done_pgm;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1(" old_events:0x%" PRIx64 "\n", old_events);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (counter = 0; counter < grp_p->num_counters; counter++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->counters_p[counter].zero_regoff == NO_REGISTER)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu continue;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu event_mask = grp_p->regsel_p->fields_p[counter].event_mask <<
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->fields_p[counter].event_offset;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "grp:%s, counter:%d, zero_regoff:0x%lx, "
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "event_mask:0x%" PRIx64 ", old&mask:0x%lx, "
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "new&mask:0x%lx\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->grp_name, counter,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->counters_p[counter].zero_regoff,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu event_mask, old_events & event_mask,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu new_events & event_mask);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((old_events & event_mask) ==
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (new_events & event_mask))
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu continue;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1("Zeroing counter %d\n", counter);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((rval = grp_p->access(iospc_p, ksinfo_p->arg,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_REG_WRITE, grp_p->counters_p[counter].zero_regoff,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu &grp_p->counters_p[counter].zero_value)) != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto done_pgm;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (old_events != new_events) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1("old != new, setting event reg %ld to 0x%lx\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->regoff, new_events);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if ((rval = grp_p->access(iospc_p, ksinfo_p->arg,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_REG_WRITE, grp_p->regsel_p->regoff, &new_events))
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu != SUCCESS) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "Write of new event data failed, "
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "select reg offset: %ld\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->regoff);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu goto done_pgm;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Ludone_pgm:
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG1("iospc_perfcnt_program: returning status %d.\n", rval);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (rval);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu/*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * kstat update function. Handles reads/writes
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * from/to kstat.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic int
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_kstat_update(kstat_t *ksp, int rw)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu struct kstat_named *data_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int counter;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_ksinfo_t *ksinfop = ksp->ks_private;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t *grp_p = ksinfop->grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_t *iospc_p = ksinfop->iospc_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p = (struct kstat_named *)ksp->ks_data;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (rw == KSTAT_WRITE) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc_kstat_update: wr %ld\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p[0].value.ui64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /*
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * Fields without programmable events won't be zeroed as
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu * iospc_perfcnt_program is what zeros them.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* This group has programmable events. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->regsel_p->regoff != NO_REGISTER) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("write: regoff has valid register\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_perfcnt_program(iospc_p, grp_p, ksinfop,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p[0].value.ui64) != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (EIO);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu } else { /* Read the event register and all of the counters. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu /* This group has programmable events. */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->regsel_p->regoff != NO_REGISTER) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("read: regoff has valid register\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->access(iospc_p, ksinfop->arg, IOSPC_REG_READ,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->regsel_p->regoff, &data_p[0].value.ui64)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (EIO);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu } else
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p[0].value.ui64 = 0ull;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc_kstat_update: rd event %lx\n",
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p[0].value.ui64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (counter = 0; counter < grp_p->num_counters; counter++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->access(iospc_p, ksinfop->arg, IOSPC_REG_READ,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->counters_p[counter].regoff,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu &data_p[counter + 1].value.ui64) != SUCCESS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (EIO);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("cntr%d, off:0x%lx, val:0x%lx\n", counter,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->counters_p[counter].regoff,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu data_p[counter + 1].value.ui64);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return (SUCCESS);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Luvoid
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_kstat_fini()
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t **grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t *grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int j;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc_kstat_fini called\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (j = 0, grp_pp = iospc_leaf_grps; *grp_pp != NULL; j++, grp_pp++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p = *grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (grp_p->name_kstats_pp != NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_delete_name_kstats(grp_p->name_kstats_pp,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->num_counters);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kmem_free(grp_p->name_kstats_pp,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->num_counters * sizeof (kstat_t));
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->name_kstats_pp = NULL;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lustatic void
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_delete_name_kstats(kstat_t **name_kstats_pp, int num_kstats)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int i;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (name_kstats_pp != NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (i = 0; i < num_kstats; i++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (name_kstats_pp[i] != NULL)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_delete(name_kstats_pp[i]);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Luvoid
4df55fde49134f9735f84011f23a767c75e393c7Janie Luiospc_kstat_detach(iospc_t *iospc_p)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu{
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t **grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_grp_t *grp_p;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu int i;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu IOSPC_DBG2("iospc_kstat_detach called\n");
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu for (i = 0, grp_pp = iospc_leaf_grps; *grp_pp != NULL; i++, grp_pp++) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (i >= IOSPC_MAX_NUM_GRPS)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu return;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p = *grp_pp;
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_p->iospc_ksinfo_p[i] != NULL) {
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu grp_p->access_fini(iospc_p, iospc_p->iospc_ksinfo_p[i]);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu if (iospc_p->iospc_ksinfo_p[i]->cntr_ksp != NULL)
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kstat_delete(
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu iospc_p->iospc_ksinfo_p[i]->cntr_ksp);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu kmem_free(iospc_p->iospc_ksinfo_p[i],
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu sizeof (iospc_ksinfo_t));
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu }
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu}