130588217SMike Christensen /* 230588217SMike Christensen * CDDL HEADER START 330588217SMike Christensen * 430588217SMike Christensen * The contents of this file are subject to the terms of the 530588217SMike Christensen * Common Development and Distribution License (the "License"). 630588217SMike Christensen * You may not use this file except in compliance with the License. 730588217SMike Christensen * 830588217SMike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 930588217SMike Christensen * or http://www.opensolaris.org/os/licensing. 1030588217SMike Christensen * See the License for the specific language governing permissions 1130588217SMike Christensen * and limitations under the License. 1230588217SMike Christensen * 1330588217SMike Christensen * When distributing Covered Code, include this CDDL HEADER in each 1430588217SMike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1530588217SMike Christensen * If applicable, add the following below this CDDL HEADER, with the 1630588217SMike Christensen * fields enclosed by brackets "[]" replaced with your own identifying 1730588217SMike Christensen * information: Portions Copyright [yyyy] [name of copyright owner] 1830588217SMike Christensen * 1930588217SMike Christensen * CDDL HEADER END 2030588217SMike Christensen */ 2130588217SMike Christensen 2230588217SMike Christensen /* 2340c61268SMike Christensen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2430588217SMike Christensen * Use is subject to license terms. 2530588217SMike Christensen */ 2630588217SMike Christensen 2730588217SMike Christensen 2830588217SMike Christensen /* 2930588217SMike Christensen * Domain Services Module System Specific Code. 3030588217SMike Christensen * 3130588217SMike Christensen * The Domain Services (DS) module is responsible for communication 3230588217SMike Christensen * with external service entities. It provides a kernel API for clients to 3330588217SMike Christensen * publish capabilities and handles the low level communication and 3430588217SMike Christensen * version negotiation required to export those capabilities to any 3530588217SMike Christensen * interested service entity. Once a capability has been successfully 3630588217SMike Christensen * registered with a service entity, the DS module facilitates all 3730588217SMike Christensen * data transfers between the service entity and the client providing 3830588217SMike Christensen * that particular capability. 3930588217SMike Christensen * 4030588217SMike Christensen * This file provides the system interfaces that are required for 4130588217SMike Christensen * the ds.c module, which is common to both Solaris and VBSC (linux). 4230588217SMike Christensen */ 4330588217SMike Christensen 4430588217SMike Christensen #include <sys/modctl.h> 4530588217SMike Christensen #include <sys/ksynch.h> 4630588217SMike Christensen #include <sys/taskq.h> 4730588217SMike Christensen #include <sys/disp.h> 4830588217SMike Christensen #include <sys/cmn_err.h> 4930588217SMike Christensen #include <sys/note.h> 5030588217SMike Christensen #include <sys/mach_descrip.h> 5130588217SMike Christensen #include <sys/mdesc.h> 5230588217SMike Christensen #include <sys/mdeg.h> 5330588217SMike Christensen #include <sys/ldc.h> 5430588217SMike Christensen #include <sys/ds.h> 5530588217SMike Christensen #include <sys/ds_impl.h> 5630588217SMike Christensen 5730588217SMike Christensen /* 5830588217SMike Christensen * All DS ports in the system 5930588217SMike Christensen * 6030588217SMike Christensen * The list of DS ports is read in from the MD when the DS module is 6130588217SMike Christensen * initialized and is never modified. This eliminates the need for 6230588217SMike Christensen * locking to access the port array itself. Access to the individual 6330588217SMike Christensen * ports are synchronized at the port level. 6430588217SMike Christensen */ 6530588217SMike Christensen ds_port_t ds_ports[DS_MAX_PORTS]; 6630588217SMike Christensen ds_portset_t ds_allports; /* all DS ports in the system */ 6730588217SMike Christensen 6830588217SMike Christensen /* 6930588217SMike Christensen * Table of registered services 7030588217SMike Christensen * 7130588217SMike Christensen * Locking: Accesses to the table of services are synchronized using 7230588217SMike Christensen * a mutex lock. The reader lock must be held when looking up service 7330588217SMike Christensen * information in the table. The writer lock must be held when any 7430588217SMike Christensen * service information is being modified. 7530588217SMike Christensen */ 7630588217SMike Christensen ds_svcs_t ds_svcs; 7730588217SMike Christensen 7830588217SMike Christensen /* 7930588217SMike Christensen * Taskq for internal task processing 8030588217SMike Christensen */ 8130588217SMike Christensen static taskq_t *ds_taskq; 8230588217SMike Christensen 8330588217SMike Christensen /* 8430588217SMike Christensen * The actual required number of parallel threads is not expected 8530588217SMike Christensen * to be very large. Use the maximum number of CPUs in the system 8630588217SMike Christensen * as a rough upper bound. 8730588217SMike Christensen */ 8830588217SMike Christensen #define DS_MAX_TASKQ_THR NCPU 8930588217SMike Christensen #define DS_DISPATCH(fn, arg) taskq_dispatch(ds_taskq, fn, arg, TQ_SLEEP) 9030588217SMike Christensen 91a600f50dSMike Christensen ds_domain_hdl_t ds_my_domain_hdl = DS_DHDL_INVALID; 92a600f50dSMike Christensen char *ds_my_domain_name = NULL; 9330588217SMike Christensen 9430588217SMike Christensen #ifdef DEBUG 9530588217SMike Christensen /* 9630588217SMike Christensen * Debug Flag 9730588217SMike Christensen */ 9830588217SMike Christensen uint_t ds_debug = 0; 9930588217SMike Christensen #endif /* DEBUG */ 10030588217SMike Christensen 10130588217SMike Christensen /* initialization functions */ 10230588217SMike Christensen static void ds_init(void); 10330588217SMike Christensen static void ds_fini(void); 10430588217SMike Christensen static int ds_ports_init(void); 10530588217SMike Christensen static int ds_ports_fini(void); 10630588217SMike Christensen 10730588217SMike Christensen /* port utilities */ 10830588217SMike Christensen static int ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan); 10930588217SMike Christensen 11030588217SMike Christensen /* log functions */ 11130588217SMike Christensen static void ds_log_init(void); 11230588217SMike Christensen static void ds_log_fini(void); 11330588217SMike Christensen static int ds_log_remove(void); 11430588217SMike Christensen static void ds_log_purge(void *arg); 11530588217SMike Christensen 11630588217SMike Christensen static struct modlmisc modlmisc = { 11730588217SMike Christensen &mod_miscops, 11830588217SMike Christensen "Domain Services 1.9" 11930588217SMike Christensen }; 12030588217SMike Christensen 12130588217SMike Christensen static struct modlinkage modlinkage = { 12230588217SMike Christensen MODREV_1, 12330588217SMike Christensen (void *)&modlmisc, 12430588217SMike Christensen NULL 12530588217SMike Christensen }; 12630588217SMike Christensen 12730588217SMike Christensen int 12830588217SMike Christensen _init(void) 12930588217SMike Christensen { 13030588217SMike Christensen int rv; 13130588217SMike Christensen 13230588217SMike Christensen /* 13330588217SMike Christensen * Perform all internal setup before initializing 13430588217SMike Christensen * the DS ports. This ensures that events can be 13530588217SMike Christensen * processed as soon as the port comes up. 13630588217SMike Christensen */ 13730588217SMike Christensen ds_init(); 13830588217SMike Christensen 13930588217SMike Christensen /* force attach channel nexus */ 14030588217SMike Christensen (void) i_ddi_attach_hw_nodes("cnex"); 14130588217SMike Christensen 14230588217SMike Christensen if ((rv = ds_ports_init()) != 0) { 14330588217SMike Christensen cmn_err(CE_WARN, "Domain Services initialization failed"); 14430588217SMike Christensen ds_fini(); 14530588217SMike Christensen return (rv); 14630588217SMike Christensen } 14730588217SMike Christensen 14830588217SMike Christensen if ((rv = mod_install(&modlinkage)) != 0) { 14930588217SMike Christensen (void) ds_ports_fini(); 15030588217SMike Christensen ds_fini(); 15130588217SMike Christensen } 15230588217SMike Christensen 15330588217SMike Christensen return (rv); 15430588217SMike Christensen } 15530588217SMike Christensen 15630588217SMike Christensen int 15730588217SMike Christensen _info(struct modinfo *modinfop) 15830588217SMike Christensen { 15930588217SMike Christensen return (mod_info(&modlinkage, modinfop)); 16030588217SMike Christensen } 16130588217SMike Christensen 16230588217SMike Christensen int 16330588217SMike Christensen _fini(void) 16430588217SMike Christensen { 16530588217SMike Christensen int rv; 16630588217SMike Christensen 16730588217SMike Christensen if ((rv = mod_remove(&modlinkage)) == 0) { 16830588217SMike Christensen (void) ds_ports_fini(); 16930588217SMike Christensen ds_fini(); 17030588217SMike Christensen } 17130588217SMike Christensen 17230588217SMike Christensen return (rv); 17330588217SMike Christensen } 17430588217SMike Christensen 17530588217SMike Christensen static void 17630588217SMike Christensen ds_fini(void) 17730588217SMike Christensen { 17830588217SMike Christensen /* 17930588217SMike Christensen * Flip the enabled switch to make sure that no 18030588217SMike Christensen * incoming events get dispatched while things 18130588217SMike Christensen * are being torn down. 18230588217SMike Christensen */ 18330588217SMike Christensen ds_enabled = B_FALSE; 18430588217SMike Christensen 18530588217SMike Christensen /* 18630588217SMike Christensen * Destroy the taskq. 18730588217SMike Christensen */ 18830588217SMike Christensen taskq_destroy(ds_taskq); 18930588217SMike Christensen 19030588217SMike Christensen /* 19130588217SMike Christensen * Destroy the message log. 19230588217SMike Christensen */ 19330588217SMike Christensen ds_log_fini(); 19430588217SMike Christensen 19530588217SMike Christensen /* 19630588217SMike Christensen * Deallocate the table of registered services 19730588217SMike Christensen */ 19830588217SMike Christensen 19930588217SMike Christensen /* clear out all entries */ 20030588217SMike Christensen mutex_enter(&ds_svcs.lock); 20130588217SMike Christensen (void) ds_walk_svcs(ds_svc_free, NULL); 20230588217SMike Christensen mutex_exit(&ds_svcs.lock); 20330588217SMike Christensen 20430588217SMike Christensen /* destroy the table itself */ 20530588217SMike Christensen DS_FREE(ds_svcs.tbl, ds_svcs.maxsvcs * sizeof (ds_svc_t *)); 20630588217SMike Christensen mutex_destroy(&ds_svcs.lock); 20730588217SMike Christensen bzero(&ds_svcs, sizeof (ds_svcs)); 20830588217SMike Christensen } 20930588217SMike Christensen 21030588217SMike Christensen /* 21130588217SMike Christensen * Initialize the list of ports based on the MD. 21230588217SMike Christensen */ 21330588217SMike Christensen static int 21430588217SMike Christensen ds_ports_init(void) 21530588217SMike Christensen { 21630588217SMike Christensen int idx; 21730588217SMike Christensen int rv = 0; 21830588217SMike Christensen md_t *mdp; 21930588217SMike Christensen int num_nodes; 22030588217SMike Christensen int listsz; 22130588217SMike Christensen mde_cookie_t rootnode; 22230588217SMike Christensen mde_cookie_t dsnode; 22330588217SMike Christensen mde_cookie_t *portp = NULL; 22430588217SMike Christensen mde_cookie_t *chanp = NULL; 22530588217SMike Christensen int nport; 22630588217SMike Christensen int nchan; 22730588217SMike Christensen 22830588217SMike Christensen if ((mdp = md_get_handle()) == NULL) { 22930588217SMike Christensen cmn_err(CE_WARN, "Unable to initialize machine description"); 23030588217SMike Christensen return (-1); 23130588217SMike Christensen } 23230588217SMike Christensen 23330588217SMike Christensen num_nodes = md_node_count(mdp); 23430588217SMike Christensen ASSERT(num_nodes > 0); 23530588217SMike Christensen 23630588217SMike Christensen listsz = num_nodes * sizeof (mde_cookie_t); 23730588217SMike Christensen 23830588217SMike Christensen /* allocate temporary storage for MD scans */ 23930588217SMike Christensen portp = kmem_zalloc(listsz, KM_SLEEP); 24030588217SMike Christensen chanp = kmem_zalloc(listsz, KM_SLEEP); 24130588217SMike Christensen 24230588217SMike Christensen rootnode = md_root_node(mdp); 24330588217SMike Christensen ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 24430588217SMike Christensen 24530588217SMike Christensen /* 24630588217SMike Christensen * The root of the search for DS port nodes is the 24730588217SMike Christensen * DS node. Perform a scan to find that node. 24830588217SMike Christensen */ 24930588217SMike Christensen nport = md_scan_dag(mdp, rootnode, md_find_name(mdp, DS_MD_ROOT_NAME), 25030588217SMike Christensen md_find_name(mdp, "fwd"), portp); 25130588217SMike Christensen 25230588217SMike Christensen if (nport <= 0) { 25330588217SMike Christensen DS_DBG_MD(CE_NOTE, "No '%s' node in MD", DS_MD_ROOT_NAME); 25430588217SMike Christensen goto done; 25530588217SMike Christensen } 25630588217SMike Christensen 25730588217SMike Christensen /* expecting only one DS node */ 25830588217SMike Christensen if (nport != 1) { 25930588217SMike Christensen DS_DBG_MD(CE_NOTE, "Expected one '%s' node in the MD, found %d", 26030588217SMike Christensen DS_MD_ROOT_NAME, nport); 26130588217SMike Christensen } 26230588217SMike Christensen 26330588217SMike Christensen dsnode = portp[0]; 26430588217SMike Christensen 26530588217SMike Christensen /* find all the DS ports in the MD */ 26630588217SMike Christensen nport = md_scan_dag(mdp, dsnode, md_find_name(mdp, DS_MD_PORT_NAME), 26730588217SMike Christensen md_find_name(mdp, "fwd"), portp); 26830588217SMike Christensen 26930588217SMike Christensen if (nport <= 0) { 27030588217SMike Christensen DS_DBG_MD(CE_NOTE, "No '%s' nodes in MD", DS_MD_PORT_NAME); 27130588217SMike Christensen goto done; 27230588217SMike Christensen } 27330588217SMike Christensen 27430588217SMike Christensen /* 27530588217SMike Christensen * Initialize all the ports found in the MD. 27630588217SMike Christensen */ 27730588217SMike Christensen for (idx = 0; idx < nport; idx++) { 27830588217SMike Christensen 27930588217SMike Christensen /* get the channels for this port */ 28030588217SMike Christensen nchan = md_scan_dag(mdp, portp[idx], 28130588217SMike Christensen md_find_name(mdp, DS_MD_CHAN_NAME), 28230588217SMike Christensen md_find_name(mdp, "fwd"), chanp); 28330588217SMike Christensen 28430588217SMike Christensen if (nchan <= 0) { 28530588217SMike Christensen cmn_err(CE_WARN, "No '%s' node for DS port", 28630588217SMike Christensen DS_MD_CHAN_NAME); 28730588217SMike Christensen rv = -1; 28830588217SMike Christensen goto done; 28930588217SMike Christensen } 29030588217SMike Christensen 29130588217SMike Christensen /* expecting only one channel */ 29230588217SMike Christensen if (nchan != 1) { 29330588217SMike Christensen DS_DBG_MD(CE_NOTE, "Expected one '%s' node for DS " 29430588217SMike Christensen " port, found %d", DS_MD_CHAN_NAME, nchan); 29530588217SMike Christensen } 29630588217SMike Christensen 29730588217SMike Christensen if (ds_port_add(mdp, portp[idx], chanp[0]) != 0) { 29830588217SMike Christensen rv = -1; 29930588217SMike Christensen goto done; 30030588217SMike Christensen } 30130588217SMike Christensen } 30230588217SMike Christensen 30330588217SMike Christensen done: 30430588217SMike Christensen if (rv != 0) 30530588217SMike Christensen (void) ds_ports_fini(); 30630588217SMike Christensen 30730588217SMike Christensen DS_FREE(portp, listsz); 30830588217SMike Christensen DS_FREE(chanp, listsz); 30930588217SMike Christensen 31030588217SMike Christensen (void) md_fini_handle(mdp); 31130588217SMike Christensen 31230588217SMike Christensen return (rv); 31330588217SMike Christensen } 31430588217SMike Christensen 31530588217SMike Christensen static int 31630588217SMike Christensen ds_ports_fini(void) 31730588217SMike Christensen { 31830588217SMike Christensen int idx; 31930588217SMike Christensen 32030588217SMike Christensen /* 32130588217SMike Christensen * Tear down each initialized port. 32230588217SMike Christensen */ 32330588217SMike Christensen for (idx = 0; idx < DS_MAX_PORTS; idx++) { 32430588217SMike Christensen if (DS_PORT_IN_SET(ds_allports, idx)) { 32530588217SMike Christensen (void) ds_remove_port(idx, 1); 32630588217SMike Christensen } 32730588217SMike Christensen } 32830588217SMike Christensen 32930588217SMike Christensen return (0); 33030588217SMike Christensen } 33130588217SMike Christensen 33230588217SMike Christensen static int 33330588217SMike Christensen ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan) 33430588217SMike Christensen { 33530588217SMike Christensen uint64_t port_id; 33630588217SMike Christensen uint64_t ldc_id; 33740c61268SMike Christensen uint8_t *ldcidsp; 33840c61268SMike Christensen int len; 33930588217SMike Christensen 34030588217SMike Christensen /* get the ID for this port */ 34130588217SMike Christensen if (md_get_prop_val(mdp, port, "id", &port_id) != 0) { 34230588217SMike Christensen cmn_err(CE_WARN, "%s: port 'id' property not found", 34330588217SMike Christensen __func__); 34430588217SMike Christensen return (-1); 34530588217SMike Christensen } 34630588217SMike Christensen 34730588217SMike Christensen /* sanity check the port id */ 34830588217SMike Christensen if (port_id > DS_MAX_PORT_ID) { 34930588217SMike Christensen cmn_err(CE_WARN, "%s: port ID %ld out of range", 35030588217SMike Christensen __func__, port_id); 35130588217SMike Christensen return (-1); 35230588217SMike Christensen } 35330588217SMike Christensen 35430588217SMike Christensen /* get the channel ID for this port */ 35530588217SMike Christensen if (md_get_prop_val(mdp, chan, "id", &ldc_id) != 0) { 35630588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: no channel 'id' property", 35730588217SMike Christensen port_id, __func__); 35830588217SMike Christensen return (-1); 35930588217SMike Christensen } 36030588217SMike Christensen 361a600f50dSMike Christensen if (ds_add_port(port_id, ldc_id, DS_DHDL_INVALID, NULL, 1) != 0) 36230588217SMike Christensen return (-1); 36330588217SMike Christensen 36440c61268SMike Christensen /* 36540c61268SMike Christensen * Identify the SP Port. The SP port is the only one with 36640c61268SMike Christensen * the "ldc-ids" property, and is only on the primary domain. 36740c61268SMike Christensen */ 36840c61268SMike Christensen if (ds_sp_port_id == DS_PORTID_INVALID && 36940c61268SMike Christensen md_get_prop_data(mdp, port, "ldc-ids", &ldcidsp, &len) == 0) { 37040c61268SMike Christensen ds_sp_port_id = port_id; 37140c61268SMike Christensen } 37240c61268SMike Christensen 37330588217SMike Christensen return (0); 37430588217SMike Christensen } 37530588217SMike Christensen 37630588217SMike Christensen void 377a600f50dSMike Christensen ds_set_my_dom_hdl_name(ds_domain_hdl_t dhdl, char *name) 378a600f50dSMike Christensen { 379a600f50dSMike Christensen ds_my_domain_hdl = dhdl; 380a600f50dSMike Christensen if (ds_my_domain_name != NULL) { 381a600f50dSMike Christensen DS_FREE(ds_my_domain_name, strlen(ds_my_domain_name)+1); 382a600f50dSMike Christensen ds_my_domain_name = NULL; 383a600f50dSMike Christensen } 384a600f50dSMike Christensen if (name != NULL) { 385a600f50dSMike Christensen ds_my_domain_name = ds_strdup(name); 386a600f50dSMike Christensen } 387a600f50dSMike Christensen } 388a600f50dSMike Christensen 389a600f50dSMike Christensen void 39030588217SMike Christensen ds_init() 39130588217SMike Christensen { 39230588217SMike Christensen ds_common_init(); 39330588217SMike Christensen 39430588217SMike Christensen /* 39530588217SMike Christensen * Create taskq for internal processing threads. This 39630588217SMike Christensen * includes processing incoming request messages and 39730588217SMike Christensen * sending out of band registration messages. 39830588217SMike Christensen */ 39930588217SMike Christensen ds_taskq = taskq_create("ds_taskq", 1, minclsyspri, 1, 40030588217SMike Christensen DS_MAX_TASKQ_THR, TASKQ_PREPOPULATE | TASKQ_DYNAMIC); 40130588217SMike Christensen 40230588217SMike Christensen /* 40330588217SMike Christensen * Initialize the message log. 40430588217SMike Christensen */ 40530588217SMike Christensen ds_log_init(); 40630588217SMike Christensen } 40730588217SMike Christensen 40830588217SMike Christensen int 40930588217SMike Christensen ds_sys_dispatch_func(void (func)(void *), void *arg) 41030588217SMike Christensen { 41130588217SMike Christensen return (DS_DISPATCH(func, arg) == NULL); 41230588217SMike Christensen } 41330588217SMike Christensen 41430588217SMike Christensen /* 41530588217SMike Christensen * Drain event queue, if necessary. 41630588217SMike Christensen */ 41730588217SMike Christensen void 41830588217SMike Christensen ds_sys_drain_events(ds_port_t *port) 41930588217SMike Christensen { 42030588217SMike Christensen _NOTE(ARGUNUSED(port)) 42130588217SMike Christensen } 42230588217SMike Christensen 42330588217SMike Christensen /* 42430588217SMike Christensen * System specific port initalization. 42530588217SMike Christensen */ 42630588217SMike Christensen void 42730588217SMike Christensen ds_sys_port_init(ds_port_t *port) 42830588217SMike Christensen { 42930588217SMike Christensen _NOTE(ARGUNUSED(port)) 43030588217SMike Christensen } 43130588217SMike Christensen 43230588217SMike Christensen /* 43330588217SMike Christensen * System specific port teardown. 43430588217SMike Christensen */ 43530588217SMike Christensen void 43630588217SMike Christensen ds_sys_port_fini(ds_port_t *port) 43730588217SMike Christensen { 43830588217SMike Christensen _NOTE(ARGUNUSED(port)) 43930588217SMike Christensen } 44030588217SMike Christensen 44130588217SMike Christensen /* 44230588217SMike Christensen * System specific LDC channel initialization. 44330588217SMike Christensen */ 44430588217SMike Christensen void 44530588217SMike Christensen ds_sys_ldc_init(ds_port_t *port) 44630588217SMike Christensen { 44730588217SMike Christensen int rv; 44830588217SMike Christensen char ebuf[DS_EBUFSIZE]; 44930588217SMike Christensen 45030588217SMike Christensen ASSERT(MUTEX_HELD(&port->lock)); 45130588217SMike Christensen 45230588217SMike Christensen if ((rv = ldc_open(port->ldc.hdl)) != 0) { 45330588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_open: %s", 45430588217SMike Christensen PORTID(port), __func__, ds_errno_to_str(rv, ebuf)); 45530588217SMike Christensen return; 45630588217SMike Christensen } 45730588217SMike Christensen 45830588217SMike Christensen (void) ldc_up(port->ldc.hdl); 45930588217SMike Christensen 46030588217SMike Christensen (void) ldc_status(port->ldc.hdl, &port->ldc.state); 46130588217SMike Christensen 46230588217SMike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: initial LDC state 0x%x", 46330588217SMike Christensen PORTID(port), __func__, port->ldc.state); 46430588217SMike Christensen 46530588217SMike Christensen port->state = DS_PORT_LDC_INIT; 46630588217SMike Christensen } 46730588217SMike Christensen 46830588217SMike Christensen /* 46930588217SMike Christensen * DS message log 47030588217SMike Christensen * 47130588217SMike Christensen * Locking: The message log is protected by a single mutex. This 47230588217SMike Christensen * protects all fields in the log structure itself as well as 47330588217SMike Christensen * everything in the entry structures on both the log and the 47430588217SMike Christensen * free list. 47530588217SMike Christensen */ 47630588217SMike Christensen static struct log { 47730588217SMike Christensen ds_log_entry_t *head; /* head of the log */ 47830588217SMike Christensen ds_log_entry_t *freelist; /* head of the free list */ 47930588217SMike Christensen size_t size; /* size of the log in bytes */ 48030588217SMike Christensen uint32_t nentry; /* number of entries */ 48130588217SMike Christensen kmutex_t lock; /* log lock */ 48230588217SMike Christensen } ds_log; 48330588217SMike Christensen 48430588217SMike Christensen /* log soft limit */ 48530588217SMike Christensen uint_t ds_log_sz = DS_LOG_DEFAULT_SZ; 48630588217SMike Christensen 48730588217SMike Christensen /* initial pool of log entry structures */ 48830588217SMike Christensen static ds_log_entry_t ds_log_entry_pool[DS_LOG_NPOOL]; 48930588217SMike Christensen 49030588217SMike Christensen /* 49130588217SMike Christensen * Logging Support 49230588217SMike Christensen */ 49330588217SMike Christensen static void 49430588217SMike Christensen ds_log_init(void) 49530588217SMike Christensen { 49630588217SMike Christensen ds_log_entry_t *new; 49730588217SMike Christensen 49830588217SMike Christensen /* initialize global lock */ 49930588217SMike Christensen mutex_init(&ds_log.lock, NULL, MUTEX_DRIVER, NULL); 50030588217SMike Christensen 50130588217SMike Christensen mutex_enter(&ds_log.lock); 50230588217SMike Christensen 50330588217SMike Christensen /* initialize the log */ 50430588217SMike Christensen ds_log.head = NULL; 50530588217SMike Christensen ds_log.size = 0; 50630588217SMike Christensen ds_log.nentry = 0; 50730588217SMike Christensen 50830588217SMike Christensen /* initialize the free list */ 50930588217SMike Christensen for (new = ds_log_entry_pool; new < DS_LOG_POOL_END; new++) { 51030588217SMike Christensen new->next = ds_log.freelist; 51130588217SMike Christensen ds_log.freelist = new; 51230588217SMike Christensen } 51330588217SMike Christensen 51430588217SMike Christensen mutex_exit(&ds_log.lock); 51530588217SMike Christensen 51630588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log initialized: size=%d bytes, " 51730588217SMike Christensen " limit=%d bytes, ninit=%ld", ds_log_sz, DS_LOG_LIMIT, 51830588217SMike Christensen DS_LOG_NPOOL); 51930588217SMike Christensen } 52030588217SMike Christensen 52130588217SMike Christensen static void 52230588217SMike Christensen ds_log_fini(void) 52330588217SMike Christensen { 52430588217SMike Christensen ds_log_entry_t *next; 52530588217SMike Christensen 52630588217SMike Christensen mutex_enter(&ds_log.lock); 52730588217SMike Christensen 52830588217SMike Christensen /* clear out the log */ 52930588217SMike Christensen while (ds_log.nentry > 0) 53030588217SMike Christensen (void) ds_log_remove(); 53130588217SMike Christensen 53230588217SMike Christensen /* 53330588217SMike Christensen * Now all the entries are on the free list. 53430588217SMike Christensen * Clear out the free list, deallocating any 53530588217SMike Christensen * entry that was dynamically allocated. 53630588217SMike Christensen */ 53730588217SMike Christensen while (ds_log.freelist != NULL) { 53830588217SMike Christensen next = ds_log.freelist->next; 53930588217SMike Christensen 54030588217SMike Christensen if (!DS_IS_POOL_ENTRY(ds_log.freelist)) { 54130588217SMike Christensen kmem_free(ds_log.freelist, sizeof (ds_log_entry_t)); 54230588217SMike Christensen } 54330588217SMike Christensen 54430588217SMike Christensen ds_log.freelist = next; 54530588217SMike Christensen } 54630588217SMike Christensen 54730588217SMike Christensen mutex_exit(&ds_log.lock); 54830588217SMike Christensen 54930588217SMike Christensen mutex_destroy(&ds_log.lock); 55030588217SMike Christensen } 55130588217SMike Christensen 55230588217SMike Christensen static ds_log_entry_t * 55330588217SMike Christensen ds_log_entry_alloc(void) 55430588217SMike Christensen { 55530588217SMike Christensen ds_log_entry_t *new = NULL; 55630588217SMike Christensen 55730588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock)); 55830588217SMike Christensen 55930588217SMike Christensen if (ds_log.freelist != NULL) { 56030588217SMike Christensen new = ds_log.freelist; 56130588217SMike Christensen ds_log.freelist = ds_log.freelist->next; 56230588217SMike Christensen } 56330588217SMike Christensen 56430588217SMike Christensen if (new == NULL) { 56530588217SMike Christensen /* free list was empty */ 56630588217SMike Christensen new = kmem_zalloc(sizeof (ds_log_entry_t), KM_SLEEP); 56730588217SMike Christensen } 56830588217SMike Christensen 56930588217SMike Christensen ASSERT(new); 57030588217SMike Christensen 57130588217SMike Christensen return (new); 57230588217SMike Christensen } 57330588217SMike Christensen 57430588217SMike Christensen static void 57530588217SMike Christensen ds_log_entry_free(ds_log_entry_t *entry) 57630588217SMike Christensen { 57730588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock)); 57830588217SMike Christensen 57930588217SMike Christensen if (entry == NULL) 58030588217SMike Christensen return; 58130588217SMike Christensen 58230588217SMike Christensen if (entry->data != NULL) { 58330588217SMike Christensen kmem_free(entry->data, entry->datasz); 58430588217SMike Christensen entry->data = NULL; 58530588217SMike Christensen } 58630588217SMike Christensen 58730588217SMike Christensen /* place entry on the free list */ 58830588217SMike Christensen entry->next = ds_log.freelist; 58930588217SMike Christensen ds_log.freelist = entry; 59030588217SMike Christensen } 59130588217SMike Christensen 59230588217SMike Christensen /* 59330588217SMike Christensen * Add a message to the end of the log 59430588217SMike Christensen */ 59530588217SMike Christensen static int 59630588217SMike Christensen ds_log_add(ds_log_entry_t *new) 59730588217SMike Christensen { 59830588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock)); 59930588217SMike Christensen 60030588217SMike Christensen if (ds_log.head == NULL) { 60130588217SMike Christensen 60230588217SMike Christensen new->prev = new; 60330588217SMike Christensen new->next = new; 60430588217SMike Christensen 60530588217SMike Christensen ds_log.head = new; 60630588217SMike Christensen } else { 60730588217SMike Christensen ds_log_entry_t *head = ds_log.head; 60830588217SMike Christensen ds_log_entry_t *tail = ds_log.head->prev; 60930588217SMike Christensen 61030588217SMike Christensen new->next = head; 61130588217SMike Christensen new->prev = tail; 61230588217SMike Christensen tail->next = new; 61330588217SMike Christensen head->prev = new; 61430588217SMike Christensen } 61530588217SMike Christensen 61630588217SMike Christensen /* increase the log size, including the metadata size */ 61730588217SMike Christensen ds_log.size += DS_LOG_ENTRY_SZ(new); 61830588217SMike Christensen ds_log.nentry++; 61930588217SMike Christensen 62030588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: added %ld data bytes, %ld total bytes", 62130588217SMike Christensen new->datasz, DS_LOG_ENTRY_SZ(new)); 62230588217SMike Christensen 62330588217SMike Christensen return (0); 62430588217SMike Christensen } 62530588217SMike Christensen 62630588217SMike Christensen /* 62730588217SMike Christensen * Remove an entry from the head of the log 62830588217SMike Christensen */ 62930588217SMike Christensen static int 63030588217SMike Christensen ds_log_remove(void) 63130588217SMike Christensen { 63230588217SMike Christensen ds_log_entry_t *head; 63330588217SMike Christensen 63430588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock)); 63530588217SMike Christensen 63630588217SMike Christensen head = ds_log.head; 63730588217SMike Christensen 63830588217SMike Christensen /* empty list */ 63930588217SMike Christensen if (head == NULL) 64030588217SMike Christensen return (0); 64130588217SMike Christensen 64230588217SMike Christensen if (head->next == ds_log.head) { 64330588217SMike Christensen /* one element list */ 64430588217SMike Christensen ds_log.head = NULL; 64530588217SMike Christensen } else { 64630588217SMike Christensen head->next->prev = head->prev; 64730588217SMike Christensen head->prev->next = head->next; 64830588217SMike Christensen ds_log.head = head->next; 64930588217SMike Christensen } 65030588217SMike Christensen 65130588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: removed %ld data bytes, %ld total bytes", 65230588217SMike Christensen head->datasz, DS_LOG_ENTRY_SZ(head)); 65330588217SMike Christensen 65430588217SMike Christensen ds_log.size -= DS_LOG_ENTRY_SZ(head); 65530588217SMike Christensen ds_log.nentry--; 65630588217SMike Christensen 65730588217SMike Christensen ds_log_entry_free(head); 65830588217SMike Christensen 65930588217SMike Christensen return (0); 66030588217SMike Christensen } 66130588217SMike Christensen 66230588217SMike Christensen /* 66330588217SMike Christensen * Replace the data in the entry at the front of the list with then 66430588217SMike Christensen * new data. This has the effect of removing the oldest entry and 66530588217SMike Christensen * adding the new entry. 66630588217SMike Christensen */ 66730588217SMike Christensen static int 66830588217SMike Christensen ds_log_replace(int32_t dest, uint8_t *msg, size_t sz) 66930588217SMike Christensen { 67030588217SMike Christensen ds_log_entry_t *head; 67130588217SMike Christensen 67230588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock)); 67330588217SMike Christensen 67430588217SMike Christensen head = ds_log.head; 67530588217SMike Christensen 67630588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: replaced %ld data bytes (%ld total) with " 67730588217SMike Christensen " %ld data bytes (%ld total)", head->datasz, 67830588217SMike Christensen DS_LOG_ENTRY_SZ(head), sz, sz + sizeof (ds_log_entry_t)); 67930588217SMike Christensen 68030588217SMike Christensen ds_log.size -= DS_LOG_ENTRY_SZ(head); 68130588217SMike Christensen 68230588217SMike Christensen kmem_free(head->data, head->datasz); 68330588217SMike Christensen 68430588217SMike Christensen head->data = msg; 68530588217SMike Christensen head->datasz = sz; 68630588217SMike Christensen head->timestamp = ddi_get_time(); 68730588217SMike Christensen head->dest = dest; 68830588217SMike Christensen 68930588217SMike Christensen ds_log.size += DS_LOG_ENTRY_SZ(head); 69030588217SMike Christensen 69130588217SMike Christensen ds_log.head = head->next; 69230588217SMike Christensen 69330588217SMike Christensen return (0); 69430588217SMike Christensen } 69530588217SMike Christensen 69630588217SMike Christensen static void 69730588217SMike Christensen ds_log_purge(void *arg) 69830588217SMike Christensen { 69930588217SMike Christensen _NOTE(ARGUNUSED(arg)) 70030588217SMike Christensen 70130588217SMike Christensen mutex_enter(&ds_log.lock); 70230588217SMike Christensen 70330588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: purging oldest log entries"); 70430588217SMike Christensen 70530588217SMike Christensen while ((ds_log.nentry) && (ds_log.size >= ds_log_sz)) { 70630588217SMike Christensen (void) ds_log_remove(); 70730588217SMike Christensen } 70830588217SMike Christensen 70930588217SMike Christensen mutex_exit(&ds_log.lock); 71030588217SMike Christensen } 71130588217SMike Christensen 71230588217SMike Christensen int 71330588217SMike Christensen ds_log_add_msg(int32_t dest, uint8_t *msg, size_t sz) 71430588217SMike Christensen { 71530588217SMike Christensen int rv = 0; 71630588217SMike Christensen void *data; 71730588217SMike Christensen 71830588217SMike Christensen mutex_enter(&ds_log.lock); 71930588217SMike Christensen 72030588217SMike Christensen /* allocate a local copy of the data */ 72130588217SMike Christensen data = kmem_alloc(sz, KM_SLEEP); 72230588217SMike Christensen bcopy(msg, data, sz); 72330588217SMike Christensen 72430588217SMike Christensen /* check if the log is larger than the soft limit */ 72530588217SMike Christensen if ((ds_log.nentry) && ((ds_log.size + sz) >= ds_log_sz)) { 72630588217SMike Christensen /* 72730588217SMike Christensen * The log is larger than the soft limit. 72830588217SMike Christensen * Swap the oldest entry for the newest. 72930588217SMike Christensen */ 73030588217SMike Christensen DS_DBG_LOG(CE_NOTE, "%s: replacing oldest entry with new entry", 73130588217SMike Christensen __func__); 73230588217SMike Christensen (void) ds_log_replace(dest, data, sz); 73330588217SMike Christensen } else { 73430588217SMike Christensen /* 73530588217SMike Christensen * Still have headroom under the soft limit. 73630588217SMike Christensen * Add the new entry to the log. 73730588217SMike Christensen */ 73830588217SMike Christensen ds_log_entry_t *new; 73930588217SMike Christensen 74030588217SMike Christensen new = ds_log_entry_alloc(); 74130588217SMike Christensen 74230588217SMike Christensen /* fill in message data */ 74330588217SMike Christensen new->data = data; 74430588217SMike Christensen new->datasz = sz; 74530588217SMike Christensen new->timestamp = ddi_get_time(); 74630588217SMike Christensen new->dest = dest; 74730588217SMike Christensen 74830588217SMike Christensen rv = ds_log_add(new); 74930588217SMike Christensen } 75030588217SMike Christensen 75130588217SMike Christensen /* check if the log is larger than the hard limit */ 75230588217SMike Christensen if ((ds_log.nentry > 1) && (ds_log.size >= DS_LOG_LIMIT)) { 75330588217SMike Christensen /* 75430588217SMike Christensen * Wakeup the thread to remove entries 75530588217SMike Christensen * from the log until it is smaller than 75630588217SMike Christensen * the soft limit. 75730588217SMike Christensen */ 75830588217SMike Christensen DS_DBG_LOG(CE_NOTE, "%s: log exceeded %d bytes, scheduling" 75930588217SMike Christensen " a purge...", __func__, DS_LOG_LIMIT); 76030588217SMike Christensen 76130588217SMike Christensen if (DS_DISPATCH(ds_log_purge, NULL) == NULL) { 76230588217SMike Christensen cmn_err(CE_NOTE, "%s: purge thread failed to start", 76330588217SMike Christensen __func__); 76430588217SMike Christensen } 76530588217SMike Christensen } 76630588217SMike Christensen 76730588217SMike Christensen mutex_exit(&ds_log.lock); 76830588217SMike Christensen 76930588217SMike Christensen return (rv); 77030588217SMike Christensen } 77130588217SMike Christensen 77230588217SMike Christensen int 77330588217SMike Christensen ds_add_port(uint64_t port_id, uint64_t ldc_id, ds_domain_hdl_t dhdl, 77430588217SMike Christensen char *dom_name, int verbose) 77530588217SMike Christensen { 77630588217SMike Christensen ds_port_t *newport; 77730588217SMike Christensen 77830588217SMike Christensen /* sanity check the port id */ 77930588217SMike Christensen if (port_id > DS_MAX_PORT_ID) { 78030588217SMike Christensen cmn_err(CE_WARN, "%s: port ID %ld out of range", 78130588217SMike Christensen __func__, port_id); 78230588217SMike Christensen return (EINVAL); 78330588217SMike Christensen } 78430588217SMike Christensen 785a600f50dSMike Christensen DS_DBG_MD(CE_NOTE, "%s: adding port ds@%ld, LDC: 0x%lx, dhdl: 0x%lx " 786a600f50dSMike Christensen "name: '%s'", __func__, port_id, ldc_id, dhdl, 787a600f50dSMike Christensen dom_name == NULL ? "NULL" : dom_name); 78830588217SMike Christensen 78930588217SMike Christensen /* get the port structure from the array of ports */ 79030588217SMike Christensen newport = &ds_ports[port_id]; 79130588217SMike Christensen 79230588217SMike Christensen /* check for a duplicate port in the MD */ 79330588217SMike Christensen if (newport->state != DS_PORT_FREE) { 79430588217SMike Christensen if (verbose) { 79530588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: port already exists", 79630588217SMike Christensen port_id, __func__); 79730588217SMike Christensen } 79830588217SMike Christensen if (newport->domain_hdl == DS_DHDL_INVALID) { 79930588217SMike Christensen newport->domain_hdl = dhdl; 80030588217SMike Christensen } 80130588217SMike Christensen if (newport->domain_name == NULL && dom_name != NULL) { 80230588217SMike Christensen newport->domain_name = ds_strdup(dom_name); 80330588217SMike Christensen } 80430588217SMike Christensen return (EBUSY); 80530588217SMike Christensen } 80630588217SMike Christensen 80730588217SMike Christensen /* initialize the port */ 80830588217SMike Christensen newport->id = port_id; 80930588217SMike Christensen newport->ldc.id = ldc_id; 81030588217SMike Christensen newport->domain_hdl = dhdl; 81130588217SMike Christensen if (dom_name) { 81230588217SMike Christensen newport->domain_name = ds_strdup(dom_name); 81330588217SMike Christensen } else 81430588217SMike Christensen newport->domain_name = NULL; 81530588217SMike Christensen ds_port_common_init(newport); 81630588217SMike Christensen 81730588217SMike Christensen return (0); 81830588217SMike Christensen } 81930588217SMike Christensen 820*beba1dd8SMike Christensen /* ARGSUSED */ 82130588217SMike Christensen int 82230588217SMike Christensen ds_remove_port(uint64_t port_id, int is_fini) 82330588217SMike Christensen { 82430588217SMike Christensen ds_port_t *port; 82530588217SMike Christensen 82630588217SMike Christensen if (port_id >= DS_MAX_PORTS || !DS_PORT_IN_SET(ds_allports, port_id)) { 82730588217SMike Christensen DS_DBG_MD(CE_NOTE, "%s: invalid port %lx", __func__, 82830588217SMike Christensen port_id); 82930588217SMike Christensen return (EINVAL); 83030588217SMike Christensen } 83130588217SMike Christensen 83230588217SMike Christensen DS_DBG_MD(CE_NOTE, "%s: removing port ds@%lx", __func__, port_id); 83330588217SMike Christensen 83430588217SMike Christensen port = &ds_ports[port_id]; 83530588217SMike Christensen 83630588217SMike Christensen mutex_enter(&port->lock); 83730588217SMike Christensen 83830588217SMike Christensen if (port->state >= DS_PORT_LDC_INIT) { 83930588217SMike Christensen /* shut down the LDC for this port */ 84030588217SMike Christensen (void) ds_ldc_fini(port); 84130588217SMike Christensen } 84230588217SMike Christensen 84330588217SMike Christensen if (port->domain_name) { 84430588217SMike Christensen DS_FREE(port->domain_name, strlen(port->domain_name) + 1); 84530588217SMike Christensen port->domain_name = NULL; 84630588217SMike Christensen } 84730588217SMike Christensen port->domain_hdl = DS_DHDL_INVALID; 84830588217SMike Christensen 84930588217SMike Christensen /* clean up the port structure */ 850*beba1dd8SMike Christensen ds_port_common_fini(port); 851*beba1dd8SMike Christensen 852*beba1dd8SMike Christensen mutex_exit(&port->lock); 85330588217SMike Christensen return (0); 85430588217SMike Christensen } 85530588217SMike Christensen 85630588217SMike Christensen /* 85730588217SMike Christensen * Interface for ds_service_lookup in lds driver. 85830588217SMike Christensen */ 85930588217SMike Christensen int 86030588217SMike Christensen ds_service_lookup(ds_svc_hdl_t hdl, char **servicep, uint_t *is_client) 86130588217SMike Christensen { 86230588217SMike Christensen ds_svc_t *svc; 86330588217SMike Christensen 86430588217SMike Christensen mutex_enter(&ds_svcs.lock); 86530588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) { 86630588217SMike Christensen mutex_exit(&ds_svcs.lock); 86730588217SMike Christensen DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 86830588217SMike Christensen (u_longlong_t)hdl); 86930588217SMike Christensen return (ENXIO); 87030588217SMike Christensen } 87130588217SMike Christensen *servicep = svc->cap.svc_id; 87230588217SMike Christensen *is_client = svc->flags & DSSF_ISCLIENT; 87330588217SMike Christensen mutex_exit(&ds_svcs.lock); 87430588217SMike Christensen return (0); 87530588217SMike Christensen } 87630588217SMike Christensen 87730588217SMike Christensen /* 87830588217SMike Christensen * Interface for ds_domain_lookup in lds driver. 87930588217SMike Christensen */ 88030588217SMike Christensen int 88130588217SMike Christensen ds_domain_lookup(ds_svc_hdl_t hdl, ds_domain_hdl_t *dhdlp) 88230588217SMike Christensen { 88330588217SMike Christensen ds_svc_t *svc; 88430588217SMike Christensen 88530588217SMike Christensen mutex_enter(&ds_svcs.lock); 88630588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) { 88730588217SMike Christensen mutex_exit(&ds_svcs.lock); 88830588217SMike Christensen DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 88930588217SMike Christensen (u_longlong_t)hdl); 89030588217SMike Christensen return (ENXIO); 89130588217SMike Christensen } 89230588217SMike Christensen if (svc->port == NULL) 89330588217SMike Christensen *dhdlp = ds_my_domain_hdl; 89430588217SMike Christensen else 89530588217SMike Christensen *dhdlp = svc->port->domain_hdl; 89630588217SMike Christensen mutex_exit(&ds_svcs.lock); 89730588217SMike Christensen return (0); 89830588217SMike Christensen } 89930588217SMike Christensen 90030588217SMike Christensen /* 90130588217SMike Christensen * Interface for ds_hdl_isready in lds driver. 90230588217SMike Christensen */ 90330588217SMike Christensen int 90430588217SMike Christensen ds_hdl_isready(ds_svc_hdl_t hdl, uint_t *is_ready) 90530588217SMike Christensen { 90630588217SMike Christensen ds_svc_t *svc; 90730588217SMike Christensen 90830588217SMike Christensen mutex_enter(&ds_svcs.lock); 90930588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) { 91030588217SMike Christensen mutex_exit(&ds_svcs.lock); 91130588217SMike Christensen DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__, 91230588217SMike Christensen (u_longlong_t)hdl); 91330588217SMike Christensen return (ENXIO); 91430588217SMike Christensen } 91530588217SMike Christensen *is_ready = (svc->state == DS_SVC_ACTIVE); 91630588217SMike Christensen mutex_exit(&ds_svcs.lock); 91730588217SMike Christensen return (0); 91830588217SMike Christensen } 91930588217SMike Christensen 92030588217SMike Christensen /* 92130588217SMike Christensen * Interface for ds_dom_name_to_hdl in lds driver. 92230588217SMike Christensen */ 92330588217SMike Christensen int 92430588217SMike Christensen ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp) 92530588217SMike Christensen { 92630588217SMike Christensen int i; 92730588217SMike Christensen ds_port_t *port; 92830588217SMike Christensen 929a600f50dSMike Christensen if (domain_name == NULL) { 930a600f50dSMike Christensen return (ENXIO); 931a600f50dSMike Christensen } 932a600f50dSMike Christensen if (ds_my_domain_name != NULL && 933a600f50dSMike Christensen strcmp(ds_my_domain_name, domain_name) == 0) { 934a600f50dSMike Christensen *dhdlp = ds_my_domain_hdl; 935a600f50dSMike Christensen return (0); 936a600f50dSMike Christensen } 93730588217SMike Christensen for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) { 93830588217SMike Christensen if (port->state != DS_PORT_FREE && 93930588217SMike Christensen port->domain_name != NULL && 94030588217SMike Christensen strcmp(port->domain_name, domain_name) == 0) { 94130588217SMike Christensen *dhdlp = port->domain_hdl; 94230588217SMike Christensen return (0); 94330588217SMike Christensen } 94430588217SMike Christensen } 94530588217SMike Christensen return (ENXIO); 94630588217SMike Christensen } 94730588217SMike Christensen 94830588217SMike Christensen /* 94930588217SMike Christensen * Interface for ds_dom_hdl_to_name in lds driver. 95030588217SMike Christensen */ 95130588217SMike Christensen int 95230588217SMike Christensen ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char **domain_namep) 95330588217SMike Christensen { 95430588217SMike Christensen int i; 95530588217SMike Christensen ds_port_t *port; 95630588217SMike Christensen 957a600f50dSMike Christensen if (dhdl == ds_my_domain_hdl) { 958a600f50dSMike Christensen if (ds_my_domain_name != NULL) { 959a600f50dSMike Christensen *domain_namep = ds_my_domain_name; 960a600f50dSMike Christensen return (0); 961a600f50dSMike Christensen } 962a600f50dSMike Christensen return (ENXIO); 963a600f50dSMike Christensen } 96430588217SMike Christensen for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) { 96530588217SMike Christensen if (port->state != DS_PORT_FREE && 96630588217SMike Christensen port->domain_hdl == dhdl) { 96730588217SMike Christensen *domain_namep = port->domain_name; 96830588217SMike Christensen return (0); 96930588217SMike Christensen } 97030588217SMike Christensen } 97130588217SMike Christensen return (ENXIO); 97230588217SMike Christensen } 97330588217SMike Christensen 97430588217SMike Christensen /* 97530588217SMike Christensen * Unregister all handles related to device open instance. 97630588217SMike Christensen */ 97730588217SMike Christensen void 97830588217SMike Christensen ds_unreg_all(int instance) 97930588217SMike Christensen { 98030588217SMike Christensen int idx; 98130588217SMike Christensen ds_svc_t *svc; 98230588217SMike Christensen ds_svc_hdl_t hdl; 98330588217SMike Christensen 98430588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: entered", __func__); 98530588217SMike Christensen 98630588217SMike Christensen /* walk every table entry */ 98730588217SMike Christensen mutex_enter(&ds_svcs.lock); 98830588217SMike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) { 98930588217SMike Christensen svc = ds_svcs.tbl[idx]; 99030588217SMike Christensen if (DS_SVC_ISFREE(svc)) 99130588217SMike Christensen continue; 99230588217SMike Christensen if ((svc->flags & DSSF_ISUSER) != 0 && svc->drvi == instance) { 99330588217SMike Christensen hdl = svc->hdl; 99430588217SMike Christensen mutex_exit(&ds_svcs.lock); 99530588217SMike Christensen (void) ds_unreg_hdl(hdl); 99630588217SMike Christensen mutex_enter(&ds_svcs.lock); 99730588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: ds_unreg_hdl(0x%llx):", 99830588217SMike Christensen __func__, (u_longlong_t)hdl); 99930588217SMike Christensen } 100030588217SMike Christensen } 100130588217SMike Christensen mutex_exit(&ds_svcs.lock); 100230588217SMike Christensen } 100330588217SMike Christensen 100430588217SMike Christensen /* 100530588217SMike Christensen * Special callbacks to allow the lds module revision-independent access 100630588217SMike Christensen * to service structure data in the callback routines. This assumes that 100730588217SMike Christensen * we put a special "cookie" in the arg argument passed to those 100830588217SMike Christensen * routines (for now, a ptr to the svc structure, but it could be a svc 100930588217SMike Christensen * table index or something that we could get back to the svc table entry). 101030588217SMike Christensen */ 101130588217SMike Christensen void 101230588217SMike Christensen ds_cbarg_get_hdl(ds_cb_arg_t arg, ds_svc_hdl_t *hdlp) 101330588217SMike Christensen { 101430588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 101530588217SMike Christensen 101630588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 101730588217SMike Christensen *hdlp = svc->hdl; 101830588217SMike Christensen } 101930588217SMike Christensen 102030588217SMike Christensen void 102130588217SMike Christensen ds_cbarg_get_flags(ds_cb_arg_t arg, uint32_t *flagsp) 102230588217SMike Christensen { 102330588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 102430588217SMike Christensen 102530588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 102630588217SMike Christensen *flagsp = svc->flags; 102730588217SMike Christensen } 102830588217SMike Christensen 102930588217SMike Christensen void 103030588217SMike Christensen ds_cbarg_get_drv_info(ds_cb_arg_t arg, int *drvip) 103130588217SMike Christensen { 103230588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 103330588217SMike Christensen 103430588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 103530588217SMike Christensen *drvip = svc->drvi; 103630588217SMike Christensen } 103730588217SMike Christensen 103830588217SMike Christensen void 103930588217SMike Christensen ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg, void **dpspp) 104030588217SMike Christensen { 104130588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 104230588217SMike Christensen 104330588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 104430588217SMike Christensen *dpspp = svc->drv_psp; 104530588217SMike Christensen } 104630588217SMike Christensen 104730588217SMike Christensen void 104830588217SMike Christensen ds_cbarg_get_domain(ds_cb_arg_t arg, ds_domain_hdl_t *dhdlp) 104930588217SMike Christensen { 105030588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 105130588217SMike Christensen 105230588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 105330588217SMike Christensen if (svc->port == NULL) 105430588217SMike Christensen *dhdlp = ds_my_domain_hdl; 105530588217SMike Christensen else 105630588217SMike Christensen *dhdlp = svc->port->domain_hdl; 105730588217SMike Christensen } 105830588217SMike Christensen 105930588217SMike Christensen void 106030588217SMike Christensen ds_cbarg_get_service_id(ds_cb_arg_t arg, char **servicep) 106130588217SMike Christensen { 106230588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 106330588217SMike Christensen 106430588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 106530588217SMike Christensen *servicep = svc->cap.svc_id; 106630588217SMike Christensen } 106730588217SMike Christensen 106830588217SMike Christensen void 106930588217SMike Christensen ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg, void *dpsp) 107030588217SMike Christensen { 107130588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg; 107230588217SMike Christensen 107330588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 107430588217SMike Christensen svc->drv_psp = dpsp; 107530588217SMike Christensen } 107630588217SMike Christensen 107730588217SMike Christensen void 107830588217SMike Christensen ds_cbarg_set_cookie(ds_svc_t *svc) 107930588217SMike Christensen { 108030588217SMike Christensen svc->ops.cb_arg = (ds_cb_arg_t)(svc); 108130588217SMike Christensen } 108230588217SMike Christensen 108330588217SMike Christensen int 108430588217SMike Christensen ds_hdl_get_cbarg(ds_svc_hdl_t hdl, ds_cb_arg_t *cbargp) 108530588217SMike Christensen { 108630588217SMike Christensen ds_svc_t *svc; 108730588217SMike Christensen 108830588217SMike Christensen mutex_enter(&ds_svcs.lock); 108930588217SMike Christensen if ((svc = ds_get_svc(hdl)) != NULL && 109030588217SMike Christensen (svc->flags & DSSF_ISUSER) != 0) { 109130588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg); 109230588217SMike Christensen *cbargp = svc->ops.cb_arg; 109330588217SMike Christensen mutex_exit(&ds_svcs.lock); 109430588217SMike Christensen return (0); 109530588217SMike Christensen } 109630588217SMike Christensen mutex_exit(&ds_svcs.lock); 109730588217SMike Christensen return (ENXIO); 109830588217SMike Christensen } 109930588217SMike Christensen 110030588217SMike Christensen int 110130588217SMike Christensen ds_is_my_hdl(ds_svc_hdl_t hdl, int instance) 110230588217SMike Christensen { 110330588217SMike Christensen ds_svc_t *svc; 110430588217SMike Christensen int rv = 0; 110530588217SMike Christensen 110630588217SMike Christensen mutex_enter(&ds_svcs.lock); 110730588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) { 110830588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: invalid hdl: 0x%llx\n", __func__, 110930588217SMike Christensen (u_longlong_t)hdl); 111030588217SMike Christensen rv = ENXIO; 111130588217SMike Christensen } else if (instance == DS_INVALID_INSTANCE) { 111230588217SMike Christensen if ((svc->flags & DSSF_ISUSER) != 0) { 111330588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", 111430588217SMike Christensen __func__, (u_longlong_t)hdl); 111530588217SMike Christensen rv = EACCES; 111630588217SMike Christensen } 111730588217SMike Christensen } else if ((svc->flags & DSSF_ISUSER) == 0 || svc->drvi != instance) { 111830588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", __func__, 111930588217SMike Christensen (u_longlong_t)hdl); 112030588217SMike Christensen rv = EACCES; 112130588217SMike Christensen } 112230588217SMike Christensen mutex_exit(&ds_svcs.lock); 112330588217SMike Christensen return (rv); 112430588217SMike Christensen } 1125