17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5c2623971Sscarter * Common Development and Distribution License (the "License"). 6c2623971Sscarter * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*fc0105deSJames Anderson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Implementation of ri_init routine for obtaining mapping 287c478bd9Sstevel@tonic-gate * of system board attachment points to physical devices and to 297c478bd9Sstevel@tonic-gate * the Reconfiguration Coordination Manager (RCM) client usage 307c478bd9Sstevel@tonic-gate * of these devices. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <kstat.h> 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <sys/sbd_ioctl.h> 387c478bd9Sstevel@tonic-gate #include "rsrc_info_impl.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * Occupant types exported by cfgadm sbd plugin via 427c478bd9Sstevel@tonic-gate * config_admin(3CFGADM). 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate #define SBD_CM_CPU "cpu" 457c478bd9Sstevel@tonic-gate #define SBD_CM_MEM "memory" 467c478bd9Sstevel@tonic-gate #define SBD_CM_IO "io" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * RCM abstract resource names. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate #define RCM_MEM_ALL "SUNW_memory" 527c478bd9Sstevel@tonic-gate #define RCM_CPU_ALL "SUNW_cpu" 537c478bd9Sstevel@tonic-gate #define RCM_CPU RCM_CPU_ALL"/cpu" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #define KBYTE 1024 567c478bd9Sstevel@tonic-gate #define MBYTE 1048576 577c478bd9Sstevel@tonic-gate #define USAGE_ALLOC_SIZE 128 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * define to allow io_cm_info to return NODE is NULL to ri_init, 617c478bd9Sstevel@tonic-gate * in order to skip over nodes w/unattached drivers 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate #define RI_NODE_NIL 1 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * This code is CMP aware as it parses the 677c478bd9Sstevel@tonic-gate * cfgadm info field for individual cpuids. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate #define CPUID_SEP "," 707c478bd9Sstevel@tonic-gate #define CPU_INFO_FMT "cpuid=%s speed=%d ecache=%d" 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate typedef struct { 737c478bd9Sstevel@tonic-gate cfga_list_data_t *cfga_list_data; 747c478bd9Sstevel@tonic-gate int nlist; 757c478bd9Sstevel@tonic-gate } apd_t; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate typedef struct { 787c478bd9Sstevel@tonic-gate long pagesize; 797c478bd9Sstevel@tonic-gate long syspages; 807c478bd9Sstevel@tonic-gate long sysmb; 817c478bd9Sstevel@tonic-gate } mem_stat_t; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #define ms_syspages m_stat.syspages 847c478bd9Sstevel@tonic-gate #define ms_pagesize m_stat.pagesize 857c478bd9Sstevel@tonic-gate #define ms_sysmb m_stat.sysmb 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate typedef int32_t cpuid_t; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate typedef struct { 907c478bd9Sstevel@tonic-gate int cpuid_max; /* maximum cpuid value */ 91*fc0105deSJames Anderson int ecache_curr; /* cached during tree walk */ 927c478bd9Sstevel@tonic-gate int *ecache_sizes; /* indexed by cpuid */ 937c478bd9Sstevel@tonic-gate } ecache_info_t; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate typedef struct { 967c478bd9Sstevel@tonic-gate rcm_handle_t *hdl; 977c478bd9Sstevel@tonic-gate rcm_info_t *offline_query_info; 987c478bd9Sstevel@tonic-gate char **rlist; 997c478bd9Sstevel@tonic-gate int nrlist; 1007c478bd9Sstevel@tonic-gate cpuid_t *cpus; 1017c478bd9Sstevel@tonic-gate int ncpus; 1027c478bd9Sstevel@tonic-gate int ndevs; 1037c478bd9Sstevel@tonic-gate uint_t query_pages; 1047c478bd9Sstevel@tonic-gate mem_stat_t m_stat; 1057c478bd9Sstevel@tonic-gate ecache_info_t ecache_info; 1067c478bd9Sstevel@tonic-gate } rcmd_t; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate typedef struct { 1097c478bd9Sstevel@tonic-gate const char *rsrc; 1107c478bd9Sstevel@tonic-gate const char *info; 1117c478bd9Sstevel@tonic-gate } usage_t; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* Lookup table entry for matching IO devices to RCM resource usage */ 1147c478bd9Sstevel@tonic-gate typedef struct { 1157c478bd9Sstevel@tonic-gate int index; /* index into the table array */ 1167c478bd9Sstevel@tonic-gate di_node_t node; /* associated devinfo node */ 1177c478bd9Sstevel@tonic-gate char *name; /* device full path name */ 1187c478bd9Sstevel@tonic-gate int n_usage; 1197c478bd9Sstevel@tonic-gate usage_t *usage; 1207c478bd9Sstevel@tonic-gate } lookup_entry_t; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate typedef struct { 1237c478bd9Sstevel@tonic-gate int n_entries; 1247c478bd9Sstevel@tonic-gate int n_slots; 1257c478bd9Sstevel@tonic-gate lookup_entry_t *table; 1267c478bd9Sstevel@tonic-gate } lookup_table_t; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate typedef struct { 1297c478bd9Sstevel@tonic-gate int err; 1307c478bd9Sstevel@tonic-gate di_node_t node; 1317c478bd9Sstevel@tonic-gate char *pathbuf; 1327c478bd9Sstevel@tonic-gate lookup_table_t *table; 1337c478bd9Sstevel@tonic-gate di_devlink_handle_t linkhd; 1347c478bd9Sstevel@tonic-gate } devinfo_arg_t; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static int dyn_ap_ids(char *, cfga_list_data_t **, int *); 1377c478bd9Sstevel@tonic-gate static int rcm_init(rcmd_t *, apd_t [], int, int); 1387c478bd9Sstevel@tonic-gate static void rcm_fini(rcmd_t *); 1397c478bd9Sstevel@tonic-gate static int rcm_query_init(rcmd_t *, apd_t [], int); 1407c478bd9Sstevel@tonic-gate static int cap_request(ri_hdl_t *, rcmd_t *); 1417c478bd9Sstevel@tonic-gate static int syscpus(cpuid_t **, int *); 1427c478bd9Sstevel@tonic-gate static int cpu_cap_request(ri_hdl_t *, rcmd_t *); 1437c478bd9Sstevel@tonic-gate static int mem_cap_request(ri_hdl_t *, rcmd_t *); 1447c478bd9Sstevel@tonic-gate static int (*cm_rcm_qpass_func(cfga_type_t))(cfga_list_data_t *, rcmd_t *); 1457c478bd9Sstevel@tonic-gate static int cpu_rcm_qpass(cfga_list_data_t *, rcmd_t *); 1467c478bd9Sstevel@tonic-gate static int mem_rcm_qpass(cfga_list_data_t *, rcmd_t *); 1477c478bd9Sstevel@tonic-gate static int io_rcm_qpass(cfga_list_data_t *, rcmd_t *); 1487c478bd9Sstevel@tonic-gate static int (*cm_info_func(cfga_type_t))(ri_ap_t *, cfga_list_data_t *, int, 1497c478bd9Sstevel@tonic-gate rcmd_t *); 1507c478bd9Sstevel@tonic-gate static int cpu_cm_info(ri_ap_t *, cfga_list_data_t *, int, rcmd_t *); 15161ddd3aaSscarter static int i_cpu_cm_info(processorid_t, int, int, ri_ap_t *, rcmd_t *); 1527c478bd9Sstevel@tonic-gate static int mem_cm_info(ri_ap_t *, cfga_list_data_t *, int, rcmd_t *); 1537c478bd9Sstevel@tonic-gate static int io_cm_info(ri_ap_t *, cfga_list_data_t *, int, rcmd_t *); 1547c478bd9Sstevel@tonic-gate static int ident_leaf(di_node_t); 1557c478bd9Sstevel@tonic-gate static int mk_drv_inst(di_node_t, char [], char *); 1567c478bd9Sstevel@tonic-gate static int devinfo_node_walk(di_node_t, void *); 1577c478bd9Sstevel@tonic-gate static int devinfo_minor_walk(di_node_t, di_minor_t, void *); 1587c478bd9Sstevel@tonic-gate static int devinfo_devlink_walk(di_devlink_t, void *); 1597c478bd9Sstevel@tonic-gate static int add_rcm_clients(ri_client_t **, rcmd_t *, rcm_info_t *, int, int *); 1607c478bd9Sstevel@tonic-gate static int rcm_ignore(char *, char *); 1617c478bd9Sstevel@tonic-gate static int add_query_state(rcmd_t *, ri_client_t *, const char *, const char *); 1627c478bd9Sstevel@tonic-gate static int state2query(int); 1637c478bd9Sstevel@tonic-gate static void dev_list_append(ri_dev_t **, ri_dev_t *); 1647c478bd9Sstevel@tonic-gate static void dev_list_cpu_insert(ri_dev_t **, ri_dev_t *, processorid_t); 1657c478bd9Sstevel@tonic-gate static rcm_info_tuple_t *tuple_lookup(rcmd_t *, const char *, const char *); 1667c478bd9Sstevel@tonic-gate static ri_ap_t *ri_ap_alloc(char *, ri_hdl_t *); 1677c478bd9Sstevel@tonic-gate static ri_dev_t *ri_dev_alloc(void); 1687c478bd9Sstevel@tonic-gate static ri_dev_t *io_dev_alloc(char *); 1697c478bd9Sstevel@tonic-gate static ri_client_t *ri_client_alloc(char *, char *); 1707c478bd9Sstevel@tonic-gate static void apd_tbl_free(apd_t [], int); 1717c478bd9Sstevel@tonic-gate static char *pstate2str(int); 1727c478bd9Sstevel@tonic-gate static int ecache_info_init(ecache_info_t *); 1737c478bd9Sstevel@tonic-gate static int find_cpu_nodes(di_node_t, void *); 1747c478bd9Sstevel@tonic-gate static int prop_lookup_int(di_node_t, di_prom_handle_t, char *, int **); 1757c478bd9Sstevel@tonic-gate static int add_lookup_entry(lookup_table_t *, const char *, di_node_t); 1767c478bd9Sstevel@tonic-gate static int table_compare_names(const void *, const void *); 1777c478bd9Sstevel@tonic-gate static int table_compare_indices(const void *, const void *); 1787c478bd9Sstevel@tonic-gate static lookup_entry_t *lookup(lookup_table_t *table, const char *); 1797c478bd9Sstevel@tonic-gate static int add_usage(lookup_entry_t *, const char *, rcm_info_tuple_t *); 1807c478bd9Sstevel@tonic-gate static void empty_table(lookup_table_t *); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate #ifdef DEBUG 1837c478bd9Sstevel@tonic-gate static void dump_apd_tbl(FILE *, apd_t *, int); 1847c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static struct { 1877c478bd9Sstevel@tonic-gate char *type; 1887c478bd9Sstevel@tonic-gate int (*cm_info)(ri_ap_t *, cfga_list_data_t *, int, rcmd_t *); 1897c478bd9Sstevel@tonic-gate int (*cm_rcm_qpass)(cfga_list_data_t *, rcmd_t *); 1907c478bd9Sstevel@tonic-gate } cm_ctl[] = { 1917c478bd9Sstevel@tonic-gate {SBD_CM_CPU, cpu_cm_info, cpu_rcm_qpass}, 1927c478bd9Sstevel@tonic-gate {SBD_CM_MEM, mem_cm_info, mem_rcm_qpass}, 1937c478bd9Sstevel@tonic-gate {SBD_CM_IO, io_cm_info, io_rcm_qpass} 1947c478bd9Sstevel@tonic-gate }; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * Table of known info string prefixes for RCM modules that do not 1987c478bd9Sstevel@tonic-gate * represent actual resource usage, but instead provide name translations 1997c478bd9Sstevel@tonic-gate * or sequencing within the RCM namespace. Since RCM provides no way to 2007c478bd9Sstevel@tonic-gate * filter these out, we must maintain this hack. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate static char *rcm_info_filter[] = { 2037c478bd9Sstevel@tonic-gate "Network interface", /* Network naming module */ 2047c478bd9Sstevel@tonic-gate NULL 2057c478bd9Sstevel@tonic-gate }; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Allocate snapshot handle. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate int 2127c478bd9Sstevel@tonic-gate ri_init(int n_apids, char **ap_ids, int flags, ri_hdl_t **hdlp) 2137c478bd9Sstevel@tonic-gate { 2147c478bd9Sstevel@tonic-gate int i, j; 2157c478bd9Sstevel@tonic-gate ri_hdl_t *ri_hdl; 2167c478bd9Sstevel@tonic-gate ri_ap_t *ap_hdl; 2177c478bd9Sstevel@tonic-gate rcmd_t *rcm = NULL; 2187c478bd9Sstevel@tonic-gate cfga_list_data_t *cfga_ldata; 2197c478bd9Sstevel@tonic-gate apd_t *apd, *apd_tbl = NULL; 2207c478bd9Sstevel@tonic-gate int (*cm_info)(ri_ap_t *, cfga_list_data_t *, 2217c478bd9Sstevel@tonic-gate int, rcmd_t *); 2227c478bd9Sstevel@tonic-gate int rv = RI_SUCCESS; 2237c478bd9Sstevel@tonic-gate int cm_info_rv; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (n_apids <= 0 || ap_ids == NULL || hdlp == NULL) 2267c478bd9Sstevel@tonic-gate return (RI_INVAL); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (flags & ~RI_REQ_MASK) 2297c478bd9Sstevel@tonic-gate return (RI_NOTSUP); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate *hdlp = NULL; 2327c478bd9Sstevel@tonic-gate if ((ri_hdl = calloc(1, sizeof (*ri_hdl))) == NULL || 2337c478bd9Sstevel@tonic-gate (rcm = calloc(1, sizeof (*rcm))) == NULL || 2347c478bd9Sstevel@tonic-gate (apd_tbl = calloc(n_apids, sizeof (*apd_tbl))) == NULL) { 2357c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s\n", strerror(errno))); 2367c478bd9Sstevel@tonic-gate rv = RI_FAILURE; 2377c478bd9Sstevel@tonic-gate goto out; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Create mapping of boards to components. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate for (i = 0, apd = apd_tbl; i < n_apids; i++, apd++) { 2447c478bd9Sstevel@tonic-gate if (dyn_ap_ids(ap_ids[i], &apd->cfga_list_data, 2457c478bd9Sstevel@tonic-gate &apd->nlist) == -1) { 2467c478bd9Sstevel@tonic-gate rv = RI_INVAL; 2477c478bd9Sstevel@tonic-gate goto out; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate #ifdef DEBUG 2517c478bd9Sstevel@tonic-gate dump_apd_tbl(stderr, apd_tbl, n_apids); 2527c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if (rcm_init(rcm, apd_tbl, n_apids, flags) != 0) { 2557c478bd9Sstevel@tonic-gate rv = RI_FAILURE; 2567c478bd9Sstevel@tonic-gate goto out; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Best effort attempt to read cpu ecache sizes from 2617c478bd9Sstevel@tonic-gate * OBP/Solaris device trees. These are later looked up 2627c478bd9Sstevel@tonic-gate * in i_cpu_cm_info(). 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate (void) ecache_info_init(&rcm->ecache_info); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate for (i = 0, apd = apd_tbl; i < n_apids; i++, apd++) { 2677c478bd9Sstevel@tonic-gate if ((ap_hdl = ri_ap_alloc(ap_ids[i], ri_hdl)) == NULL) { 2687c478bd9Sstevel@tonic-gate rv = RI_FAILURE; 2697c478bd9Sstevel@tonic-gate goto out; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * Add component info based on occupant type. Note all 2747c478bd9Sstevel@tonic-gate * passes through the apd table skip over the first 2757c478bd9Sstevel@tonic-gate * cfgadm_list_data entry, which is the static system board 2767c478bd9Sstevel@tonic-gate * attachment point. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate for (j = 1, cfga_ldata = &apd->cfga_list_data[1]; 2797c478bd9Sstevel@tonic-gate j < apd->nlist; j++, cfga_ldata++) { 2807c478bd9Sstevel@tonic-gate if (cfga_ldata->ap_o_state != CFGA_STAT_CONFIGURED) { 2817c478bd9Sstevel@tonic-gate continue; 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate if ((cm_info = 2857c478bd9Sstevel@tonic-gate cm_info_func(cfga_ldata->ap_type)) != NULL) { 2867c478bd9Sstevel@tonic-gate cm_info_rv = 2877c478bd9Sstevel@tonic-gate (*cm_info)(ap_hdl, cfga_ldata, flags, rcm); 2887c478bd9Sstevel@tonic-gate if (cm_info_rv != 0) { 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * If we cannot obtain info for the ap, 2917c478bd9Sstevel@tonic-gate * skip it and do not fail the entire 2927c478bd9Sstevel@tonic-gate * operation. This case occurs when the 2937c478bd9Sstevel@tonic-gate * driver for a device is not attached: 2947c478bd9Sstevel@tonic-gate * di_init() returns failed back to 2957c478bd9Sstevel@tonic-gate * io_cm_info(). 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate if (cm_info_rv == RI_NODE_NIL) 2987c478bd9Sstevel@tonic-gate continue; 2997c478bd9Sstevel@tonic-gate else { 3007c478bd9Sstevel@tonic-gate rv = RI_FAILURE; 3017c478bd9Sstevel@tonic-gate goto out; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if ((flags & RI_INCLUDE_QUERY) && cap_request(ri_hdl, rcm) != 0) 3097c478bd9Sstevel@tonic-gate rv = RI_FAILURE; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate out: 3127c478bd9Sstevel@tonic-gate if (apd_tbl != NULL) 3137c478bd9Sstevel@tonic-gate apd_tbl_free(apd_tbl, n_apids); 3147c478bd9Sstevel@tonic-gate if (rcm != NULL) 3157c478bd9Sstevel@tonic-gate rcm_fini(rcm); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if (rv == RI_SUCCESS) 3187c478bd9Sstevel@tonic-gate *hdlp = ri_hdl; 3197c478bd9Sstevel@tonic-gate else 3207c478bd9Sstevel@tonic-gate ri_fini(ri_hdl); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate return (rv); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * Map static board attachment point to dynamic attachment points (components). 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate static int 3297c478bd9Sstevel@tonic-gate dyn_ap_ids(char *ap_id, cfga_list_data_t **ap_id_list, int *nlist) 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate cfga_err_t cfga_err; 3327c478bd9Sstevel@tonic-gate char *errstr; 3337c478bd9Sstevel@tonic-gate char *opts = "parsable"; 3347c478bd9Sstevel@tonic-gate char *listops = "class=sbd"; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate cfga_err = config_list_ext(1, &ap_id, ap_id_list, nlist, 3377c478bd9Sstevel@tonic-gate opts, listops, &errstr, CFGA_FLAG_LIST_ALL); 3387c478bd9Sstevel@tonic-gate if (cfga_err != CFGA_OK) { 3397c478bd9Sstevel@tonic-gate dprintf((stderr, "config_list_ext: %s\n", 3407c478bd9Sstevel@tonic-gate config_strerror(cfga_err))); 3417c478bd9Sstevel@tonic-gate return (-1); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate return (0); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Initialize rcm handle, memory stats. Cache query result if necessary. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate static int 3517c478bd9Sstevel@tonic-gate rcm_init(rcmd_t *rcm, apd_t apd_tbl[], int napds, int flags) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate longlong_t ii; 3547c478bd9Sstevel@tonic-gate int rv = 0; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate rcm->offline_query_info = NULL; 3577c478bd9Sstevel@tonic-gate rcm->rlist = NULL; 3587c478bd9Sstevel@tonic-gate rcm->cpus = NULL; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm->hdl) != RCM_SUCCESS) { 3617c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_alloc_handle (errno=%d)\n", errno)); 3627c478bd9Sstevel@tonic-gate return (-1); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if ((rcm->ms_pagesize = sysconf(_SC_PAGE_SIZE)) == -1 || 3667c478bd9Sstevel@tonic-gate (rcm->ms_syspages = sysconf(_SC_PHYS_PAGES)) == -1) { 3677c478bd9Sstevel@tonic-gate dprintf((stderr, "sysconf: %s\n", strerror(errno))); 3687c478bd9Sstevel@tonic-gate return (-1); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate ii = (longlong_t)rcm->ms_pagesize * rcm->ms_syspages; 3717c478bd9Sstevel@tonic-gate rcm->ms_sysmb = (int)((ii+MBYTE-1) / MBYTE); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (flags & RI_INCLUDE_QUERY) 3747c478bd9Sstevel@tonic-gate rv = rcm_query_init(rcm, apd_tbl, napds); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate return (rv); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate static void 3807c478bd9Sstevel@tonic-gate rcm_fini(rcmd_t *rcm) 3817c478bd9Sstevel@tonic-gate { 3827c478bd9Sstevel@tonic-gate char **cpp; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate assert(rcm != NULL); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (rcm->offline_query_info != NULL) 3877c478bd9Sstevel@tonic-gate rcm_free_info(rcm->offline_query_info); 3887c478bd9Sstevel@tonic-gate if (rcm->hdl != NULL) 3897c478bd9Sstevel@tonic-gate rcm_free_handle(rcm->hdl); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (rcm->rlist != NULL) { 3927c478bd9Sstevel@tonic-gate for (cpp = rcm->rlist; *cpp != NULL; cpp++) 3937c478bd9Sstevel@tonic-gate s_free(*cpp); 3947c478bd9Sstevel@tonic-gate free(rcm->rlist); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate s_free(rcm->cpus); 3987c478bd9Sstevel@tonic-gate free(rcm); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate #define NODENAME_CMP "cmp" 4027c478bd9Sstevel@tonic-gate #define NODENAME_SSM "ssm" 4037c478bd9Sstevel@tonic-gate #define PROP_CPUID "cpuid" 4047c478bd9Sstevel@tonic-gate #define PROP_DEVICE_TYPE "device-type" 4057c478bd9Sstevel@tonic-gate #define PROP_ECACHE_SIZE "ecache-size" 4067c478bd9Sstevel@tonic-gate #define PROP_L2_CACHE_SIZE "l2-cache-size" 4077c478bd9Sstevel@tonic-gate #define PROP_L3_CACHE_SIZE "l3-cache-size" 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate typedef struct { 4107c478bd9Sstevel@tonic-gate di_node_t root; 4117c478bd9Sstevel@tonic-gate di_prom_handle_t ph; 4127c478bd9Sstevel@tonic-gate ecache_info_t *ecache_info; 4137c478bd9Sstevel@tonic-gate } di_arg_t; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * The ecache sizes for individual cpus are read from the 4177c478bd9Sstevel@tonic-gate * OBP/Solaris device trees. This info cannot be derived 4187c478bd9Sstevel@tonic-gate * from the cfgadm_sbd cpu attachment point ecache info, 4197c478bd9Sstevel@tonic-gate * which may be a sum of multiple cores for CMP. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate static int 4227c478bd9Sstevel@tonic-gate ecache_info_init(ecache_info_t *ec) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate di_arg_t di_arg; 4257c478bd9Sstevel@tonic-gate di_prom_handle_t ph = DI_PROM_HANDLE_NIL; 4267c478bd9Sstevel@tonic-gate di_node_t root = DI_NODE_NIL; 4277c478bd9Sstevel@tonic-gate int cpuid_max, rv = 0; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate assert(ec != NULL && ec->cpuid_max == 0 && ec->ecache_sizes == NULL); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if ((cpuid_max = sysconf(_SC_CPUID_MAX)) == -1) { 4327c478bd9Sstevel@tonic-gate dprintf((stderr, "sysconf fail: %s\n", strerror(errno))); 4337c478bd9Sstevel@tonic-gate rv = -1; 4347c478bd9Sstevel@tonic-gate goto done; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 4387c478bd9Sstevel@tonic-gate dprintf((stderr, "di_init fail: %s\n", strerror(errno))); 4397c478bd9Sstevel@tonic-gate rv = -1; 4407c478bd9Sstevel@tonic-gate goto done; 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) { 4447c478bd9Sstevel@tonic-gate dprintf((stderr, "di_prom_init fail: %s\n", strerror(errno))); 4457c478bd9Sstevel@tonic-gate rv = -1; 4467c478bd9Sstevel@tonic-gate goto done; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate if ((ec->ecache_sizes = calloc(cpuid_max + 1, sizeof (int))) == NULL) { 4507c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc fail: %s\n", strerror(errno))); 4517c478bd9Sstevel@tonic-gate rv = -1; 4527c478bd9Sstevel@tonic-gate goto done; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate ec->cpuid_max = cpuid_max; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate dprintf((stderr, "cpuid_max is set to %d\n", ec->cpuid_max)); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate di_arg.ph = ph; 4597c478bd9Sstevel@tonic-gate di_arg.root = root; 4607c478bd9Sstevel@tonic-gate di_arg.ecache_info = ec; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if (di_walk_node(root, DI_WALK_CLDFIRST, (void *)&di_arg, 4637c478bd9Sstevel@tonic-gate find_cpu_nodes) != 0) { 4647c478bd9Sstevel@tonic-gate dprintf((stderr, "di_walk_node fail: %s\n", strerror(errno))); 4657c478bd9Sstevel@tonic-gate rv = -1; 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate done: 4697c478bd9Sstevel@tonic-gate if (root != DI_NODE_NIL) 4707c478bd9Sstevel@tonic-gate di_fini(root); 4717c478bd9Sstevel@tonic-gate if (ph != DI_PROM_HANDLE_NIL) 4727c478bd9Sstevel@tonic-gate di_prom_fini(ph); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate return (rv); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Libdevinfo node walk callback for reading ecache size 4797c478bd9Sstevel@tonic-gate * properties for cpu device nodes. Subtrees not containing 4807c478bd9Sstevel@tonic-gate * cpu nodes are filtered out. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate static int 4837c478bd9Sstevel@tonic-gate find_cpu_nodes(di_node_t node, void *arg) 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate char *name; 4867c478bd9Sstevel@tonic-gate int *cpuid, *ecache; 4877c478bd9Sstevel@tonic-gate di_arg_t *di_arg = (di_arg_t *)arg; 4887c478bd9Sstevel@tonic-gate ecache_info_t *ec = di_arg->ecache_info; 4897c478bd9Sstevel@tonic-gate di_prom_handle_t ph = di_arg->ph; 490*fc0105deSJames Anderson int walk_child = 0; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 4937c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate if (node == di_arg->root) { 4977c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (di_nodeid(node) == DI_PSEUDO_NODEID) { 5017c478bd9Sstevel@tonic-gate return (DI_WALK_PRUNECHILD); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate name = di_node_name(node); 5057c478bd9Sstevel@tonic-gate if (name != NULL) { 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * CMP nodes will be the parent of cpu nodes. On some platforms, 5087c478bd9Sstevel@tonic-gate * cpu nodes will be under the ssm node. In either case, 5097c478bd9Sstevel@tonic-gate * continue searching this subtree. 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate if (strncmp(name, NODENAME_SSM, strlen(NODENAME_SSM)) == 0 || 5127c478bd9Sstevel@tonic-gate strncmp(name, NODENAME_CMP, strlen(NODENAME_CMP)) == 0) { 5137c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate dprintf((stderr, "find_cpu_nodes: node=%p, name=%s, binding_name=%s\n", 5187c478bd9Sstevel@tonic-gate node, di_node_name(node), di_binding_name(node))); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate /* 5217c478bd9Sstevel@tonic-gate * Ecache size property name differs with processor implementation. 5227c478bd9Sstevel@tonic-gate * Panther has both L2 and L3, so check for L3 first to differentiate 5237c478bd9Sstevel@tonic-gate * from Jaguar, which has only L2. 5247c478bd9Sstevel@tonic-gate */ 525*fc0105deSJames Anderson if (prop_lookup_int(node, ph, PROP_ECACHE_SIZE, &ecache) == 0 || 5267c478bd9Sstevel@tonic-gate prop_lookup_int(node, ph, PROP_L3_CACHE_SIZE, &ecache) == 0 || 527*fc0105deSJames Anderson prop_lookup_int(node, ph, PROP_L2_CACHE_SIZE, &ecache) == 0) { 528*fc0105deSJames Anderson /* 529*fc0105deSJames Anderson * On some platforms the cache property is in the core 530*fc0105deSJames Anderson * node while the cpuid is in the child cpu node. It may 531*fc0105deSJames Anderson * be needed while processing this node or a child node. 532*fc0105deSJames Anderson */ 533*fc0105deSJames Anderson ec->ecache_curr = *ecache; 534*fc0105deSJames Anderson walk_child = 1; 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 537*fc0105deSJames Anderson if (prop_lookup_int(node, ph, PROP_CPUID, &cpuid) == 0) { 538*fc0105deSJames Anderson 539*fc0105deSJames Anderson assert(ec != NULL && ec->ecache_sizes != NULL && 540*fc0105deSJames Anderson *cpuid <= ec->cpuid_max); 541*fc0105deSJames Anderson 542*fc0105deSJames Anderson if (ec->ecache_curr != 0) { 543*fc0105deSJames Anderson ec->ecache_sizes[*cpuid] = ec->ecache_curr; 544*fc0105deSJames Anderson 545*fc0105deSJames Anderson } 546*fc0105deSJames Anderson } 547*fc0105deSJames Anderson 548*fc0105deSJames Anderson return (walk_child ? DI_WALK_CONTINUE : DI_WALK_PRUNECHILD); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /* 5527c478bd9Sstevel@tonic-gate * Given a di_node_t, call the appropriate int property lookup routine. 5537c478bd9Sstevel@tonic-gate * Note: This lookup fails if the int property has multiple value entries. 5547c478bd9Sstevel@tonic-gate */ 5557c478bd9Sstevel@tonic-gate static int 5567c478bd9Sstevel@tonic-gate prop_lookup_int(di_node_t node, di_prom_handle_t ph, char *propname, int **ival) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate int rv; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate rv = (di_nodeid(node) == DI_PROM_NODEID) ? 5617c478bd9Sstevel@tonic-gate di_prom_prop_lookup_ints(ph, node, propname, ival) : 5627c478bd9Sstevel@tonic-gate di_prop_lookup_ints(DDI_DEV_T_ANY, node, propname, ival); 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate return (rv == 1 ? 0 : -1); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * For offline queries, RCM must be given a list of all resources 5697c478bd9Sstevel@tonic-gate * so modules can have access to the full scope of the operation. 5707c478bd9Sstevel@tonic-gate * The rcm_get_info calls are made individually in order to map the 5717c478bd9Sstevel@tonic-gate * returned rcm_info_t's to physical devices. The rcm_request_offline 5727c478bd9Sstevel@tonic-gate * result is cached so the query state can be looked up as we process 5737c478bd9Sstevel@tonic-gate * the rcm_get_info calls. This routine also tallies up the amount of 5747c478bd9Sstevel@tonic-gate * memory going away and creates a list of cpu ids to be used 5757c478bd9Sstevel@tonic-gate * later for rcm_request_capacity_change. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate static int 5787c478bd9Sstevel@tonic-gate rcm_query_init(rcmd_t *rcm, apd_t apd_tbl[], int napds) 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate apd_t *apd; 5817c478bd9Sstevel@tonic-gate int i, j; 5827c478bd9Sstevel@tonic-gate cfga_list_data_t *cfga_ldata; 5837c478bd9Sstevel@tonic-gate int (*cm_rcm_qpass)(cfga_list_data_t *, rcmd_t *); 5847c478bd9Sstevel@tonic-gate #ifdef DEBUG 5857c478bd9Sstevel@tonic-gate char **cpp; 5867c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * Initial pass to size cpu and resource name arrays needed to 5907c478bd9Sstevel@tonic-gate * interface with RCM. Attachment point ids for CMP can represent 5917c478bd9Sstevel@tonic-gate * multiple cpus (and resource names). Instead of parsing the 5927c478bd9Sstevel@tonic-gate * cfgadm info field here, use the worse case that all component 5937c478bd9Sstevel@tonic-gate * attachment points are CMP. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate rcm->ndevs = 0; 5967c478bd9Sstevel@tonic-gate for (i = 0, apd = apd_tbl; i < napds; i++, apd++) { 5977c478bd9Sstevel@tonic-gate for (j = 1, cfga_ldata = &apd->cfga_list_data[1]; 5987c478bd9Sstevel@tonic-gate j < apd->nlist; j++, cfga_ldata++) { 5997c478bd9Sstevel@tonic-gate if (cfga_ldata->ap_o_state != CFGA_STAT_CONFIGURED) { 6007c478bd9Sstevel@tonic-gate continue; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate rcm->ndevs += SBD_MAX_CORES_PER_CMP; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* account for trailing NULL in rlist */ 6077c478bd9Sstevel@tonic-gate if (rcm->ndevs > 0 && 6087c478bd9Sstevel@tonic-gate ((rcm->cpus = calloc(rcm->ndevs, sizeof (cpuid_t))) == NULL || 6097c478bd9Sstevel@tonic-gate (rcm->rlist = calloc(rcm->ndevs + 1, sizeof (char *))) == NULL)) { 6107c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s\n", strerror(errno))); 6117c478bd9Sstevel@tonic-gate return (-1); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * Second pass to fill in the RCM resource and cpu lists. 6167c478bd9Sstevel@tonic-gate */ 6177c478bd9Sstevel@tonic-gate for (i = 0, apd = apd_tbl; i < napds; i++, apd++) { 6187c478bd9Sstevel@tonic-gate for (j = 1, cfga_ldata = &apd->cfga_list_data[1]; 6197c478bd9Sstevel@tonic-gate j < apd->nlist; j++, cfga_ldata++) { 6207c478bd9Sstevel@tonic-gate if (cfga_ldata->ap_o_state != CFGA_STAT_CONFIGURED) { 6217c478bd9Sstevel@tonic-gate continue; 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate if ((cm_rcm_qpass = 6247c478bd9Sstevel@tonic-gate cm_rcm_qpass_func(cfga_ldata->ap_type)) != NULL && 6257c478bd9Sstevel@tonic-gate (*cm_rcm_qpass)(cfga_ldata, rcm) != 0) { 6267c478bd9Sstevel@tonic-gate return (-1); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate if (rcm->nrlist == 0) 6327c478bd9Sstevel@tonic-gate return (0); 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * Cache query result. Since we are only interested in the 6367c478bd9Sstevel@tonic-gate * set of RCM clients processed and not their request status, 6377c478bd9Sstevel@tonic-gate * the return value is irrelevant. 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate (void) rcm_request_offline_list(rcm->hdl, rcm->rlist, 6407c478bd9Sstevel@tonic-gate RCM_QUERY|RCM_SCOPE, &rcm->offline_query_info); 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate #ifdef DEBUG 6437c478bd9Sstevel@tonic-gate dprintf((stderr, "RCM rlist: nrlist=%d\n", rcm->nrlist)); 6447c478bd9Sstevel@tonic-gate for (cpp = rcm->rlist, i = 0; *cpp != NULL; cpp++, i++) { 6457c478bd9Sstevel@tonic-gate dprintf((stderr, "rlist[%d]=%s\n", i, *cpp)); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate return (0); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate static int 6537c478bd9Sstevel@tonic-gate cap_request(ri_hdl_t *ri_hdl, rcmd_t *rcm) 6547c478bd9Sstevel@tonic-gate { 6557c478bd9Sstevel@tonic-gate return (((rcm->ncpus > 0 && cpu_cap_request(ri_hdl, rcm) != 0) || 6567c478bd9Sstevel@tonic-gate (rcm->query_pages > 0 && mem_cap_request(ri_hdl, rcm) != 0)) ? 6577c478bd9Sstevel@tonic-gate -1 : 0); 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate /* 6617c478bd9Sstevel@tonic-gate * RCM capacity change request for cpus. 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate static int 6647c478bd9Sstevel@tonic-gate cpu_cap_request(ri_hdl_t *ri_hdl, rcmd_t *rcm) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate cpuid_t *syscpuids, *newcpuids; 6677c478bd9Sstevel@tonic-gate int sysncpus, newncpus; 6687c478bd9Sstevel@tonic-gate rcm_info_t *rcm_info = NULL; 6697c478bd9Sstevel@tonic-gate int i, j, k; 6707c478bd9Sstevel@tonic-gate nvlist_t *nvl; 6717c478bd9Sstevel@tonic-gate int rv = 0; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* get all cpus in the system */ 6747c478bd9Sstevel@tonic-gate if (syscpus(&syscpuids, &sysncpus) == -1) 6757c478bd9Sstevel@tonic-gate return (-1); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate newncpus = sysncpus - rcm->ncpus; 6787c478bd9Sstevel@tonic-gate if ((newcpuids = calloc(newncpus, sizeof (cpuid_t))) == NULL) { 6797c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s", strerror(errno))); 6807c478bd9Sstevel@tonic-gate rv = -1; 6817c478bd9Sstevel@tonic-gate goto out; 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 6857c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_alloc fail\n")); 6867c478bd9Sstevel@tonic-gate rv = -1; 6877c478bd9Sstevel@tonic-gate goto out; 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * Construct the new cpu list. 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < sysncpus; i++) { 6947c478bd9Sstevel@tonic-gate for (k = 0; k < rcm->ncpus; k++) { 6957c478bd9Sstevel@tonic-gate if (rcm->cpus[k] == syscpuids[i]) { 6967c478bd9Sstevel@tonic-gate break; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate if (k == rcm->ncpus) { 7007c478bd9Sstevel@tonic-gate newcpuids[j++] = syscpuids[i]; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, "old_total", sysncpus) != 0 || 7057c478bd9Sstevel@tonic-gate nvlist_add_int32(nvl, "new_total", newncpus) != 0 || 7067c478bd9Sstevel@tonic-gate nvlist_add_int32_array(nvl, "old_cpu_list", syscpuids, 7077c478bd9Sstevel@tonic-gate sysncpus) != 0 || 7087c478bd9Sstevel@tonic-gate nvlist_add_int32_array(nvl, "new_cpu_list", newcpuids, 7097c478bd9Sstevel@tonic-gate newncpus) != 0) { 7107c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add fail\n")); 7117c478bd9Sstevel@tonic-gate rv = -1; 7127c478bd9Sstevel@tonic-gate goto out; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate #ifdef DEBUG 7167c478bd9Sstevel@tonic-gate dprintf((stderr, "old_total=%d\n", sysncpus)); 7177c478bd9Sstevel@tonic-gate for (i = 0; i < sysncpus; i++) { 7187c478bd9Sstevel@tonic-gate dprintf((stderr, "old_cpu_list[%d]=%d\n", i, syscpuids[i])); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate dprintf((stderr, "new_total=%d\n", newncpus)); 7217c478bd9Sstevel@tonic-gate for (i = 0; i < newncpus; i++) { 7227c478bd9Sstevel@tonic-gate dprintf((stderr, "new_cpu_list[%d]=%d\n", i, newcpuids[i])); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate (void) rcm_request_capacity_change(rcm->hdl, RCM_CPU_ALL, 7277c478bd9Sstevel@tonic-gate RCM_QUERY|RCM_SCOPE, nvl, &rcm_info); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate rv = add_rcm_clients(&ri_hdl->cpu_cap_clients, rcm, rcm_info, 0, NULL); 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate out: 7327c478bd9Sstevel@tonic-gate s_free(syscpuids); 7337c478bd9Sstevel@tonic-gate s_free(newcpuids); 7347c478bd9Sstevel@tonic-gate nvlist_free(nvl); 7357c478bd9Sstevel@tonic-gate if (rcm_info != NULL) 7367c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate return (rv); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate static int 7427c478bd9Sstevel@tonic-gate syscpus(cpuid_t **cpuids, int *ncpus) 7437c478bd9Sstevel@tonic-gate { 7447c478bd9Sstevel@tonic-gate kstat_t *ksp; 7457c478bd9Sstevel@tonic-gate kstat_ctl_t *kc; 7467c478bd9Sstevel@tonic-gate cpuid_t *cp; 7477c478bd9Sstevel@tonic-gate int i; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if ((*ncpus = sysconf(_SC_NPROCESSORS_CONF)) == -1) { 7507c478bd9Sstevel@tonic-gate dprintf((stderr, "sysconf: %s\n", errno)); 7517c478bd9Sstevel@tonic-gate return (-1); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL) { 7557c478bd9Sstevel@tonic-gate dprintf((stderr, "kstat_open fail\n")); 7567c478bd9Sstevel@tonic-gate return (-1); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate if ((cp = calloc(*ncpus, sizeof (cpuid_t))) == NULL) { 7607c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s\n", errno)); 7617c478bd9Sstevel@tonic-gate (void) kstat_close(kc); 7627c478bd9Sstevel@tonic-gate return (-1); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate for (i = 0, ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { 7667c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu_info") == 0) { 7677c478bd9Sstevel@tonic-gate cp[i++] = ksp->ks_instance; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate (void) kstat_close(kc); 7727c478bd9Sstevel@tonic-gate *cpuids = cp; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate return (0); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * RCM capacity change request for memory. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate static int 7817c478bd9Sstevel@tonic-gate mem_cap_request(ri_hdl_t *ri_hdl, rcmd_t *rcm) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate nvlist_t *nvl; 7847c478bd9Sstevel@tonic-gate rcm_info_t *rcm_info = NULL; 7857c478bd9Sstevel@tonic-gate long newpages; 7867c478bd9Sstevel@tonic-gate int rv = 0; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 7897c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_alloc fail\n")); 7907c478bd9Sstevel@tonic-gate return (-1); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate newpages = rcm->ms_syspages - rcm->query_pages; 7947c478bd9Sstevel@tonic-gate if (nvlist_add_int32(nvl, "page_size", rcm->ms_pagesize) != 0 || 7957c478bd9Sstevel@tonic-gate nvlist_add_int32(nvl, "old_pages", rcm->ms_syspages) != 0 || 7967c478bd9Sstevel@tonic-gate nvlist_add_int32(nvl, "new_pages", newpages) != 0) { 7977c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add fail\n")); 7987c478bd9Sstevel@tonic-gate nvlist_free(nvl); 7997c478bd9Sstevel@tonic-gate return (-1); 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate dprintf((stderr, "memory capacity change req: " 8037c478bd9Sstevel@tonic-gate "page_size=%d, old_pages=%d, new_pages=%d\n", 8047c478bd9Sstevel@tonic-gate rcm->ms_pagesize, rcm->ms_syspages, newpages)); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate (void) rcm_request_capacity_change(rcm->hdl, RCM_MEM_ALL, 8077c478bd9Sstevel@tonic-gate RCM_QUERY|RCM_SCOPE, nvl, &rcm_info); 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate rv = add_rcm_clients(&ri_hdl->mem_cap_clients, rcm, rcm_info, 0, NULL); 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate nvlist_free(nvl); 8127c478bd9Sstevel@tonic-gate if (rcm_info != NULL) 8137c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate return (rv); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate static int 8197c478bd9Sstevel@tonic-gate (*cm_rcm_qpass_func(cfga_type_t ap_type))(cfga_list_data_t *, rcmd_t *) 8207c478bd9Sstevel@tonic-gate { 8217c478bd9Sstevel@tonic-gate int i; 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cm_ctl) / sizeof (cm_ctl[0]); i++) { 8247c478bd9Sstevel@tonic-gate if (strcmp(cm_ctl[i].type, ap_type) == 0) { 8257c478bd9Sstevel@tonic-gate return (cm_ctl[i].cm_rcm_qpass); 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate return (NULL); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* 8327c478bd9Sstevel@tonic-gate * Save cpu ids and RCM abstract resource names. 8337c478bd9Sstevel@tonic-gate * Cpu ids will be used for the capacity change request. 8347c478bd9Sstevel@tonic-gate * Resource names will be used for the offline query. 8357c478bd9Sstevel@tonic-gate */ 8367c478bd9Sstevel@tonic-gate static int 8377c478bd9Sstevel@tonic-gate cpu_rcm_qpass(cfga_list_data_t *cfga_ldata, rcmd_t *rcm) 8387c478bd9Sstevel@tonic-gate { 8397c478bd9Sstevel@tonic-gate processorid_t cpuid; 8407c478bd9Sstevel@tonic-gate char *cpustr, *lasts, *rsrcname, rbuf[32]; 8417c478bd9Sstevel@tonic-gate char cbuf[CFGA_INFO_LEN]; 8427c478bd9Sstevel@tonic-gate int speed, ecache; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate assert(sscanf(cfga_ldata->ap_info, CPU_INFO_FMT, &cbuf, &speed, 8457c478bd9Sstevel@tonic-gate &ecache) == 3); 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate for (cpustr = (char *)strtok_r(cbuf, CPUID_SEP, &lasts); 8487c478bd9Sstevel@tonic-gate cpustr != NULL; 8497c478bd9Sstevel@tonic-gate cpustr = (char *)strtok_r(NULL, CPUID_SEP, &lasts)) { 8507c478bd9Sstevel@tonic-gate cpuid = atoi(cpustr); 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate (void) snprintf(rbuf, sizeof (rbuf), "%s%d", RCM_CPU, cpuid); 8537c478bd9Sstevel@tonic-gate if ((rsrcname = strdup(rbuf)) == NULL) { 8547c478bd9Sstevel@tonic-gate dprintf((stderr, "strdup fail\n")); 8557c478bd9Sstevel@tonic-gate return (-1); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate assert(rcm->nrlist < rcm->ndevs && rcm->ncpus < rcm->ndevs); 8587c478bd9Sstevel@tonic-gate rcm->rlist[rcm->nrlist++] = rsrcname; 8597c478bd9Sstevel@tonic-gate rcm->cpus[rcm->ncpus++] = (cpuid_t)cpuid; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate dprintf((stderr, "cpu_cm_info: cpuid=%d, rsrcname=%s", 8627c478bd9Sstevel@tonic-gate cpuid, rsrcname)); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate return (0); 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate /* 8697c478bd9Sstevel@tonic-gate * No RCM resource names for individual memory units, so 8707c478bd9Sstevel@tonic-gate * just add to offline query page count. 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate static int 8737c478bd9Sstevel@tonic-gate mem_rcm_qpass(cfga_list_data_t *cfga, rcmd_t *rcm) 8747c478bd9Sstevel@tonic-gate { 8757c478bd9Sstevel@tonic-gate char *cp; 8767c478bd9Sstevel@tonic-gate uint_t kbytes; 8777c478bd9Sstevel@tonic-gate longlong_t ii; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate if ((cp = strstr(cfga->ap_info, "size")) == NULL || 8807c478bd9Sstevel@tonic-gate sscanf(cp, "size=%u", &kbytes) != 1) { 8817c478bd9Sstevel@tonic-gate dprintf((stderr, "unknown sbd info format: %s\n", cp)); 8827c478bd9Sstevel@tonic-gate return (-1); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate ii = (longlong_t)kbytes * KBYTE; 8867c478bd9Sstevel@tonic-gate rcm->query_pages += (uint_t)(ii / rcm->ms_pagesize); 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate dprintf((stderr, "%s: npages=%u\n", cfga->ap_log_id, 8897c478bd9Sstevel@tonic-gate (uint_t)(ii / rcm->ms_pagesize))); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate return (0); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * Add physical I/O bus name to RCM resource list. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate static int 8987c478bd9Sstevel@tonic-gate io_rcm_qpass(cfga_list_data_t *cfga, rcmd_t *rcm) 8997c478bd9Sstevel@tonic-gate { 9007c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 9017c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 9027c478bd9Sstevel@tonic-gate char *rsrcname; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (sscanf(cfga->ap_info, "device=%s", path) != 1) { 9057c478bd9Sstevel@tonic-gate dprintf((stderr, "unknown sbd info format: %s\n", 9067c478bd9Sstevel@tonic-gate cfga->ap_info)); 9077c478bd9Sstevel@tonic-gate return (-1); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/devices%s", path); 9117c478bd9Sstevel@tonic-gate if ((rsrcname = strdup(buf)) == NULL) { 9127c478bd9Sstevel@tonic-gate dprintf((stderr, "strdup fail\n")); 9137c478bd9Sstevel@tonic-gate return (-1); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate assert(rcm->nrlist < rcm->ndevs); 9177c478bd9Sstevel@tonic-gate rcm->rlist[rcm->nrlist++] = rsrcname; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate return (0); 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate static int 9237c478bd9Sstevel@tonic-gate (*cm_info_func(cfga_type_t ap_type))(ri_ap_t *, cfga_list_data_t *, 9247c478bd9Sstevel@tonic-gate int, rcmd_t *) 9257c478bd9Sstevel@tonic-gate { 9267c478bd9Sstevel@tonic-gate int i; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (cm_ctl) / sizeof (cm_ctl[0]); i++) { 9297c478bd9Sstevel@tonic-gate if (strcmp(cm_ctl[i].type, ap_type) == 0) { 9307c478bd9Sstevel@tonic-gate return (cm_ctl[i].cm_info); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate return (NULL); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 9377c478bd9Sstevel@tonic-gate * Create cpu handle, adding properties exported by sbd plugin and 9387c478bd9Sstevel@tonic-gate * RCM client usage. 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9417c478bd9Sstevel@tonic-gate static int 9427c478bd9Sstevel@tonic-gate cpu_cm_info(ri_ap_t *ap, cfga_list_data_t *cfga, int flags, rcmd_t *rcm) 9437c478bd9Sstevel@tonic-gate { 9447c478bd9Sstevel@tonic-gate processorid_t cpuid; 9457c478bd9Sstevel@tonic-gate int speed, ecache, rv = 0; 9467c478bd9Sstevel@tonic-gate char buf[CFGA_INFO_LEN], *cpustr, *lasts; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate if (sscanf(cfga->ap_info, CPU_INFO_FMT, &buf, &speed, &ecache) != 3) { 9497c478bd9Sstevel@tonic-gate dprintf((stderr, "unknown sbd info format: %s\n", 9507c478bd9Sstevel@tonic-gate cfga->ap_info)); 9517c478bd9Sstevel@tonic-gate return (-1); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate /* parse cpuids */ 9557c478bd9Sstevel@tonic-gate for (cpustr = (char *)strtok_r(buf, CPUID_SEP, &lasts); 9567c478bd9Sstevel@tonic-gate cpustr != NULL; 9577c478bd9Sstevel@tonic-gate cpustr = (char *)strtok_r(NULL, CPUID_SEP, &lasts)) { 9587c478bd9Sstevel@tonic-gate cpuid = atoi(cpustr); 95961ddd3aaSscarter if ((rv = i_cpu_cm_info(cpuid, speed, ecache, ap, rcm)) != 0) { 9607c478bd9Sstevel@tonic-gate break; 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate return (rv); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate static int 96861ddd3aaSscarter i_cpu_cm_info(processorid_t cpuid, int speed, int ecache_cfga, ri_ap_t *ap, 96961ddd3aaSscarter rcmd_t *rcm) 9707c478bd9Sstevel@tonic-gate { 971*fc0105deSJames Anderson int ecache_mb = 0; 972*fc0105deSJames Anderson int ecache_kb = 0; 9737c478bd9Sstevel@tonic-gate char *state, buf[32]; 9747c478bd9Sstevel@tonic-gate processor_info_t cpu_info; 9757c478bd9Sstevel@tonic-gate ri_dev_t *cpu = NULL; 9767c478bd9Sstevel@tonic-gate rcm_info_t *rcm_info = NULL; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /* 9797c478bd9Sstevel@tonic-gate * Could have been unconfigured in the interim, so cannot 9807c478bd9Sstevel@tonic-gate * count on processor_info recognizing it. 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate state = (processor_info(cpuid, &cpu_info) == 0) ? 9837c478bd9Sstevel@tonic-gate pstate2str(cpu_info.pi_state) : "unknown"; 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate if ((cpu = ri_dev_alloc()) == NULL) { 9867c478bd9Sstevel@tonic-gate dprintf((stderr, "ri_dev_alloc failed\n")); 9877c478bd9Sstevel@tonic-gate return (-1); 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate 99061ddd3aaSscarter /* 99161ddd3aaSscarter * Assume the ecache_info table has the right e-cache size for 99261ddd3aaSscarter * this CPU. Use the value found in cfgadm (ecache_cfga) if not. 99361ddd3aaSscarter */ 9947c478bd9Sstevel@tonic-gate if (rcm->ecache_info.ecache_sizes != NULL) { 9957c478bd9Sstevel@tonic-gate assert(rcm->ecache_info.cpuid_max != 0 && 9967c478bd9Sstevel@tonic-gate cpuid <= rcm->ecache_info.cpuid_max); 997*fc0105deSJames Anderson ecache_mb = rcm->ecache_info.ecache_sizes[cpuid] / MBYTE; 998*fc0105deSJames Anderson ecache_kb = rcm->ecache_info.ecache_sizes[cpuid] / KBYTE; 9997c478bd9Sstevel@tonic-gate } 1000*fc0105deSJames Anderson 1001*fc0105deSJames Anderson if (ecache_mb == 0) { 1002*fc0105deSJames Anderson ecache_mb = ecache_cfga; 100361ddd3aaSscarter } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate dprintf((stderr, "i_cpu_cm_info: cpu(%d) ecache=%d MB\n", 10067c478bd9Sstevel@tonic-gate cpuid, ecache)); 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate if (nvlist_add_int32(cpu->conf_props, RI_CPU_ID, cpuid) != 0 || 10097c478bd9Sstevel@tonic-gate nvlist_add_int32(cpu->conf_props, RI_CPU_SPEED, speed) != 0 || 1010*fc0105deSJames Anderson nvlist_add_int32(cpu->conf_props, RI_CPU_ECACHE, ecache_mb) != 0 || 10117c478bd9Sstevel@tonic-gate nvlist_add_string(cpu->conf_props, RI_CPU_STATE, state) != 0) { 10127c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add fail\n")); 10137c478bd9Sstevel@tonic-gate ri_dev_free(cpu); 10147c478bd9Sstevel@tonic-gate return (-1); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 1017*fc0105deSJames Anderson /* 1018*fc0105deSJames Anderson * Report cache size in kilobyte units if available. This info is 1019*fc0105deSJames Anderson * added to support processors with cache sizes that are non-integer 1020*fc0105deSJames Anderson * megabyte multiples. 1021*fc0105deSJames Anderson */ 1022*fc0105deSJames Anderson if (ecache_kb != 0) { 1023*fc0105deSJames Anderson if (nvlist_add_int32(cpu->conf_props, RI_CPU_ECACHE_KBYTE, 1024*fc0105deSJames Anderson ecache_kb) != 0) { 1025*fc0105deSJames Anderson dprintf((stderr, "nvlist_add fail: %s\n", 1026*fc0105deSJames Anderson RI_CPU_ECACHE_KBYTE)); 1027*fc0105deSJames Anderson ri_dev_free(cpu); 1028*fc0105deSJames Anderson return (-1); 1029*fc0105deSJames Anderson } 1030*fc0105deSJames Anderson } 1031*fc0105deSJames Anderson 10327c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%d", RCM_CPU, cpuid); 10337c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_get_info(%s)\n", buf)); 10347c478bd9Sstevel@tonic-gate if (rcm_get_info(rcm->hdl, buf, RCM_INCLUDE_DEPENDENT, 10357c478bd9Sstevel@tonic-gate &rcm_info) != RCM_SUCCESS) { 10367c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_get_info (errno=%d)\n", errno)); 10377c478bd9Sstevel@tonic-gate ri_dev_free(cpu); 10387c478bd9Sstevel@tonic-gate if (rcm_info != NULL) 10397c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info); 10407c478bd9Sstevel@tonic-gate return (-1); 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate dev_list_cpu_insert(&ap->cpus, cpu, cpuid); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate return (0); 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate /* 10497c478bd9Sstevel@tonic-gate * Create memory handle, adding properties exported by sbd plugin. 10507c478bd9Sstevel@tonic-gate * No RCM tuples to be saved unless RCM is modified to export names 10517c478bd9Sstevel@tonic-gate * for individual memory units. 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10547c478bd9Sstevel@tonic-gate static int 10557c478bd9Sstevel@tonic-gate mem_cm_info(ri_ap_t *ap, cfga_list_data_t *cfga, int flags, rcmd_t *rcm) 10567c478bd9Sstevel@tonic-gate { 10577c478bd9Sstevel@tonic-gate ri_dev_t *mem; 10587c478bd9Sstevel@tonic-gate char *cp; 1059c2623971Sscarter char *cpval; 1060c2623971Sscarter int len; 10617c478bd9Sstevel@tonic-gate uint64_t base_addr; /* required */ 10627c478bd9Sstevel@tonic-gate int32_t size_kb; /* required */ 10637c478bd9Sstevel@tonic-gate int32_t perm_kb = 0; /* optional */ 1064c2623971Sscarter char target[CFGA_AP_LOG_ID_LEN] = ""; /* optional */ 10657c478bd9Sstevel@tonic-gate int32_t del_kb = 0; /* optional */ 10667c478bd9Sstevel@tonic-gate int32_t rem_kb = 0; /* optional */ 1067c2623971Sscarter char source[CFGA_AP_LOG_ID_LEN] = ""; /* optional */ 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate if (sscanf(cfga->ap_info, "address=0x%llx size=%u", &base_addr, 10707c478bd9Sstevel@tonic-gate &size_kb) != 2) { 10717c478bd9Sstevel@tonic-gate goto err_fmt; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if ((cp = strstr(cfga->ap_info, "permanent")) != NULL && 10757c478bd9Sstevel@tonic-gate sscanf(cp, "permanent=%u", &perm_kb) != 1) { 10767c478bd9Sstevel@tonic-gate goto err_fmt; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 1079c2623971Sscarter if ((cp = strstr(cfga->ap_info, "target")) != NULL) { 1080c2623971Sscarter if ((cpval = strstr(cp, "=")) == NULL) { 10817c478bd9Sstevel@tonic-gate goto err_fmt; 10827c478bd9Sstevel@tonic-gate } 1083c2623971Sscarter for (len = 0; cpval[len] != '\0' && cpval[len] != ' '; len++) { 1084c2623971Sscarter if (len >= CFGA_AP_LOG_ID_LEN) { 10857c478bd9Sstevel@tonic-gate goto err_fmt; 10867c478bd9Sstevel@tonic-gate } 1087c2623971Sscarter } 1088c2623971Sscarter if (sscanf(cp, "target=%s deleted=%u remaining=%u", &target, 1089c2623971Sscarter &del_kb, &rem_kb) != 3) { 1090c2623971Sscarter goto err_fmt; 1091c2623971Sscarter } 1092c2623971Sscarter } 1093c2623971Sscarter 1094c2623971Sscarter if ((cp = strstr(cfga->ap_info, "source")) != NULL) { 1095c2623971Sscarter if ((cpval = strstr(cp, "=")) == NULL) { 1096c2623971Sscarter goto err_fmt; 1097c2623971Sscarter } 1098c2623971Sscarter for (len = 0; cpval[len] != '\0' && cpval[len] != ' '; len++) { 1099c2623971Sscarter if (len >= CFGA_AP_LOG_ID_LEN) { 1100c2623971Sscarter goto err_fmt; 1101c2623971Sscarter } 1102c2623971Sscarter } 1103c2623971Sscarter if (sscanf(cp, "source=%s", &source) != 1) { 1104c2623971Sscarter goto err_fmt; 1105c2623971Sscarter } 1106c2623971Sscarter } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate dprintf((stderr, "%s: base=0x%llx, size=%u, permanent=%u\n", 11097c478bd9Sstevel@tonic-gate cfga->ap_log_id, base_addr, size_kb, perm_kb)); 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate if ((mem = ri_dev_alloc()) == NULL) 11127c478bd9Sstevel@tonic-gate return (-1); 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* 11157c478bd9Sstevel@tonic-gate * Convert memory sizes to MB (truncate). 11167c478bd9Sstevel@tonic-gate */ 11177c478bd9Sstevel@tonic-gate if (nvlist_add_uint64(mem->conf_props, RI_MEM_ADDR, base_addr) != 0 || 11187c478bd9Sstevel@tonic-gate nvlist_add_int32(mem->conf_props, RI_MEM_BRD, size_kb/KBYTE) != 0 || 11197c478bd9Sstevel@tonic-gate nvlist_add_int32(mem->conf_props, RI_MEM_PERM, 11207c478bd9Sstevel@tonic-gate perm_kb/KBYTE) != 0) { 11217c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failure\n")); 11227c478bd9Sstevel@tonic-gate ri_dev_free(mem); 11237c478bd9Sstevel@tonic-gate return (-1); 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 1126c2623971Sscarter if (target[0] != '\0' && 11277c478bd9Sstevel@tonic-gate (nvlist_add_string(mem->conf_props, RI_MEM_TARG, target) != 0 || 11287c478bd9Sstevel@tonic-gate nvlist_add_int32(mem->conf_props, RI_MEM_DEL, del_kb/KBYTE) != 0 || 11297c478bd9Sstevel@tonic-gate nvlist_add_int32(mem->conf_props, RI_MEM_REMAIN, 11307c478bd9Sstevel@tonic-gate rem_kb/KBYTE) != 0)) { 11317c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failure\n")); 11327c478bd9Sstevel@tonic-gate ri_dev_free(mem); 11337c478bd9Sstevel@tonic-gate return (-1); 11347c478bd9Sstevel@tonic-gate } 11357c478bd9Sstevel@tonic-gate 1136c2623971Sscarter if (source[0] != '\0' && 1137c2623971Sscarter nvlist_add_string(mem->conf_props, RI_MEM_SRC, source) != 0) { 11387c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failure\n")); 11397c478bd9Sstevel@tonic-gate ri_dev_free(mem); 11407c478bd9Sstevel@tonic-gate return (-1); 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate /* 11447c478bd9Sstevel@tonic-gate * XXX - move this property to attachment point hdl? 11457c478bd9Sstevel@tonic-gate */ 11467c478bd9Sstevel@tonic-gate if (nvlist_add_int32(mem->conf_props, RI_MEM_DOMAIN, 11477c478bd9Sstevel@tonic-gate rcm->ms_sysmb) != 0) { 11487c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add failure\n")); 11497c478bd9Sstevel@tonic-gate ri_dev_free(mem); 11507c478bd9Sstevel@tonic-gate return (-1); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate dev_list_append(&ap->mems, mem); 11547c478bd9Sstevel@tonic-gate return (0); 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate err_fmt: 11577c478bd9Sstevel@tonic-gate dprintf((stderr, "unknown sbd info format: %s\n", cfga->ap_info)); 11587c478bd9Sstevel@tonic-gate return (-1); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate /* 11627c478bd9Sstevel@tonic-gate * Initiate a libdevinfo walk on the IO bus path. 11637c478bd9Sstevel@tonic-gate * XXX - investigate performance using two threads here: one thread to do the 11647c478bd9Sstevel@tonic-gate * libdevinfo snapshot and treewalk; and one thread to get RCM usage info 11657c478bd9Sstevel@tonic-gate */ 11667c478bd9Sstevel@tonic-gate static int 11677c478bd9Sstevel@tonic-gate io_cm_info(ri_ap_t *ap, cfga_list_data_t *cfga, int flags, rcmd_t *rcm) 11687c478bd9Sstevel@tonic-gate { 11697c478bd9Sstevel@tonic-gate int i; 11707c478bd9Sstevel@tonic-gate int j; 11717c478bd9Sstevel@tonic-gate int k; 11727c478bd9Sstevel@tonic-gate int set_size; 11737c478bd9Sstevel@tonic-gate int retval = 0; 11747c478bd9Sstevel@tonic-gate int n_usage; 11757c478bd9Sstevel@tonic-gate devinfo_arg_t di_arg; 11767c478bd9Sstevel@tonic-gate lookup_table_t devicetable; 11777c478bd9Sstevel@tonic-gate lookup_entry_t *deventry; 11787c478bd9Sstevel@tonic-gate lookup_entry_t *lastdeventry; 11797c478bd9Sstevel@tonic-gate ri_dev_t *io = NULL; 11807c478bd9Sstevel@tonic-gate ri_client_t *client; 11817c478bd9Sstevel@tonic-gate ri_client_t *tmp; 11827c478bd9Sstevel@tonic-gate di_devlink_handle_t linkhd = NULL; 11837c478bd9Sstevel@tonic-gate di_node_t root = DI_NODE_NIL; 11847c478bd9Sstevel@tonic-gate di_node_t node = DI_NODE_NIL; 11857c478bd9Sstevel@tonic-gate rcm_info_tuple_t *rcm_tuple; 11867c478bd9Sstevel@tonic-gate rcm_info_t *rcm_info = NULL; 11877c478bd9Sstevel@tonic-gate const char *rcm_rsrc = NULL; 11887c478bd9Sstevel@tonic-gate char drv_inst[MAXPATHLEN]; 11897c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 11907c478bd9Sstevel@tonic-gate char pathbuf[MAXPATHLEN]; 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate dprintf((stderr, "io_cm_info(%s)\n", cfga->ap_log_id)); 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate /* Extract devfs path from cfgadm information */ 11957c478bd9Sstevel@tonic-gate if (sscanf(cfga->ap_info, "device=%s\n", path) != 1) { 11967c478bd9Sstevel@tonic-gate dprintf((stderr, "unknown sbd info format: %s\n", 11977c478bd9Sstevel@tonic-gate cfga->ap_info)); 11987c478bd9Sstevel@tonic-gate return (-1); 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* Initialize empty device lookup table */ 12027c478bd9Sstevel@tonic-gate devicetable.n_entries = 0; 12037c478bd9Sstevel@tonic-gate devicetable.n_slots = 0; 12047c478bd9Sstevel@tonic-gate devicetable.table = NULL; 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate /* Get libdevinfo snapshot */ 12077c478bd9Sstevel@tonic-gate dprintf((stderr, "di_init(%s)\n", path)); 12087c478bd9Sstevel@tonic-gate if ((root = di_init(path, DINFOCPYALL)) == DI_NODE_NIL) { 12097c478bd9Sstevel@tonic-gate dprintf((stderr, "di_init: %s\n", strerror(errno))); 12107c478bd9Sstevel@tonic-gate retval = RI_NODE_NIL; /* tell ri_init to skip this node */ 12117c478bd9Sstevel@tonic-gate goto end; 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate /* 12157c478bd9Sstevel@tonic-gate * Map in devlinks database. 12167c478bd9Sstevel@tonic-gate * XXX - This could be moved to ri_init() for better performance. 12177c478bd9Sstevel@tonic-gate */ 12187c478bd9Sstevel@tonic-gate dprintf((stderr, "di_devlink_init()\n")); 12197c478bd9Sstevel@tonic-gate if ((linkhd = di_devlink_init(NULL, 0)) == NULL) { 12207c478bd9Sstevel@tonic-gate dprintf((stderr, "di_devlink_init: %s\n", strerror(errno))); 12217c478bd9Sstevel@tonic-gate retval = -1; 12227c478bd9Sstevel@tonic-gate goto end; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate /* Initialize argument for devinfo treewalk */ 12267c478bd9Sstevel@tonic-gate di_arg.err = 0; 12277c478bd9Sstevel@tonic-gate di_arg.node = DI_NODE_NIL; 12287c478bd9Sstevel@tonic-gate di_arg.pathbuf = pathbuf; 12297c478bd9Sstevel@tonic-gate di_arg.table = &devicetable; 12307c478bd9Sstevel@tonic-gate di_arg.linkhd = linkhd; 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate /* Use libdevinfo treewalk to build device lookup table */ 12337c478bd9Sstevel@tonic-gate if (di_walk_node(root, DI_WALK_CLDFIRST, (void *)&di_arg, 12347c478bd9Sstevel@tonic-gate devinfo_node_walk) != 0) { 12357c478bd9Sstevel@tonic-gate dprintf((stderr, "di_walk_node: %s\n", strerror(errno))); 12367c478bd9Sstevel@tonic-gate retval = -1; 12377c478bd9Sstevel@tonic-gate goto end; 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate if (di_arg.err != 0) { 12407c478bd9Sstevel@tonic-gate dprintf((stderr, "di_walk_node: device tree walk failed\n")); 12417c478bd9Sstevel@tonic-gate retval = -1; 12427c478bd9Sstevel@tonic-gate goto end; 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /* Call RCM to gather usage information */ 12467c478bd9Sstevel@tonic-gate (void) snprintf(pathbuf, MAXPATHLEN, "/devices%s", path); 12477c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_get_info(%s)\n", pathbuf)); 12487c478bd9Sstevel@tonic-gate if (rcm_get_info(rcm->hdl, pathbuf, 12497c478bd9Sstevel@tonic-gate RCM_INCLUDE_SUBTREE|RCM_INCLUDE_DEPENDENT, &rcm_info) != 12507c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 12517c478bd9Sstevel@tonic-gate dprintf((stderr, "rcm_get_info (errno=%d)\n", errno)); 12527c478bd9Sstevel@tonic-gate retval = -1; 12537c478bd9Sstevel@tonic-gate goto end; 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* Sort the device table by name (proper order for lookups) */ 12577c478bd9Sstevel@tonic-gate qsort(devicetable.table, devicetable.n_entries, sizeof (lookup_entry_t), 12587c478bd9Sstevel@tonic-gate table_compare_names); 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate /* Perform mappings of RCM usage segments to device table entries */ 12617c478bd9Sstevel@tonic-gate lastdeventry = NULL; 12627c478bd9Sstevel@tonic-gate rcm_tuple = NULL; 12637c478bd9Sstevel@tonic-gate while ((rcm_tuple = rcm_info_next(rcm_info, rcm_tuple)) != NULL) { 12647c478bd9Sstevel@tonic-gate if ((rcm_rsrc = rcm_info_rsrc(rcm_tuple)) == NULL) 12657c478bd9Sstevel@tonic-gate continue; 12667c478bd9Sstevel@tonic-gate if (deventry = lookup(&devicetable, rcm_rsrc)) { 12677c478bd9Sstevel@tonic-gate if (add_usage(deventry, rcm_rsrc, rcm_tuple)) { 12687c478bd9Sstevel@tonic-gate retval = -1; 12697c478bd9Sstevel@tonic-gate goto end; 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate lastdeventry = deventry; 12727c478bd9Sstevel@tonic-gate } else { 12737c478bd9Sstevel@tonic-gate if (add_usage(lastdeventry, rcm_rsrc, rcm_tuple)) { 12747c478bd9Sstevel@tonic-gate retval = -1; 12757c478bd9Sstevel@tonic-gate goto end; 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate /* Re-sort the device table by index number (original treewalk order) */ 12817c478bd9Sstevel@tonic-gate qsort(devicetable.table, devicetable.n_entries, sizeof (lookup_entry_t), 12827c478bd9Sstevel@tonic-gate table_compare_indices); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate /* 12857c478bd9Sstevel@tonic-gate * Use the mapped usage and the device table to construct ri_dev_t's. 12867c478bd9Sstevel@tonic-gate * Construct one for each set of entries in the device table with 12877c478bd9Sstevel@tonic-gate * matching di_node_t's, if: 1) it has mapped RCM usage, or 2) it is 12887c478bd9Sstevel@tonic-gate * a leaf node and the caller has requested that unmanaged nodes be 12897c478bd9Sstevel@tonic-gate * included in the output. 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate i = 0; 12927c478bd9Sstevel@tonic-gate while (i < devicetable.n_entries) { 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate node = devicetable.table[i].node; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate /* Count how many usage records are mapped to this node's set */ 12977c478bd9Sstevel@tonic-gate n_usage = 0; 12987c478bd9Sstevel@tonic-gate set_size = 0; 12997c478bd9Sstevel@tonic-gate while (((i + set_size) < devicetable.n_entries) && 13007c478bd9Sstevel@tonic-gate (devicetable.table[i + set_size].node == node)) { 13017c478bd9Sstevel@tonic-gate n_usage += devicetable.table[i + set_size].n_usage; 13027c478bd9Sstevel@tonic-gate set_size += 1; 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate /* 13067c478bd9Sstevel@tonic-gate * If there's no usage, then the node is unmanaged. Skip this 13077c478bd9Sstevel@tonic-gate * set of devicetable entries unless the node is a leaf node 13087c478bd9Sstevel@tonic-gate * and the caller has requested information on unmanaged leaves. 13097c478bd9Sstevel@tonic-gate */ 13107c478bd9Sstevel@tonic-gate if ((n_usage == 0) && 13117c478bd9Sstevel@tonic-gate !((flags & RI_INCLUDE_UNMANAGED) && (ident_leaf(node)))) { 13127c478bd9Sstevel@tonic-gate i += set_size; 13137c478bd9Sstevel@tonic-gate continue; 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate /* 13177c478bd9Sstevel@tonic-gate * The checks above determined that this node is going in. 13187c478bd9Sstevel@tonic-gate * So determine its driver/instance name and allocate an 13197c478bd9Sstevel@tonic-gate * ri_dev_t for this node. 13207c478bd9Sstevel@tonic-gate */ 13217c478bd9Sstevel@tonic-gate if (mk_drv_inst(node, drv_inst, devicetable.table[i].name)) { 13227c478bd9Sstevel@tonic-gate dprintf((stderr, "mk_drv_inst failed\n")); 13237c478bd9Sstevel@tonic-gate retval = -1; 13247c478bd9Sstevel@tonic-gate break; 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate if ((io = io_dev_alloc(drv_inst)) == NULL) { 13277c478bd9Sstevel@tonic-gate dprintf((stderr, "io_dev_alloc failed\n")); 13287c478bd9Sstevel@tonic-gate retval = -1; 13297c478bd9Sstevel@tonic-gate break; 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* Now add all the RCM usage records (if any) to the ri_dev_t */ 13337c478bd9Sstevel@tonic-gate for (j = i; j < (i + set_size); j++) { 13347c478bd9Sstevel@tonic-gate for (k = 0; k < devicetable.table[j].n_usage; k++) { 13357c478bd9Sstevel@tonic-gate /* Create new ri_client_t for basic usage */ 13367c478bd9Sstevel@tonic-gate client = ri_client_alloc( 13377c478bd9Sstevel@tonic-gate (char *)devicetable.table[j].usage[k].rsrc, 13387c478bd9Sstevel@tonic-gate (char *)devicetable.table[j].usage[k].info); 13397c478bd9Sstevel@tonic-gate if (client == NULL) { 13407c478bd9Sstevel@tonic-gate dprintf((stderr, 13417c478bd9Sstevel@tonic-gate "ri_client_alloc failed\n")); 13427c478bd9Sstevel@tonic-gate ri_dev_free(io); 13437c478bd9Sstevel@tonic-gate retval = -1; 13447c478bd9Sstevel@tonic-gate goto end; 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate /* Add extra query usage to the ri_client_t */ 13487c478bd9Sstevel@tonic-gate if ((flags & RI_INCLUDE_QUERY) && 13497c478bd9Sstevel@tonic-gate (add_query_state(rcm, client, 13507c478bd9Sstevel@tonic-gate devicetable.table[j].usage[k].rsrc, 13517c478bd9Sstevel@tonic-gate devicetable.table[j].usage[k].info) != 0)) { 13527c478bd9Sstevel@tonic-gate dprintf((stderr, 13537c478bd9Sstevel@tonic-gate "add_query_state failed\n")); 13547c478bd9Sstevel@tonic-gate ri_dev_free(io); 13557c478bd9Sstevel@tonic-gate ri_client_free(client); 13567c478bd9Sstevel@tonic-gate retval = -1; 13577c478bd9Sstevel@tonic-gate goto end; 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate /* Link new ri_client_t to ri_dev_t */ 13617c478bd9Sstevel@tonic-gate if (io->rcm_clients) { 13627c478bd9Sstevel@tonic-gate tmp = io->rcm_clients; 13637c478bd9Sstevel@tonic-gate while (tmp->next) 13647c478bd9Sstevel@tonic-gate tmp = tmp->next; 13657c478bd9Sstevel@tonic-gate tmp->next = client; 13667c478bd9Sstevel@tonic-gate } else { 13677c478bd9Sstevel@tonic-gate io->rcm_clients = client; 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate /* Link the ri_dev_t into the return value */ 13737c478bd9Sstevel@tonic-gate dev_list_append(&ap->ios, io); 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate /* Advance to the next node set */ 13767c478bd9Sstevel@tonic-gate i += set_size; 13777c478bd9Sstevel@tonic-gate } 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate end: 13807c478bd9Sstevel@tonic-gate if (rcm_info != NULL) 13817c478bd9Sstevel@tonic-gate rcm_free_info(rcm_info); 13827c478bd9Sstevel@tonic-gate if (linkhd != NULL) 13837c478bd9Sstevel@tonic-gate di_devlink_fini(&linkhd); 13847c478bd9Sstevel@tonic-gate if (root != DI_NODE_NIL) 13857c478bd9Sstevel@tonic-gate di_fini(root); 13867c478bd9Sstevel@tonic-gate empty_table(&devicetable); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate dprintf((stderr, "io_cm_info: returning %d\n", retval)); 13897c478bd9Sstevel@tonic-gate return (retval); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate static int 13937c478bd9Sstevel@tonic-gate ident_leaf(di_node_t node) 13947c478bd9Sstevel@tonic-gate { 13957c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate return ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL && 13987c478bd9Sstevel@tonic-gate di_child_node(node) == DI_NODE_NIL); 13997c478bd9Sstevel@tonic-gate } 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate /* ARGSUSED */ 14027c478bd9Sstevel@tonic-gate static int 14037c478bd9Sstevel@tonic-gate mk_drv_inst(di_node_t node, char drv_inst[], char *devfs_path) 14047c478bd9Sstevel@tonic-gate { 14057c478bd9Sstevel@tonic-gate char *drv; 14067c478bd9Sstevel@tonic-gate int inst; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate if ((drv = di_driver_name(node)) == NULL) { 14097c478bd9Sstevel@tonic-gate dprintf((stderr, "no driver bound to %s\n", 14107c478bd9Sstevel@tonic-gate devfs_path)); 14117c478bd9Sstevel@tonic-gate return (-1); 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate if ((inst = di_instance(node)) == -1) { 14157c478bd9Sstevel@tonic-gate dprintf((stderr, "no instance assigned to %s\n", 14167c478bd9Sstevel@tonic-gate devfs_path)); 14177c478bd9Sstevel@tonic-gate return (-1); 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate (void) snprintf(drv_inst, MAXPATHLEN, "%s%d", drv, inst); 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate return (0); 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate /* 14257c478bd9Sstevel@tonic-gate * Libdevinfo walker. 14267c478bd9Sstevel@tonic-gate * 14277c478bd9Sstevel@tonic-gate * During the tree walk of the attached IO devices, for each node 14287c478bd9Sstevel@tonic-gate * and all of its associated minors, the following actions are performed: 14297c478bd9Sstevel@tonic-gate * - The /devices path of the physical device node or minor 14307c478bd9Sstevel@tonic-gate * is stored in a lookup table along with a reference to the 14317c478bd9Sstevel@tonic-gate * libdevinfo node it represents via add_lookup_entry(). 14327c478bd9Sstevel@tonic-gate * - The device links associated with each device are also 14337c478bd9Sstevel@tonic-gate * stored in the same lookup table along with a reference to 14347c478bd9Sstevel@tonic-gate * the libdevinfo node it represents via the minor walk callback. 14357c478bd9Sstevel@tonic-gate * 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate static int 14387c478bd9Sstevel@tonic-gate devinfo_node_walk(di_node_t node, void *arg) 14397c478bd9Sstevel@tonic-gate { 14407c478bd9Sstevel@tonic-gate char *devfs_path; 14417c478bd9Sstevel@tonic-gate #ifdef DEBUG 14427c478bd9Sstevel@tonic-gate char *drv; 14437c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 14447c478bd9Sstevel@tonic-gate devinfo_arg_t *di_arg = (devinfo_arg_t *)arg; 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 14477c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate if (((di_state(node) & DI_DRIVER_DETACHED) == 0) && 14517c478bd9Sstevel@tonic-gate ((devfs_path = di_devfs_path(node)) != NULL)) { 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Use the provided path buffer to create full /devices path */ 14547c478bd9Sstevel@tonic-gate (void) snprintf(di_arg->pathbuf, MAXPATHLEN, "/devices%s", 14557c478bd9Sstevel@tonic-gate devfs_path); 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate #ifdef DEBUG 14587c478bd9Sstevel@tonic-gate dprintf((stderr, "devinfo_node_walk(%s)\n", di_arg->pathbuf)); 14597c478bd9Sstevel@tonic-gate if ((drv = di_driver_name(node)) != NULL) 14607c478bd9Sstevel@tonic-gate dprintf((stderr, " driver name %s instance %d\n", drv, 14617c478bd9Sstevel@tonic-gate di_instance(node))); 14627c478bd9Sstevel@tonic-gate #endif 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate /* Free the devfs_path */ 14657c478bd9Sstevel@tonic-gate di_devfs_path_free(devfs_path); 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate /* Add an entry to the lookup table for this physical device */ 14687c478bd9Sstevel@tonic-gate if (add_lookup_entry(di_arg->table, di_arg->pathbuf, node)) { 14697c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry: %s\n", 14707c478bd9Sstevel@tonic-gate strerror(errno))); 14717c478bd9Sstevel@tonic-gate di_arg->err = 1; 14727c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate /* Check if this node has minors */ 14767c478bd9Sstevel@tonic-gate if ((di_minor_next(node, DI_MINOR_NIL)) != DI_MINOR_NIL) { 14777c478bd9Sstevel@tonic-gate /* Walk this node's minors */ 14787c478bd9Sstevel@tonic-gate di_arg->node = node; 14797c478bd9Sstevel@tonic-gate if (di_walk_minor(node, NULL, DI_CHECK_ALIAS, arg, 14807c478bd9Sstevel@tonic-gate devinfo_minor_walk) != 0) { 14817c478bd9Sstevel@tonic-gate dprintf((stderr, "di_walk_minor: %s\n", 14827c478bd9Sstevel@tonic-gate strerror(errno))); 14837c478bd9Sstevel@tonic-gate di_arg->err = 1; 14847c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 14857c478bd9Sstevel@tonic-gate } 14867c478bd9Sstevel@tonic-gate } 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate * Use di_devlink_walk to find the /dev link from /devices path for this minor 14947c478bd9Sstevel@tonic-gate */ 14957c478bd9Sstevel@tonic-gate static int 14967c478bd9Sstevel@tonic-gate devinfo_minor_walk(di_node_t node, di_minor_t minor, void *arg) 14977c478bd9Sstevel@tonic-gate { 14987c478bd9Sstevel@tonic-gate char *name; 14997c478bd9Sstevel@tonic-gate char *devfs_path; 15007c478bd9Sstevel@tonic-gate devinfo_arg_t *di_arg = (devinfo_arg_t *)arg; 15017c478bd9Sstevel@tonic-gate char pathbuf[MAXPATHLEN]; 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate #ifdef DEBUG 15047c478bd9Sstevel@tonic-gate dprintf((stderr, "devinfo_minor_walk(%d) %s\n", minor, 15057c478bd9Sstevel@tonic-gate di_arg->pathbuf)); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate if ((name = di_minor_name(minor)) != NULL) { 15087c478bd9Sstevel@tonic-gate dprintf((stderr, " minor name %s\n", name)); 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate /* Terminate the walk when the device node changes */ 15137c478bd9Sstevel@tonic-gate if (node != di_arg->node) { 15147c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate /* Construct full /devices path for this minor */ 15187c478bd9Sstevel@tonic-gate if ((name = di_minor_name(minor)) == NULL) { 15197c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate (void) snprintf(pathbuf, MAXPATHLEN, "%s:%s", di_arg->pathbuf, name); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate /* Add lookup entry for this minor node */ 15247c478bd9Sstevel@tonic-gate if (add_lookup_entry(di_arg->table, pathbuf, node)) { 15257c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry: %s\n", strerror(errno))); 15267c478bd9Sstevel@tonic-gate di_arg->err = 1; 15277c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* 15317c478bd9Sstevel@tonic-gate * Walk the associated device links. 15327c478bd9Sstevel@tonic-gate * Note that di_devlink_walk() doesn't want "/devices" in its paths. 15337c478bd9Sstevel@tonic-gate * Also note that di_devlink_walk() will fail if there are no device 15347c478bd9Sstevel@tonic-gate * links, which is fine; so ignore if it fails. Only check for 15357c478bd9Sstevel@tonic-gate * internal failures during such a walk. 15367c478bd9Sstevel@tonic-gate */ 15377c478bd9Sstevel@tonic-gate devfs_path = &pathbuf[strlen("/devices")]; 15387c478bd9Sstevel@tonic-gate (void) di_devlink_walk(di_arg->linkhd, NULL, devfs_path, 0, arg, 15397c478bd9Sstevel@tonic-gate devinfo_devlink_walk); 15407c478bd9Sstevel@tonic-gate if (di_arg->err != 0) { 15417c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate static int 15487c478bd9Sstevel@tonic-gate devinfo_devlink_walk(di_devlink_t devlink, void *arg) 15497c478bd9Sstevel@tonic-gate { 15507c478bd9Sstevel@tonic-gate const char *linkpath; 15517c478bd9Sstevel@tonic-gate devinfo_arg_t *di_arg = (devinfo_arg_t *)arg; 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate /* Get the devlink's path */ 15547c478bd9Sstevel@tonic-gate if ((linkpath = di_devlink_path(devlink)) == NULL) { 15557c478bd9Sstevel@tonic-gate dprintf((stderr, "di_devlink_path: %s\n", strerror(errno))); 15567c478bd9Sstevel@tonic-gate di_arg->err = 1; 15577c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate dprintf((stderr, "devinfo_devlink_walk: %s\n", linkpath)); 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate /* Add lookup entry for this devlink */ 15627c478bd9Sstevel@tonic-gate if (add_lookup_entry(di_arg->table, linkpath, di_arg->node)) { 15637c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry: %s\n", strerror(errno))); 15647c478bd9Sstevel@tonic-gate di_arg->err = 1; 15657c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate /* 15727c478bd9Sstevel@tonic-gate * Map rcm_info_t's to ri_client_t's, filtering out "uninteresting" (hack) 15737c478bd9Sstevel@tonic-gate * RCM clients. The number of "interesting" ri_client_t's is returned 15747c478bd9Sstevel@tonic-gate * in cnt if passed non-NULL. 15757c478bd9Sstevel@tonic-gate */ 15767c478bd9Sstevel@tonic-gate static int 15777c478bd9Sstevel@tonic-gate add_rcm_clients(ri_client_t **client_list, rcmd_t *rcm, rcm_info_t *info, 15787c478bd9Sstevel@tonic-gate int flags, int *cnt) 15797c478bd9Sstevel@tonic-gate { 15807c478bd9Sstevel@tonic-gate rcm_info_tuple_t *tuple; 15817c478bd9Sstevel@tonic-gate char *rsrc, *usage; 15827c478bd9Sstevel@tonic-gate ri_client_t *client, *tmp; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate assert(client_list != NULL && rcm != NULL); 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate if (info == NULL) 15877c478bd9Sstevel@tonic-gate return (0); 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate if (cnt != NULL) 15907c478bd9Sstevel@tonic-gate *cnt = 0; 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate tuple = NULL; 15937c478bd9Sstevel@tonic-gate while ((tuple = rcm_info_next(info, tuple)) != NULL) { 15947c478bd9Sstevel@tonic-gate if ((rsrc = (char *)rcm_info_rsrc(tuple)) == NULL || 15957c478bd9Sstevel@tonic-gate (usage = (char *)rcm_info_info(tuple)) == NULL) { 15967c478bd9Sstevel@tonic-gate continue; 15977c478bd9Sstevel@tonic-gate } 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate if (rcm_ignore(rsrc, usage) == 0) 16007c478bd9Sstevel@tonic-gate continue; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate if ((client = ri_client_alloc(rsrc, usage)) == NULL) 16037c478bd9Sstevel@tonic-gate return (-1); 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate if ((flags & RI_INCLUDE_QUERY) && add_query_state(rcm, client, 16067c478bd9Sstevel@tonic-gate rsrc, usage) != 0) { 16077c478bd9Sstevel@tonic-gate ri_client_free(client); 16087c478bd9Sstevel@tonic-gate return (-1); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate if (cnt != NULL) 16127c478bd9Sstevel@tonic-gate ++*cnt; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate /* 16157c478bd9Sstevel@tonic-gate * Link in 16167c478bd9Sstevel@tonic-gate */ 16177c478bd9Sstevel@tonic-gate if ((tmp = *client_list) == NULL) { 16187c478bd9Sstevel@tonic-gate *client_list = client; 16197c478bd9Sstevel@tonic-gate continue; 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate while (tmp->next != NULL) { 16227c478bd9Sstevel@tonic-gate tmp = tmp->next; 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate tmp->next = client; 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate return (0); 16287c478bd9Sstevel@tonic-gate } 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate /* 16317c478bd9Sstevel@tonic-gate * Currently only filtering out based on known info string prefixes. 16327c478bd9Sstevel@tonic-gate */ 16337c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16347c478bd9Sstevel@tonic-gate static int 16357c478bd9Sstevel@tonic-gate rcm_ignore(char *rsrc, char *infostr) 16367c478bd9Sstevel@tonic-gate { 16377c478bd9Sstevel@tonic-gate char **cpp; 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate for (cpp = rcm_info_filter; *cpp != NULL; cpp++) { 16407c478bd9Sstevel@tonic-gate if (strncmp(infostr, *cpp, strlen(*cpp)) == 0) { 16417c478bd9Sstevel@tonic-gate return (0); 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate return (-1); 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * If this tuple was cached in the offline query pass, add the 16497c478bd9Sstevel@tonic-gate * query state and error string to the ri_client_t. 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate static int 16527c478bd9Sstevel@tonic-gate add_query_state(rcmd_t *rcm, ri_client_t *client, const char *rsrc, 16537c478bd9Sstevel@tonic-gate const char *info) 16547c478bd9Sstevel@tonic-gate { 16557c478bd9Sstevel@tonic-gate int qstate = RI_QUERY_UNKNOWN; 16567c478bd9Sstevel@tonic-gate char *errstr = NULL; 16577c478bd9Sstevel@tonic-gate rcm_info_tuple_t *cached_tuple; 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate if ((cached_tuple = tuple_lookup(rcm, rsrc, info)) != NULL) { 16607c478bd9Sstevel@tonic-gate qstate = state2query(rcm_info_state(cached_tuple)); 16617c478bd9Sstevel@tonic-gate errstr = (char *)rcm_info_error(cached_tuple); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate if (nvlist_add_int32(client->usg_props, RI_QUERY_STATE, qstate) != 0 || 16657c478bd9Sstevel@tonic-gate (errstr != NULL && nvlist_add_string(client->usg_props, 16667c478bd9Sstevel@tonic-gate RI_QUERY_ERR, errstr) != 0)) { 16677c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add fail\n")); 16687c478bd9Sstevel@tonic-gate return (-1); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate return (0); 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate static int 16757c478bd9Sstevel@tonic-gate state2query(int rcm_state) 16767c478bd9Sstevel@tonic-gate { 16777c478bd9Sstevel@tonic-gate int query; 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate switch (rcm_state) { 16807c478bd9Sstevel@tonic-gate case RCM_STATE_OFFLINE_QUERY: 16817c478bd9Sstevel@tonic-gate case RCM_STATE_SUSPEND_QUERY: 16827c478bd9Sstevel@tonic-gate query = RI_QUERY_OK; 16837c478bd9Sstevel@tonic-gate break; 16847c478bd9Sstevel@tonic-gate case RCM_STATE_OFFLINE_QUERY_FAIL: 16857c478bd9Sstevel@tonic-gate case RCM_STATE_SUSPEND_QUERY_FAIL: 16867c478bd9Sstevel@tonic-gate query = RI_QUERY_FAIL; 16877c478bd9Sstevel@tonic-gate break; 16887c478bd9Sstevel@tonic-gate default: 16897c478bd9Sstevel@tonic-gate query = RI_QUERY_UNKNOWN; 16907c478bd9Sstevel@tonic-gate break; 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate return (query); 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate static void 16977c478bd9Sstevel@tonic-gate dev_list_append(ri_dev_t **head, ri_dev_t *dev) 16987c478bd9Sstevel@tonic-gate { 16997c478bd9Sstevel@tonic-gate ri_dev_t *tmp; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate if ((tmp = *head) == NULL) { 17027c478bd9Sstevel@tonic-gate *head = dev; 17037c478bd9Sstevel@tonic-gate return; 17047c478bd9Sstevel@tonic-gate } 17057c478bd9Sstevel@tonic-gate while (tmp->next != NULL) { 17067c478bd9Sstevel@tonic-gate tmp = tmp->next; 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate tmp->next = dev; 17097c478bd9Sstevel@tonic-gate } 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate /* 17127c478bd9Sstevel@tonic-gate * The cpu list is ordered on cpuid since CMP cpuids will not necessarily 17137c478bd9Sstevel@tonic-gate * be discovered in sequence. 17147c478bd9Sstevel@tonic-gate */ 17157c478bd9Sstevel@tonic-gate static void 17167c478bd9Sstevel@tonic-gate dev_list_cpu_insert(ri_dev_t **listp, ri_dev_t *dev, processorid_t newid) 17177c478bd9Sstevel@tonic-gate { 17187c478bd9Sstevel@tonic-gate ri_dev_t *tmp; 17197c478bd9Sstevel@tonic-gate int32_t cpuid; 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate while ((tmp = *listp) != NULL && 17227c478bd9Sstevel@tonic-gate nvlist_lookup_int32(tmp->conf_props, RI_CPU_ID, &cpuid) == 0 && 17237c478bd9Sstevel@tonic-gate cpuid < newid) { 17247c478bd9Sstevel@tonic-gate listp = &tmp->next; 17257c478bd9Sstevel@tonic-gate } 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate dev->next = tmp; 17287c478bd9Sstevel@tonic-gate *listp = dev; 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate /* 17327c478bd9Sstevel@tonic-gate * Linear lookup. Should convert to hash tab. 17337c478bd9Sstevel@tonic-gate */ 17347c478bd9Sstevel@tonic-gate static rcm_info_tuple_t * 17357c478bd9Sstevel@tonic-gate tuple_lookup(rcmd_t *rcm, const char *krsrc, const char *kinfo) 17367c478bd9Sstevel@tonic-gate { 17377c478bd9Sstevel@tonic-gate rcm_info_tuple_t *tuple = NULL; 17387c478bd9Sstevel@tonic-gate const char *rsrc, *info; 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate if ((rcm == NULL) || (krsrc == NULL) || (kinfo == NULL)) { 17417c478bd9Sstevel@tonic-gate return (NULL); 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate while ((tuple = rcm_info_next(rcm->offline_query_info, 17457c478bd9Sstevel@tonic-gate tuple)) != NULL) { 17467c478bd9Sstevel@tonic-gate if ((rsrc = rcm_info_rsrc(tuple)) == NULL || 17477c478bd9Sstevel@tonic-gate (info = rcm_info_info(tuple)) == NULL) { 17487c478bd9Sstevel@tonic-gate continue; 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if (strcmp(rsrc, krsrc) == 0 && strcmp(info, kinfo) == 0) { 17527c478bd9Sstevel@tonic-gate return (tuple); 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate return (NULL); 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate /* 17597c478bd9Sstevel@tonic-gate * Create and link attachment point handle. 17607c478bd9Sstevel@tonic-gate */ 17617c478bd9Sstevel@tonic-gate static ri_ap_t * 17627c478bd9Sstevel@tonic-gate ri_ap_alloc(char *ap_id, ri_hdl_t *hdl) 17637c478bd9Sstevel@tonic-gate { 17647c478bd9Sstevel@tonic-gate ri_ap_t *ap, *tmp; 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate if ((ap = calloc(1, sizeof (*ap))) == NULL) { 17677c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s\n", strerror(errno))); 17687c478bd9Sstevel@tonic-gate return (NULL); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate if (nvlist_alloc(&ap->conf_props, NV_UNIQUE_NAME, 0) != 0 || 17727c478bd9Sstevel@tonic-gate nvlist_add_string(ap->conf_props, RI_AP_REQ_ID, ap_id) != 0) { 17737c478bd9Sstevel@tonic-gate nvlist_free(ap->conf_props); 17747c478bd9Sstevel@tonic-gate free(ap); 17757c478bd9Sstevel@tonic-gate return (NULL); 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate if ((tmp = hdl->aps) == NULL) { 17797c478bd9Sstevel@tonic-gate hdl->aps = ap; 17807c478bd9Sstevel@tonic-gate } else { 17817c478bd9Sstevel@tonic-gate while (tmp->next != NULL) { 17827c478bd9Sstevel@tonic-gate tmp = tmp->next; 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate tmp->next = ap; 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate return (ap); 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate static ri_dev_t * 17917c478bd9Sstevel@tonic-gate ri_dev_alloc(void) 17927c478bd9Sstevel@tonic-gate { 17937c478bd9Sstevel@tonic-gate ri_dev_t *dev; 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate if ((dev = calloc(1, sizeof (*dev))) == NULL || 17967c478bd9Sstevel@tonic-gate nvlist_alloc(&dev->conf_props, NV_UNIQUE_NAME, 0) != 0) { 17977c478bd9Sstevel@tonic-gate s_free(dev); 17987c478bd9Sstevel@tonic-gate } 17997c478bd9Sstevel@tonic-gate return (dev); 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate static ri_dev_t * 18037c478bd9Sstevel@tonic-gate io_dev_alloc(char *drv_inst) 18047c478bd9Sstevel@tonic-gate { 18057c478bd9Sstevel@tonic-gate ri_dev_t *io; 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate assert(drv_inst != NULL); 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate if ((io = ri_dev_alloc()) == NULL) 18107c478bd9Sstevel@tonic-gate return (NULL); 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate if (nvlist_add_string(io->conf_props, RI_IO_DRV_INST, 18137c478bd9Sstevel@tonic-gate drv_inst) != 0) { 18147c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add_string fail\n")); 18157c478bd9Sstevel@tonic-gate ri_dev_free(io); 18167c478bd9Sstevel@tonic-gate return (NULL); 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate return (io); 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate static ri_client_t * 18237c478bd9Sstevel@tonic-gate ri_client_alloc(char *rsrc, char *usage) 18247c478bd9Sstevel@tonic-gate { 18257c478bd9Sstevel@tonic-gate ri_client_t *client; 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate assert(rsrc != NULL && usage != NULL); 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate if ((client = calloc(1, sizeof (*client))) == NULL) { 18307c478bd9Sstevel@tonic-gate dprintf((stderr, "calloc: %s\n", strerror(errno))); 18317c478bd9Sstevel@tonic-gate return (NULL); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate if (nvlist_alloc(&client->usg_props, NV_UNIQUE_NAME, 0) != 0) { 18357c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_alloc fail\n")); 18367c478bd9Sstevel@tonic-gate free(client); 18377c478bd9Sstevel@tonic-gate return (NULL); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate if (nvlist_add_string(client->usg_props, RI_CLIENT_RSRC, rsrc) != 0 || 18417c478bd9Sstevel@tonic-gate nvlist_add_string(client->usg_props, RI_CLIENT_USAGE, usage) != 0) { 18427c478bd9Sstevel@tonic-gate dprintf((stderr, "nvlist_add_string fail\n")); 18437c478bd9Sstevel@tonic-gate ri_client_free(client); 18447c478bd9Sstevel@tonic-gate return (NULL); 18457c478bd9Sstevel@tonic-gate } 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate return (client); 18487c478bd9Sstevel@tonic-gate } 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate static void 18517c478bd9Sstevel@tonic-gate apd_tbl_free(apd_t apd_tbl[], int napds) 18527c478bd9Sstevel@tonic-gate { 18537c478bd9Sstevel@tonic-gate int i; 18547c478bd9Sstevel@tonic-gate apd_t *apd; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate for (i = 0, apd = apd_tbl; i < napds; i++, apd++) 18577c478bd9Sstevel@tonic-gate s_free(apd->cfga_list_data); 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate free(apd_tbl); 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate static char * 18637c478bd9Sstevel@tonic-gate pstate2str(int pi_state) 18647c478bd9Sstevel@tonic-gate { 18657c478bd9Sstevel@tonic-gate char *state; 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate switch (pi_state) { 18687c478bd9Sstevel@tonic-gate case P_OFFLINE: 18697c478bd9Sstevel@tonic-gate state = PS_OFFLINE; 18707c478bd9Sstevel@tonic-gate break; 18717c478bd9Sstevel@tonic-gate case P_ONLINE: 18727c478bd9Sstevel@tonic-gate state = PS_ONLINE; 18737c478bd9Sstevel@tonic-gate break; 18747c478bd9Sstevel@tonic-gate case P_FAULTED: 18757c478bd9Sstevel@tonic-gate state = PS_FAULTED; 18767c478bd9Sstevel@tonic-gate break; 18777c478bd9Sstevel@tonic-gate case P_POWEROFF: 18787c478bd9Sstevel@tonic-gate state = PS_POWEROFF; 18797c478bd9Sstevel@tonic-gate break; 18807c478bd9Sstevel@tonic-gate case P_NOINTR: 18817c478bd9Sstevel@tonic-gate state = PS_NOINTR; 18827c478bd9Sstevel@tonic-gate break; 18837c478bd9Sstevel@tonic-gate case P_SPARE: 18847c478bd9Sstevel@tonic-gate state = PS_SPARE; 18857c478bd9Sstevel@tonic-gate break; 18867c478bd9Sstevel@tonic-gate default: 18877c478bd9Sstevel@tonic-gate state = "unknown"; 18887c478bd9Sstevel@tonic-gate break; 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate 18917c478bd9Sstevel@tonic-gate return (state); 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate #ifdef DEBUG 18957c478bd9Sstevel@tonic-gate static void 18967c478bd9Sstevel@tonic-gate dump_apd_tbl(FILE *fp, apd_t *apds, int n_apds) 18977c478bd9Sstevel@tonic-gate { 18987c478bd9Sstevel@tonic-gate int i, j; 18997c478bd9Sstevel@tonic-gate cfga_list_data_t *cfga_ldata; 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gate for (i = 0; i < n_apds; i++, apds++) { 19027c478bd9Sstevel@tonic-gate dprintf((stderr, "apd_tbl[%d].nlist=%d\n", i, apds->nlist)); 19037c478bd9Sstevel@tonic-gate for (j = 0, cfga_ldata = apds->cfga_list_data; j < apds->nlist; 19047c478bd9Sstevel@tonic-gate j++, cfga_ldata++) { 19057c478bd9Sstevel@tonic-gate dprintf((fp, 19067c478bd9Sstevel@tonic-gate "apd_tbl[%d].cfga_list_data[%d].ap_log_id=%s\n", 19077c478bd9Sstevel@tonic-gate i, j, cfga_ldata->ap_log_id)); 19087c478bd9Sstevel@tonic-gate } 19097c478bd9Sstevel@tonic-gate } 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate /* 19147c478bd9Sstevel@tonic-gate * The lookup table is a simple array that is grown in chunks 19157c478bd9Sstevel@tonic-gate * to optimize memory allocation. 19167c478bd9Sstevel@tonic-gate * Indices are assigned to each array entry in-order so that 19177c478bd9Sstevel@tonic-gate * the original device tree ordering can be discerned at a later time. 19187c478bd9Sstevel@tonic-gate * 19197c478bd9Sstevel@tonic-gate * add_lookup_entry is called from the libdevinfo tree traversal callbacks: 19207c478bd9Sstevel@tonic-gate * 1) devinfo_node_walk - physical device path for each node in 19217c478bd9Sstevel@tonic-gate * the devinfo tree via di_walk_node(), lookup entry name is 19227c478bd9Sstevel@tonic-gate * /devices/[di_devfs_path] 19237c478bd9Sstevel@tonic-gate * 2) devinfo_minor_walk - physical device path plus minor name for 19247c478bd9Sstevel@tonic-gate * each minor associated with a node via di_walk_minor(), lookup entry 19257c478bd9Sstevel@tonic-gate * name is /devices/[di_devfs_path:di_minor_name] 19267c478bd9Sstevel@tonic-gate * 3) devinfo_devlink_walk - for each minor's /dev link from its /devices 19277c478bd9Sstevel@tonic-gate * path via di_devlink_walk(), lookup entry name is di_devlink_path() 19287c478bd9Sstevel@tonic-gate */ 19297c478bd9Sstevel@tonic-gate static int 19307c478bd9Sstevel@tonic-gate add_lookup_entry(lookup_table_t *table, const char *name, di_node_t node) 19317c478bd9Sstevel@tonic-gate { 19327c478bd9Sstevel@tonic-gate size_t size; 19337c478bd9Sstevel@tonic-gate lookup_entry_t *new_table; 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate /* Grow the lookup table by USAGE_ALLOC_SIZE slots if necessary */ 19377c478bd9Sstevel@tonic-gate if (table->n_entries == table->n_slots) { 19387c478bd9Sstevel@tonic-gate size = (table->n_slots + USAGE_ALLOC_SIZE) * 19397c478bd9Sstevel@tonic-gate sizeof (lookup_entry_t); 19407c478bd9Sstevel@tonic-gate new_table = (lookup_entry_t *)realloc(table->table, size); 19417c478bd9Sstevel@tonic-gate if (new_table == NULL) { 19427c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry: alloc failed: %s\n", 19437c478bd9Sstevel@tonic-gate strerror(errno))); 19447c478bd9Sstevel@tonic-gate errno = ENOMEM; 19457c478bd9Sstevel@tonic-gate return (-1); 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate table->table = new_table; 19487c478bd9Sstevel@tonic-gate table->n_slots += USAGE_ALLOC_SIZE; 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry[%d]:%s\n", table->n_entries, name)); 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate /* Add this name to the next slot */ 19547c478bd9Sstevel@tonic-gate if ((table->table[table->n_entries].name = strdup(name)) == NULL) { 19557c478bd9Sstevel@tonic-gate dprintf((stderr, "add_lookup_entry: strdup failed: %s\n", 19567c478bd9Sstevel@tonic-gate strerror(errno))); 19577c478bd9Sstevel@tonic-gate errno = ENOMEM; 19587c478bd9Sstevel@tonic-gate return (-1); 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate table->table[table->n_entries].index = table->n_entries; 19617c478bd9Sstevel@tonic-gate table->table[table->n_entries].node = node; 19627c478bd9Sstevel@tonic-gate table->table[table->n_entries].n_usage = 0; 19637c478bd9Sstevel@tonic-gate table->table[table->n_entries].usage = NULL; 19647c478bd9Sstevel@tonic-gate table->n_entries += 1; 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate return (0); 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate /* 19707c478bd9Sstevel@tonic-gate * lookup table entry names are full pathname strings, all start with / 19717c478bd9Sstevel@tonic-gate */ 19727c478bd9Sstevel@tonic-gate static int 19737c478bd9Sstevel@tonic-gate table_compare_names(const void *a, const void *b) 19747c478bd9Sstevel@tonic-gate { 19757c478bd9Sstevel@tonic-gate lookup_entry_t *entry1 = (lookup_entry_t *)a; 19767c478bd9Sstevel@tonic-gate lookup_entry_t *entry2 = (lookup_entry_t *)b; 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate return (strcmp(entry1->name, entry2->name)); 19797c478bd9Sstevel@tonic-gate } 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate /* 19837c478bd9Sstevel@tonic-gate * Compare two indices and return -1 for less, 1 for greater, 0 for equal 19847c478bd9Sstevel@tonic-gate */ 19857c478bd9Sstevel@tonic-gate static int 19867c478bd9Sstevel@tonic-gate table_compare_indices(const void *a, const void *b) 19877c478bd9Sstevel@tonic-gate { 19887c478bd9Sstevel@tonic-gate lookup_entry_t *entry1 = (lookup_entry_t *)a; 19897c478bd9Sstevel@tonic-gate lookup_entry_t *entry2 = (lookup_entry_t *)b; 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate if (entry1->index < entry2->index) 19927c478bd9Sstevel@tonic-gate return (-1); 19937c478bd9Sstevel@tonic-gate if (entry1->index > entry2->index) 19947c478bd9Sstevel@tonic-gate return (1); 19957c478bd9Sstevel@tonic-gate return (0); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate /* 19997c478bd9Sstevel@tonic-gate * Given a RCM resource name, find the matching entry in the IO device table 20007c478bd9Sstevel@tonic-gate */ 20017c478bd9Sstevel@tonic-gate static lookup_entry_t * 20027c478bd9Sstevel@tonic-gate lookup(lookup_table_t *table, const char *rcm_rsrc) 20037c478bd9Sstevel@tonic-gate { 20047c478bd9Sstevel@tonic-gate lookup_entry_t *entry; 20057c478bd9Sstevel@tonic-gate lookup_entry_t lookup_arg; 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate dprintf((stderr, "lookup:%s\n", rcm_rsrc)); 20087c478bd9Sstevel@tonic-gate lookup_arg.name = (char *)rcm_rsrc; 20097c478bd9Sstevel@tonic-gate entry = bsearch(&lookup_arg, table->table, table->n_entries, 20107c478bd9Sstevel@tonic-gate sizeof (lookup_entry_t), table_compare_names); 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate #ifdef DEBUG 20137c478bd9Sstevel@tonic-gate if (entry != NULL) { 20147c478bd9Sstevel@tonic-gate dprintf((stderr, " found entry:%d\n", entry->index)); 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 20177c478bd9Sstevel@tonic-gate return (entry); 20187c478bd9Sstevel@tonic-gate } 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate /* 20217c478bd9Sstevel@tonic-gate * Add RCM usage to the given device table entry. 20227c478bd9Sstevel@tonic-gate * Returns -1 on realloc failure. 20237c478bd9Sstevel@tonic-gate */ 20247c478bd9Sstevel@tonic-gate static int 20257c478bd9Sstevel@tonic-gate add_usage(lookup_entry_t *entry, const char *rcm_rsrc, rcm_info_tuple_t *tuple) 20267c478bd9Sstevel@tonic-gate { 20277c478bd9Sstevel@tonic-gate size_t size; 20287c478bd9Sstevel@tonic-gate const char *info; 20297c478bd9Sstevel@tonic-gate usage_t *new_usage; 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate if ((entry == NULL) || 20327c478bd9Sstevel@tonic-gate ((info = rcm_info_info(tuple)) == NULL)) 20337c478bd9Sstevel@tonic-gate return (0); 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate if (rcm_ignore((char *)rcm_rsrc, (char *)info) == 0) 20367c478bd9Sstevel@tonic-gate return (0); 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate size = (entry->n_usage + 1) * sizeof (usage_t); 20397c478bd9Sstevel@tonic-gate new_usage = (usage_t *)realloc(entry->usage, size); 20407c478bd9Sstevel@tonic-gate if (new_usage == NULL) { 20417c478bd9Sstevel@tonic-gate dprintf((stderr, "add_usage: alloc failed: %s\n", 20427c478bd9Sstevel@tonic-gate strerror(errno))); 20437c478bd9Sstevel@tonic-gate return (-1); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate dprintf((stderr, "add_usage: entry %d rsrc: %s info: %s\n", 20467c478bd9Sstevel@tonic-gate entry->index, rcm_rsrc, info)); 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate entry->usage = new_usage; 20497c478bd9Sstevel@tonic-gate entry->usage[entry->n_usage].rsrc = rcm_rsrc; 20507c478bd9Sstevel@tonic-gate entry->usage[entry->n_usage].info = info; 20517c478bd9Sstevel@tonic-gate entry->n_usage += 1; 20527c478bd9Sstevel@tonic-gate return (0); 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate static void 20567c478bd9Sstevel@tonic-gate empty_table(lookup_table_t *table) 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate int i; 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate if (table) { 20617c478bd9Sstevel@tonic-gate for (i = 0; i < table->n_entries; i++) { 20627c478bd9Sstevel@tonic-gate if (table->table[i].name) 20637c478bd9Sstevel@tonic-gate free(table->table[i].name); 20647c478bd9Sstevel@tonic-gate /* 20657c478bd9Sstevel@tonic-gate * Note: the strings pointed to from within 20667c478bd9Sstevel@tonic-gate * usage were freed already by rcm_free_info 20677c478bd9Sstevel@tonic-gate */ 20687c478bd9Sstevel@tonic-gate if (table->table[i].usage) 20697c478bd9Sstevel@tonic-gate free(table->table[i].usage); 20707c478bd9Sstevel@tonic-gate } 20717c478bd9Sstevel@tonic-gate if (table->table) 20727c478bd9Sstevel@tonic-gate free(table->table); 20737c478bd9Sstevel@tonic-gate table->table = NULL; 20747c478bd9Sstevel@tonic-gate table->n_entries = 0; 20757c478bd9Sstevel@tonic-gate table->n_slots = 0; 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate } 2078