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 * Taskq for internal task processing
5930588217SMike Christensen */
6030588217SMike Christensen static taskq_t *ds_taskq;
6130588217SMike Christensen
6230588217SMike Christensen /*
6330588217SMike Christensen * The actual required number of parallel threads is not expected
6430588217SMike Christensen * to be very large. Use the maximum number of CPUs in the system
6530588217SMike Christensen * as a rough upper bound.
6630588217SMike Christensen */
6730588217SMike Christensen #define DS_MAX_TASKQ_THR NCPU
6830588217SMike Christensen #define DS_DISPATCH(fn, arg) taskq_dispatch(ds_taskq, fn, arg, TQ_SLEEP)
6930588217SMike Christensen
70a600f50dSMike Christensen ds_domain_hdl_t ds_my_domain_hdl = DS_DHDL_INVALID;
71a600f50dSMike Christensen char *ds_my_domain_name = NULL;
7230588217SMike Christensen
7330588217SMike Christensen #ifdef DEBUG
7430588217SMike Christensen /*
7530588217SMike Christensen * Debug Flag
7630588217SMike Christensen */
7730588217SMike Christensen uint_t ds_debug = 0;
7830588217SMike Christensen #endif /* DEBUG */
7930588217SMike Christensen
8030588217SMike Christensen /* initialization functions */
8130588217SMike Christensen static void ds_init(void);
8230588217SMike Christensen static void ds_fini(void);
8330588217SMike Christensen static int ds_ports_init(void);
8430588217SMike Christensen static int ds_ports_fini(void);
8530588217SMike Christensen
8630588217SMike Christensen /* port utilities */
8730588217SMike Christensen static int ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan);
8830588217SMike Christensen
8930588217SMike Christensen /* log functions */
9030588217SMike Christensen static void ds_log_init(void);
9130588217SMike Christensen static void ds_log_fini(void);
9230588217SMike Christensen static int ds_log_remove(void);
9330588217SMike Christensen static void ds_log_purge(void *arg);
9430588217SMike Christensen
9530588217SMike Christensen static struct modlmisc modlmisc = {
9630588217SMike Christensen &mod_miscops,
9730588217SMike Christensen "Domain Services 1.9"
9830588217SMike Christensen };
9930588217SMike Christensen
10030588217SMike Christensen static struct modlinkage modlinkage = {
10130588217SMike Christensen MODREV_1,
10230588217SMike Christensen (void *)&modlmisc,
10330588217SMike Christensen NULL
10430588217SMike Christensen };
10530588217SMike Christensen
10630588217SMike Christensen int
_init(void)10730588217SMike Christensen _init(void)
10830588217SMike Christensen {
10930588217SMike Christensen int rv;
11030588217SMike Christensen
11130588217SMike Christensen /*
11230588217SMike Christensen * Perform all internal setup before initializing
11330588217SMike Christensen * the DS ports. This ensures that events can be
11430588217SMike Christensen * processed as soon as the port comes up.
11530588217SMike Christensen */
11630588217SMike Christensen ds_init();
11730588217SMike Christensen
11830588217SMike Christensen /* force attach channel nexus */
11930588217SMike Christensen (void) i_ddi_attach_hw_nodes("cnex");
12030588217SMike Christensen
12130588217SMike Christensen if ((rv = ds_ports_init()) != 0) {
12230588217SMike Christensen cmn_err(CE_WARN, "Domain Services initialization failed");
12330588217SMike Christensen ds_fini();
12430588217SMike Christensen return (rv);
12530588217SMike Christensen }
12630588217SMike Christensen
12730588217SMike Christensen if ((rv = mod_install(&modlinkage)) != 0) {
12830588217SMike Christensen (void) ds_ports_fini();
12930588217SMike Christensen ds_fini();
13030588217SMike Christensen }
13130588217SMike Christensen
13230588217SMike Christensen return (rv);
13330588217SMike Christensen }
13430588217SMike Christensen
13530588217SMike Christensen int
_info(struct modinfo * modinfop)13630588217SMike Christensen _info(struct modinfo *modinfop)
13730588217SMike Christensen {
13830588217SMike Christensen return (mod_info(&modlinkage, modinfop));
13930588217SMike Christensen }
14030588217SMike Christensen
14130588217SMike Christensen int
_fini(void)14230588217SMike Christensen _fini(void)
14330588217SMike Christensen {
14430588217SMike Christensen int rv;
14530588217SMike Christensen
14630588217SMike Christensen if ((rv = mod_remove(&modlinkage)) == 0) {
14730588217SMike Christensen (void) ds_ports_fini();
14830588217SMike Christensen ds_fini();
14930588217SMike Christensen }
15030588217SMike Christensen
15130588217SMike Christensen return (rv);
15230588217SMike Christensen }
15330588217SMike Christensen
15430588217SMike Christensen static void
ds_fini(void)15530588217SMike Christensen ds_fini(void)
15630588217SMike Christensen {
15730588217SMike Christensen /*
15830588217SMike Christensen * Flip the enabled switch to make sure that no
15930588217SMike Christensen * incoming events get dispatched while things
16030588217SMike Christensen * are being torn down.
16130588217SMike Christensen */
16230588217SMike Christensen ds_enabled = B_FALSE;
16330588217SMike Christensen
16430588217SMike Christensen /*
16530588217SMike Christensen * Destroy the taskq.
16630588217SMike Christensen */
16730588217SMike Christensen taskq_destroy(ds_taskq);
16830588217SMike Christensen
16930588217SMike Christensen /*
17030588217SMike Christensen * Destroy the message log.
17130588217SMike Christensen */
17230588217SMike Christensen ds_log_fini();
17330588217SMike Christensen
17430588217SMike Christensen /*
17530588217SMike Christensen * Deallocate the table of registered services
17630588217SMike Christensen */
17730588217SMike Christensen
17830588217SMike Christensen /* clear out all entries */
17930588217SMike Christensen mutex_enter(&ds_svcs.lock);
18030588217SMike Christensen (void) ds_walk_svcs(ds_svc_free, NULL);
18130588217SMike Christensen mutex_exit(&ds_svcs.lock);
18230588217SMike Christensen
18330588217SMike Christensen /* destroy the table itself */
18430588217SMike Christensen DS_FREE(ds_svcs.tbl, ds_svcs.maxsvcs * sizeof (ds_svc_t *));
18530588217SMike Christensen mutex_destroy(&ds_svcs.lock);
18630588217SMike Christensen bzero(&ds_svcs, sizeof (ds_svcs));
18730588217SMike Christensen }
18830588217SMike Christensen
18930588217SMike Christensen /*
19030588217SMike Christensen * Initialize the list of ports based on the MD.
19130588217SMike Christensen */
19230588217SMike Christensen static int
ds_ports_init(void)19330588217SMike Christensen ds_ports_init(void)
19430588217SMike Christensen {
19530588217SMike Christensen int idx;
19630588217SMike Christensen int rv = 0;
19730588217SMike Christensen md_t *mdp;
19830588217SMike Christensen int num_nodes;
19930588217SMike Christensen int listsz;
20030588217SMike Christensen mde_cookie_t rootnode;
20130588217SMike Christensen mde_cookie_t dsnode;
20230588217SMike Christensen mde_cookie_t *portp = NULL;
20330588217SMike Christensen mde_cookie_t *chanp = NULL;
20430588217SMike Christensen int nport;
20530588217SMike Christensen int nchan;
20630588217SMike Christensen
20730588217SMike Christensen if ((mdp = md_get_handle()) == NULL) {
20830588217SMike Christensen cmn_err(CE_WARN, "Unable to initialize machine description");
20930588217SMike Christensen return (-1);
21030588217SMike Christensen }
21130588217SMike Christensen
21230588217SMike Christensen num_nodes = md_node_count(mdp);
21330588217SMike Christensen ASSERT(num_nodes > 0);
21430588217SMike Christensen
21530588217SMike Christensen listsz = num_nodes * sizeof (mde_cookie_t);
21630588217SMike Christensen
21730588217SMike Christensen /* allocate temporary storage for MD scans */
21830588217SMike Christensen portp = kmem_zalloc(listsz, KM_SLEEP);
21930588217SMike Christensen chanp = kmem_zalloc(listsz, KM_SLEEP);
22030588217SMike Christensen
22130588217SMike Christensen rootnode = md_root_node(mdp);
22230588217SMike Christensen ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
22330588217SMike Christensen
22430588217SMike Christensen /*
22530588217SMike Christensen * The root of the search for DS port nodes is the
22630588217SMike Christensen * DS node. Perform a scan to find that node.
22730588217SMike Christensen */
22830588217SMike Christensen nport = md_scan_dag(mdp, rootnode, md_find_name(mdp, DS_MD_ROOT_NAME),
22930588217SMike Christensen md_find_name(mdp, "fwd"), portp);
23030588217SMike Christensen
23130588217SMike Christensen if (nport <= 0) {
23230588217SMike Christensen DS_DBG_MD(CE_NOTE, "No '%s' node in MD", DS_MD_ROOT_NAME);
23330588217SMike Christensen goto done;
23430588217SMike Christensen }
23530588217SMike Christensen
23630588217SMike Christensen /* expecting only one DS node */
23730588217SMike Christensen if (nport != 1) {
23830588217SMike Christensen DS_DBG_MD(CE_NOTE, "Expected one '%s' node in the MD, found %d",
23930588217SMike Christensen DS_MD_ROOT_NAME, nport);
24030588217SMike Christensen }
24130588217SMike Christensen
24230588217SMike Christensen dsnode = portp[0];
24330588217SMike Christensen
24430588217SMike Christensen /* find all the DS ports in the MD */
24530588217SMike Christensen nport = md_scan_dag(mdp, dsnode, md_find_name(mdp, DS_MD_PORT_NAME),
24630588217SMike Christensen md_find_name(mdp, "fwd"), portp);
24730588217SMike Christensen
24830588217SMike Christensen if (nport <= 0) {
24930588217SMike Christensen DS_DBG_MD(CE_NOTE, "No '%s' nodes in MD", DS_MD_PORT_NAME);
25030588217SMike Christensen goto done;
25130588217SMike Christensen }
25230588217SMike Christensen
25330588217SMike Christensen /*
25430588217SMike Christensen * Initialize all the ports found in the MD.
25530588217SMike Christensen */
25630588217SMike Christensen for (idx = 0; idx < nport; idx++) {
25730588217SMike Christensen
25830588217SMike Christensen /* get the channels for this port */
25930588217SMike Christensen nchan = md_scan_dag(mdp, portp[idx],
26030588217SMike Christensen md_find_name(mdp, DS_MD_CHAN_NAME),
26130588217SMike Christensen md_find_name(mdp, "fwd"), chanp);
26230588217SMike Christensen
26330588217SMike Christensen if (nchan <= 0) {
26430588217SMike Christensen cmn_err(CE_WARN, "No '%s' node for DS port",
26530588217SMike Christensen DS_MD_CHAN_NAME);
26630588217SMike Christensen rv = -1;
26730588217SMike Christensen goto done;
26830588217SMike Christensen }
26930588217SMike Christensen
27030588217SMike Christensen /* expecting only one channel */
27130588217SMike Christensen if (nchan != 1) {
27230588217SMike Christensen DS_DBG_MD(CE_NOTE, "Expected one '%s' node for DS "
27330588217SMike Christensen " port, found %d", DS_MD_CHAN_NAME, nchan);
27430588217SMike Christensen }
27530588217SMike Christensen
27630588217SMike Christensen if (ds_port_add(mdp, portp[idx], chanp[0]) != 0) {
27730588217SMike Christensen rv = -1;
27830588217SMike Christensen goto done;
27930588217SMike Christensen }
28030588217SMike Christensen }
28130588217SMike Christensen
28230588217SMike Christensen done:
28330588217SMike Christensen if (rv != 0)
28430588217SMike Christensen (void) ds_ports_fini();
28530588217SMike Christensen
28630588217SMike Christensen DS_FREE(portp, listsz);
28730588217SMike Christensen DS_FREE(chanp, listsz);
28830588217SMike Christensen
28930588217SMike Christensen (void) md_fini_handle(mdp);
29030588217SMike Christensen
29130588217SMike Christensen return (rv);
29230588217SMike Christensen }
29330588217SMike Christensen
29430588217SMike Christensen static int
ds_ports_fini(void)29530588217SMike Christensen ds_ports_fini(void)
29630588217SMike Christensen {
29730588217SMike Christensen int idx;
29830588217SMike Christensen
29930588217SMike Christensen /*
30030588217SMike Christensen * Tear down each initialized port.
30130588217SMike Christensen */
30230588217SMike Christensen for (idx = 0; idx < DS_MAX_PORTS; idx++) {
30330588217SMike Christensen if (DS_PORT_IN_SET(ds_allports, idx)) {
30430588217SMike Christensen (void) ds_remove_port(idx, 1);
30530588217SMike Christensen }
30630588217SMike Christensen }
30730588217SMike Christensen
30830588217SMike Christensen return (0);
30930588217SMike Christensen }
31030588217SMike Christensen
31130588217SMike Christensen static int
ds_port_add(md_t * mdp,mde_cookie_t port,mde_cookie_t chan)31230588217SMike Christensen ds_port_add(md_t *mdp, mde_cookie_t port, mde_cookie_t chan)
31330588217SMike Christensen {
31430588217SMike Christensen uint64_t port_id;
31530588217SMike Christensen uint64_t ldc_id;
31640c61268SMike Christensen uint8_t *ldcidsp;
31740c61268SMike Christensen int len;
31830588217SMike Christensen
31930588217SMike Christensen /* get the ID for this port */
32030588217SMike Christensen if (md_get_prop_val(mdp, port, "id", &port_id) != 0) {
32130588217SMike Christensen cmn_err(CE_WARN, "%s: port 'id' property not found",
32230588217SMike Christensen __func__);
32330588217SMike Christensen return (-1);
32430588217SMike Christensen }
32530588217SMike Christensen
32630588217SMike Christensen /* sanity check the port id */
32730588217SMike Christensen if (port_id > DS_MAX_PORT_ID) {
32830588217SMike Christensen cmn_err(CE_WARN, "%s: port ID %ld out of range",
32930588217SMike Christensen __func__, port_id);
33030588217SMike Christensen return (-1);
33130588217SMike Christensen }
33230588217SMike Christensen
33330588217SMike Christensen /* get the channel ID for this port */
33430588217SMike Christensen if (md_get_prop_val(mdp, chan, "id", &ldc_id) != 0) {
33530588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: no channel 'id' property",
33630588217SMike Christensen port_id, __func__);
33730588217SMike Christensen return (-1);
33830588217SMike Christensen }
33930588217SMike Christensen
340a600f50dSMike Christensen if (ds_add_port(port_id, ldc_id, DS_DHDL_INVALID, NULL, 1) != 0)
34130588217SMike Christensen return (-1);
34230588217SMike Christensen
34340c61268SMike Christensen /*
34440c61268SMike Christensen * Identify the SP Port. The SP port is the only one with
34540c61268SMike Christensen * the "ldc-ids" property, and is only on the primary domain.
34640c61268SMike Christensen */
34740c61268SMike Christensen if (ds_sp_port_id == DS_PORTID_INVALID &&
34840c61268SMike Christensen md_get_prop_data(mdp, port, "ldc-ids", &ldcidsp, &len) == 0) {
34940c61268SMike Christensen ds_sp_port_id = port_id;
35040c61268SMike Christensen }
35140c61268SMike Christensen
35230588217SMike Christensen return (0);
35330588217SMike Christensen }
35430588217SMike Christensen
355a600f50dSMike Christensen void
ds_set_my_dom_hdl_name(ds_domain_hdl_t dhdl,char * name)356a600f50dSMike Christensen ds_set_my_dom_hdl_name(ds_domain_hdl_t dhdl, char *name)
357a600f50dSMike Christensen {
358a600f50dSMike Christensen ds_my_domain_hdl = dhdl;
359a600f50dSMike Christensen if (ds_my_domain_name != NULL) {
360a600f50dSMike Christensen DS_FREE(ds_my_domain_name, strlen(ds_my_domain_name)+1);
361a600f50dSMike Christensen ds_my_domain_name = NULL;
362a600f50dSMike Christensen }
363a600f50dSMike Christensen if (name != NULL) {
364a600f50dSMike Christensen ds_my_domain_name = ds_strdup(name);
365a600f50dSMike Christensen }
366a600f50dSMike Christensen }
367a600f50dSMike Christensen
36830588217SMike Christensen void
ds_init()36930588217SMike Christensen ds_init()
37030588217SMike Christensen {
37130588217SMike Christensen ds_common_init();
37230588217SMike Christensen
37330588217SMike Christensen /*
37430588217SMike Christensen * Create taskq for internal processing threads. This
37530588217SMike Christensen * includes processing incoming request messages and
37630588217SMike Christensen * sending out of band registration messages.
37730588217SMike Christensen */
37830588217SMike Christensen ds_taskq = taskq_create("ds_taskq", 1, minclsyspri, 1,
37930588217SMike Christensen DS_MAX_TASKQ_THR, TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
38030588217SMike Christensen
38130588217SMike Christensen /*
38230588217SMike Christensen * Initialize the message log.
38330588217SMike Christensen */
38430588217SMike Christensen ds_log_init();
38530588217SMike Christensen }
38630588217SMike Christensen
38730588217SMike Christensen int
ds_sys_dispatch_func(void (func)(void *),void * arg)38830588217SMike Christensen ds_sys_dispatch_func(void (func)(void *), void *arg)
38930588217SMike Christensen {
390fc8ae2ecSToomas Soome return (DS_DISPATCH(func, arg) == TASKQID_INVALID);
39130588217SMike Christensen }
39230588217SMike Christensen
39330588217SMike Christensen /*
39430588217SMike Christensen * Drain event queue, if necessary.
39530588217SMike Christensen */
39630588217SMike Christensen void
ds_sys_drain_events(ds_port_t * port)39730588217SMike Christensen ds_sys_drain_events(ds_port_t *port)
39830588217SMike Christensen {
39930588217SMike Christensen _NOTE(ARGUNUSED(port))
40030588217SMike Christensen }
40130588217SMike Christensen
40230588217SMike Christensen /*
40330588217SMike Christensen * System specific port initalization.
40430588217SMike Christensen */
40530588217SMike Christensen void
ds_sys_port_init(ds_port_t * port)40630588217SMike Christensen ds_sys_port_init(ds_port_t *port)
40730588217SMike Christensen {
40830588217SMike Christensen _NOTE(ARGUNUSED(port))
40930588217SMike Christensen }
41030588217SMike Christensen
41130588217SMike Christensen /*
41230588217SMike Christensen * System specific port teardown.
41330588217SMike Christensen */
41430588217SMike Christensen void
ds_sys_port_fini(ds_port_t * port)41530588217SMike Christensen ds_sys_port_fini(ds_port_t *port)
41630588217SMike Christensen {
41730588217SMike Christensen _NOTE(ARGUNUSED(port))
41830588217SMike Christensen }
41930588217SMike Christensen
42030588217SMike Christensen /*
42130588217SMike Christensen * System specific LDC channel initialization.
42230588217SMike Christensen */
42330588217SMike Christensen void
ds_sys_ldc_init(ds_port_t * port)42430588217SMike Christensen ds_sys_ldc_init(ds_port_t *port)
42530588217SMike Christensen {
42630588217SMike Christensen int rv;
42730588217SMike Christensen char ebuf[DS_EBUFSIZE];
42830588217SMike Christensen
42930588217SMike Christensen ASSERT(MUTEX_HELD(&port->lock));
43030588217SMike Christensen
43130588217SMike Christensen if ((rv = ldc_open(port->ldc.hdl)) != 0) {
43230588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_open: %s",
43330588217SMike Christensen PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
43430588217SMike Christensen return;
43530588217SMike Christensen }
43630588217SMike Christensen
43730588217SMike Christensen (void) ldc_up(port->ldc.hdl);
43830588217SMike Christensen
43930588217SMike Christensen (void) ldc_status(port->ldc.hdl, &port->ldc.state);
44030588217SMike Christensen
44130588217SMike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: initial LDC state 0x%x",
44230588217SMike Christensen PORTID(port), __func__, port->ldc.state);
44330588217SMike Christensen
44430588217SMike Christensen port->state = DS_PORT_LDC_INIT;
44530588217SMike Christensen }
44630588217SMike Christensen
44730588217SMike Christensen /*
44830588217SMike Christensen * DS message log
44930588217SMike Christensen *
45030588217SMike Christensen * Locking: The message log is protected by a single mutex. This
45130588217SMike Christensen * protects all fields in the log structure itself as well as
45230588217SMike Christensen * everything in the entry structures on both the log and the
45330588217SMike Christensen * free list.
45430588217SMike Christensen */
45530588217SMike Christensen static struct log {
45630588217SMike Christensen ds_log_entry_t *head; /* head of the log */
45730588217SMike Christensen ds_log_entry_t *freelist; /* head of the free list */
45830588217SMike Christensen size_t size; /* size of the log in bytes */
45930588217SMike Christensen uint32_t nentry; /* number of entries */
46030588217SMike Christensen kmutex_t lock; /* log lock */
46130588217SMike Christensen } ds_log;
46230588217SMike Christensen
46330588217SMike Christensen /* log soft limit */
46430588217SMike Christensen uint_t ds_log_sz = DS_LOG_DEFAULT_SZ;
46530588217SMike Christensen
46630588217SMike Christensen /* initial pool of log entry structures */
46730588217SMike Christensen static ds_log_entry_t ds_log_entry_pool[DS_LOG_NPOOL];
46830588217SMike Christensen
46930588217SMike Christensen /*
47030588217SMike Christensen * Logging Support
47130588217SMike Christensen */
47230588217SMike Christensen static void
ds_log_init(void)47330588217SMike Christensen ds_log_init(void)
47430588217SMike Christensen {
47530588217SMike Christensen /* initialize global lock */
47630588217SMike Christensen mutex_init(&ds_log.lock, NULL, MUTEX_DRIVER, NULL);
47730588217SMike Christensen
47830588217SMike Christensen mutex_enter(&ds_log.lock);
47930588217SMike Christensen
48030588217SMike Christensen /* initialize the log */
48130588217SMike Christensen ds_log.head = NULL;
48230588217SMike Christensen ds_log.size = 0;
48330588217SMike Christensen ds_log.nentry = 0;
48430588217SMike Christensen
48530588217SMike Christensen /* initialize the free list */
486*cb453c7aSToomas Soome for (int i = 0; i < DS_LOG_NPOOL; i++) {
487*cb453c7aSToomas Soome ds_log_entry_pool[i].next = ds_log.freelist;
488*cb453c7aSToomas Soome ds_log.freelist = &ds_log_entry_pool[i];
48930588217SMike Christensen }
49030588217SMike Christensen
49130588217SMike Christensen mutex_exit(&ds_log.lock);
49230588217SMike Christensen
49330588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log initialized: size=%d bytes, "
49430588217SMike Christensen " limit=%d bytes, ninit=%ld", ds_log_sz, DS_LOG_LIMIT,
49530588217SMike Christensen DS_LOG_NPOOL);
49630588217SMike Christensen }
49730588217SMike Christensen
49830588217SMike Christensen static void
ds_log_fini(void)49930588217SMike Christensen ds_log_fini(void)
50030588217SMike Christensen {
50130588217SMike Christensen ds_log_entry_t *next;
50230588217SMike Christensen
50330588217SMike Christensen mutex_enter(&ds_log.lock);
50430588217SMike Christensen
50530588217SMike Christensen /* clear out the log */
50630588217SMike Christensen while (ds_log.nentry > 0)
50730588217SMike Christensen (void) ds_log_remove();
50830588217SMike Christensen
50930588217SMike Christensen /*
51030588217SMike Christensen * Now all the entries are on the free list.
51130588217SMike Christensen * Clear out the free list, deallocating any
51230588217SMike Christensen * entry that was dynamically allocated.
51330588217SMike Christensen */
51430588217SMike Christensen while (ds_log.freelist != NULL) {
51530588217SMike Christensen next = ds_log.freelist->next;
51630588217SMike Christensen
51730588217SMike Christensen if (!DS_IS_POOL_ENTRY(ds_log.freelist)) {
51830588217SMike Christensen kmem_free(ds_log.freelist, sizeof (ds_log_entry_t));
51930588217SMike Christensen }
52030588217SMike Christensen
52130588217SMike Christensen ds_log.freelist = next;
52230588217SMike Christensen }
52330588217SMike Christensen
52430588217SMike Christensen mutex_exit(&ds_log.lock);
52530588217SMike Christensen
52630588217SMike Christensen mutex_destroy(&ds_log.lock);
52730588217SMike Christensen }
52830588217SMike Christensen
52930588217SMike Christensen static ds_log_entry_t *
ds_log_entry_alloc(void)53030588217SMike Christensen ds_log_entry_alloc(void)
53130588217SMike Christensen {
53230588217SMike Christensen ds_log_entry_t *new = NULL;
53330588217SMike Christensen
53430588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock));
53530588217SMike Christensen
53630588217SMike Christensen if (ds_log.freelist != NULL) {
53730588217SMike Christensen new = ds_log.freelist;
53830588217SMike Christensen ds_log.freelist = ds_log.freelist->next;
53930588217SMike Christensen }
54030588217SMike Christensen
54130588217SMike Christensen if (new == NULL) {
54230588217SMike Christensen /* free list was empty */
54330588217SMike Christensen new = kmem_zalloc(sizeof (ds_log_entry_t), KM_SLEEP);
54430588217SMike Christensen }
54530588217SMike Christensen
54630588217SMike Christensen ASSERT(new);
54730588217SMike Christensen
54830588217SMike Christensen return (new);
54930588217SMike Christensen }
55030588217SMike Christensen
55130588217SMike Christensen static void
ds_log_entry_free(ds_log_entry_t * entry)55230588217SMike Christensen ds_log_entry_free(ds_log_entry_t *entry)
55330588217SMike Christensen {
55430588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock));
55530588217SMike Christensen
55630588217SMike Christensen if (entry == NULL)
55730588217SMike Christensen return;
55830588217SMike Christensen
55930588217SMike Christensen if (entry->data != NULL) {
56030588217SMike Christensen kmem_free(entry->data, entry->datasz);
56130588217SMike Christensen entry->data = NULL;
56230588217SMike Christensen }
56330588217SMike Christensen
56430588217SMike Christensen /* place entry on the free list */
56530588217SMike Christensen entry->next = ds_log.freelist;
56630588217SMike Christensen ds_log.freelist = entry;
56730588217SMike Christensen }
56830588217SMike Christensen
56930588217SMike Christensen /*
57030588217SMike Christensen * Add a message to the end of the log
57130588217SMike Christensen */
57230588217SMike Christensen static int
ds_log_add(ds_log_entry_t * new)57330588217SMike Christensen ds_log_add(ds_log_entry_t *new)
57430588217SMike Christensen {
57530588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock));
57630588217SMike Christensen
57730588217SMike Christensen if (ds_log.head == NULL) {
57830588217SMike Christensen
57930588217SMike Christensen new->prev = new;
58030588217SMike Christensen new->next = new;
58130588217SMike Christensen
58230588217SMike Christensen ds_log.head = new;
58330588217SMike Christensen } else {
58430588217SMike Christensen ds_log_entry_t *head = ds_log.head;
58530588217SMike Christensen ds_log_entry_t *tail = ds_log.head->prev;
58630588217SMike Christensen
58730588217SMike Christensen new->next = head;
58830588217SMike Christensen new->prev = tail;
58930588217SMike Christensen tail->next = new;
59030588217SMike Christensen head->prev = new;
59130588217SMike Christensen }
59230588217SMike Christensen
59330588217SMike Christensen /* increase the log size, including the metadata size */
59430588217SMike Christensen ds_log.size += DS_LOG_ENTRY_SZ(new);
59530588217SMike Christensen ds_log.nentry++;
59630588217SMike Christensen
59730588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: added %ld data bytes, %ld total bytes",
59830588217SMike Christensen new->datasz, DS_LOG_ENTRY_SZ(new));
59930588217SMike Christensen
60030588217SMike Christensen return (0);
60130588217SMike Christensen }
60230588217SMike Christensen
60330588217SMike Christensen /*
60430588217SMike Christensen * Remove an entry from the head of the log
60530588217SMike Christensen */
60630588217SMike Christensen static int
ds_log_remove(void)60730588217SMike Christensen ds_log_remove(void)
60830588217SMike Christensen {
60930588217SMike Christensen ds_log_entry_t *head;
61030588217SMike Christensen
61130588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock));
61230588217SMike Christensen
61330588217SMike Christensen head = ds_log.head;
61430588217SMike Christensen
61530588217SMike Christensen /* empty list */
61630588217SMike Christensen if (head == NULL)
61730588217SMike Christensen return (0);
61830588217SMike Christensen
61930588217SMike Christensen if (head->next == ds_log.head) {
62030588217SMike Christensen /* one element list */
62130588217SMike Christensen ds_log.head = NULL;
62230588217SMike Christensen } else {
62330588217SMike Christensen head->next->prev = head->prev;
62430588217SMike Christensen head->prev->next = head->next;
62530588217SMike Christensen ds_log.head = head->next;
62630588217SMike Christensen }
62730588217SMike Christensen
62830588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: removed %ld data bytes, %ld total bytes",
62930588217SMike Christensen head->datasz, DS_LOG_ENTRY_SZ(head));
63030588217SMike Christensen
63130588217SMike Christensen ds_log.size -= DS_LOG_ENTRY_SZ(head);
63230588217SMike Christensen ds_log.nentry--;
63330588217SMike Christensen
63430588217SMike Christensen ds_log_entry_free(head);
63530588217SMike Christensen
63630588217SMike Christensen return (0);
63730588217SMike Christensen }
63830588217SMike Christensen
63930588217SMike Christensen /*
64030588217SMike Christensen * Replace the data in the entry at the front of the list with then
64130588217SMike Christensen * new data. This has the effect of removing the oldest entry and
64230588217SMike Christensen * adding the new entry.
64330588217SMike Christensen */
64430588217SMike Christensen static int
ds_log_replace(int32_t dest,uint8_t * msg,size_t sz)64530588217SMike Christensen ds_log_replace(int32_t dest, uint8_t *msg, size_t sz)
64630588217SMike Christensen {
64730588217SMike Christensen ds_log_entry_t *head;
64830588217SMike Christensen
64930588217SMike Christensen ASSERT(MUTEX_HELD(&ds_log.lock));
65030588217SMike Christensen
65130588217SMike Christensen head = ds_log.head;
65230588217SMike Christensen
65330588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: replaced %ld data bytes (%ld total) with "
65430588217SMike Christensen " %ld data bytes (%ld total)", head->datasz,
65530588217SMike Christensen DS_LOG_ENTRY_SZ(head), sz, sz + sizeof (ds_log_entry_t));
65630588217SMike Christensen
65730588217SMike Christensen ds_log.size -= DS_LOG_ENTRY_SZ(head);
65830588217SMike Christensen
65930588217SMike Christensen kmem_free(head->data, head->datasz);
66030588217SMike Christensen
66130588217SMike Christensen head->data = msg;
66230588217SMike Christensen head->datasz = sz;
66330588217SMike Christensen head->timestamp = ddi_get_time();
66430588217SMike Christensen head->dest = dest;
66530588217SMike Christensen
66630588217SMike Christensen ds_log.size += DS_LOG_ENTRY_SZ(head);
66730588217SMike Christensen
66830588217SMike Christensen ds_log.head = head->next;
66930588217SMike Christensen
67030588217SMike Christensen return (0);
67130588217SMike Christensen }
67230588217SMike Christensen
67330588217SMike Christensen static void
ds_log_purge(void * arg)67430588217SMike Christensen ds_log_purge(void *arg)
67530588217SMike Christensen {
67630588217SMike Christensen _NOTE(ARGUNUSED(arg))
67730588217SMike Christensen
67830588217SMike Christensen mutex_enter(&ds_log.lock);
67930588217SMike Christensen
68030588217SMike Christensen DS_DBG_LOG(CE_NOTE, "ds_log: purging oldest log entries");
68130588217SMike Christensen
68230588217SMike Christensen while ((ds_log.nentry) && (ds_log.size >= ds_log_sz)) {
68330588217SMike Christensen (void) ds_log_remove();
68430588217SMike Christensen }
68530588217SMike Christensen
68630588217SMike Christensen mutex_exit(&ds_log.lock);
68730588217SMike Christensen }
68830588217SMike Christensen
68930588217SMike Christensen int
ds_log_add_msg(int32_t dest,uint8_t * msg,size_t sz)69030588217SMike Christensen ds_log_add_msg(int32_t dest, uint8_t *msg, size_t sz)
69130588217SMike Christensen {
69230588217SMike Christensen int rv = 0;
69330588217SMike Christensen void *data;
69430588217SMike Christensen
69530588217SMike Christensen mutex_enter(&ds_log.lock);
69630588217SMike Christensen
69730588217SMike Christensen /* allocate a local copy of the data */
69830588217SMike Christensen data = kmem_alloc(sz, KM_SLEEP);
69930588217SMike Christensen bcopy(msg, data, sz);
70030588217SMike Christensen
70130588217SMike Christensen /* check if the log is larger than the soft limit */
70230588217SMike Christensen if ((ds_log.nentry) && ((ds_log.size + sz) >= ds_log_sz)) {
70330588217SMike Christensen /*
70430588217SMike Christensen * The log is larger than the soft limit.
70530588217SMike Christensen * Swap the oldest entry for the newest.
70630588217SMike Christensen */
70730588217SMike Christensen DS_DBG_LOG(CE_NOTE, "%s: replacing oldest entry with new entry",
70830588217SMike Christensen __func__);
70930588217SMike Christensen (void) ds_log_replace(dest, data, sz);
71030588217SMike Christensen } else {
71130588217SMike Christensen /*
71230588217SMike Christensen * Still have headroom under the soft limit.
71330588217SMike Christensen * Add the new entry to the log.
71430588217SMike Christensen */
71530588217SMike Christensen ds_log_entry_t *new;
71630588217SMike Christensen
71730588217SMike Christensen new = ds_log_entry_alloc();
71830588217SMike Christensen
71930588217SMike Christensen /* fill in message data */
72030588217SMike Christensen new->data = data;
72130588217SMike Christensen new->datasz = sz;
72230588217SMike Christensen new->timestamp = ddi_get_time();
72330588217SMike Christensen new->dest = dest;
72430588217SMike Christensen
72530588217SMike Christensen rv = ds_log_add(new);
72630588217SMike Christensen }
72730588217SMike Christensen
72830588217SMike Christensen /* check if the log is larger than the hard limit */
72930588217SMike Christensen if ((ds_log.nentry > 1) && (ds_log.size >= DS_LOG_LIMIT)) {
73030588217SMike Christensen /*
73130588217SMike Christensen * Wakeup the thread to remove entries
73230588217SMike Christensen * from the log until it is smaller than
73330588217SMike Christensen * the soft limit.
73430588217SMike Christensen */
73530588217SMike Christensen DS_DBG_LOG(CE_NOTE, "%s: log exceeded %d bytes, scheduling"
73630588217SMike Christensen " a purge...", __func__, DS_LOG_LIMIT);
73730588217SMike Christensen
738fc8ae2ecSToomas Soome if (DS_DISPATCH(ds_log_purge, NULL) == TASKQID_INVALID) {
73930588217SMike Christensen cmn_err(CE_NOTE, "%s: purge thread failed to start",
74030588217SMike Christensen __func__);
74130588217SMike Christensen }
74230588217SMike Christensen }
74330588217SMike Christensen
74430588217SMike Christensen mutex_exit(&ds_log.lock);
74530588217SMike Christensen
74630588217SMike Christensen return (rv);
74730588217SMike Christensen }
74830588217SMike Christensen
74930588217SMike Christensen int
ds_add_port(uint64_t port_id,uint64_t ldc_id,ds_domain_hdl_t dhdl,char * dom_name,int verbose)75030588217SMike Christensen ds_add_port(uint64_t port_id, uint64_t ldc_id, ds_domain_hdl_t dhdl,
75130588217SMike Christensen char *dom_name, int verbose)
75230588217SMike Christensen {
75330588217SMike Christensen ds_port_t *newport;
75430588217SMike Christensen
75530588217SMike Christensen /* sanity check the port id */
75630588217SMike Christensen if (port_id > DS_MAX_PORT_ID) {
75730588217SMike Christensen cmn_err(CE_WARN, "%s: port ID %ld out of range",
75830588217SMike Christensen __func__, port_id);
75930588217SMike Christensen return (EINVAL);
76030588217SMike Christensen }
76130588217SMike Christensen
762a600f50dSMike Christensen DS_DBG_MD(CE_NOTE, "%s: adding port ds@%ld, LDC: 0x%lx, dhdl: 0x%lx "
763a600f50dSMike Christensen "name: '%s'", __func__, port_id, ldc_id, dhdl,
764a600f50dSMike Christensen dom_name == NULL ? "NULL" : dom_name);
76530588217SMike Christensen
76630588217SMike Christensen /* get the port structure from the array of ports */
76730588217SMike Christensen newport = &ds_ports[port_id];
76830588217SMike Christensen
76930588217SMike Christensen /* check for a duplicate port in the MD */
77030588217SMike Christensen if (newport->state != DS_PORT_FREE) {
77130588217SMike Christensen if (verbose) {
77230588217SMike Christensen cmn_err(CE_WARN, "ds@%lx: %s: port already exists",
77330588217SMike Christensen port_id, __func__);
77430588217SMike Christensen }
77530588217SMike Christensen if (newport->domain_hdl == DS_DHDL_INVALID) {
77630588217SMike Christensen newport->domain_hdl = dhdl;
77730588217SMike Christensen }
77830588217SMike Christensen if (newport->domain_name == NULL && dom_name != NULL) {
77930588217SMike Christensen newport->domain_name = ds_strdup(dom_name);
78030588217SMike Christensen }
78130588217SMike Christensen return (EBUSY);
78230588217SMike Christensen }
78330588217SMike Christensen
78430588217SMike Christensen /* initialize the port */
78530588217SMike Christensen newport->id = port_id;
78630588217SMike Christensen newport->ldc.id = ldc_id;
78730588217SMike Christensen newport->domain_hdl = dhdl;
78830588217SMike Christensen if (dom_name) {
78930588217SMike Christensen newport->domain_name = ds_strdup(dom_name);
79030588217SMike Christensen } else
79130588217SMike Christensen newport->domain_name = NULL;
79230588217SMike Christensen ds_port_common_init(newport);
79330588217SMike Christensen
79430588217SMike Christensen return (0);
79530588217SMike Christensen }
79630588217SMike Christensen
797beba1dd8SMike Christensen /* ARGSUSED */
79830588217SMike Christensen int
ds_remove_port(uint64_t port_id,int is_fini)79930588217SMike Christensen ds_remove_port(uint64_t port_id, int is_fini)
80030588217SMike Christensen {
80130588217SMike Christensen ds_port_t *port;
80230588217SMike Christensen
80330588217SMike Christensen if (port_id >= DS_MAX_PORTS || !DS_PORT_IN_SET(ds_allports, port_id)) {
80430588217SMike Christensen DS_DBG_MD(CE_NOTE, "%s: invalid port %lx", __func__,
80530588217SMike Christensen port_id);
80630588217SMike Christensen return (EINVAL);
80730588217SMike Christensen }
80830588217SMike Christensen
80930588217SMike Christensen DS_DBG_MD(CE_NOTE, "%s: removing port ds@%lx", __func__, port_id);
81030588217SMike Christensen
81130588217SMike Christensen port = &ds_ports[port_id];
81230588217SMike Christensen
81330588217SMike Christensen mutex_enter(&port->lock);
81430588217SMike Christensen
81530588217SMike Christensen if (port->state >= DS_PORT_LDC_INIT) {
81630588217SMike Christensen /* shut down the LDC for this port */
81730588217SMike Christensen (void) ds_ldc_fini(port);
81830588217SMike Christensen }
81930588217SMike Christensen
82030588217SMike Christensen if (port->domain_name) {
82130588217SMike Christensen DS_FREE(port->domain_name, strlen(port->domain_name) + 1);
82230588217SMike Christensen port->domain_name = NULL;
82330588217SMike Christensen }
82430588217SMike Christensen port->domain_hdl = DS_DHDL_INVALID;
82530588217SMike Christensen
82630588217SMike Christensen /* clean up the port structure */
827beba1dd8SMike Christensen ds_port_common_fini(port);
828beba1dd8SMike Christensen
829beba1dd8SMike Christensen mutex_exit(&port->lock);
83030588217SMike Christensen return (0);
83130588217SMike Christensen }
83230588217SMike Christensen
83330588217SMike Christensen /*
83430588217SMike Christensen * Interface for ds_service_lookup in lds driver.
83530588217SMike Christensen */
83630588217SMike Christensen int
ds_service_lookup(ds_svc_hdl_t hdl,char ** servicep,uint_t * is_client)83730588217SMike Christensen ds_service_lookup(ds_svc_hdl_t hdl, char **servicep, uint_t *is_client)
83830588217SMike Christensen {
83930588217SMike Christensen ds_svc_t *svc;
84030588217SMike Christensen
84130588217SMike Christensen mutex_enter(&ds_svcs.lock);
84230588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
84330588217SMike Christensen mutex_exit(&ds_svcs.lock);
84430588217SMike Christensen DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__,
84530588217SMike Christensen (u_longlong_t)hdl);
84630588217SMike Christensen return (ENXIO);
84730588217SMike Christensen }
84830588217SMike Christensen *servicep = svc->cap.svc_id;
84930588217SMike Christensen *is_client = svc->flags & DSSF_ISCLIENT;
85030588217SMike Christensen mutex_exit(&ds_svcs.lock);
85130588217SMike Christensen return (0);
85230588217SMike Christensen }
85330588217SMike Christensen
85430588217SMike Christensen /*
85530588217SMike Christensen * Interface for ds_domain_lookup in lds driver.
85630588217SMike Christensen */
85730588217SMike Christensen int
ds_domain_lookup(ds_svc_hdl_t hdl,ds_domain_hdl_t * dhdlp)85830588217SMike Christensen ds_domain_lookup(ds_svc_hdl_t hdl, ds_domain_hdl_t *dhdlp)
85930588217SMike Christensen {
86030588217SMike Christensen ds_svc_t *svc;
86130588217SMike Christensen
86230588217SMike Christensen mutex_enter(&ds_svcs.lock);
86330588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
86430588217SMike Christensen mutex_exit(&ds_svcs.lock);
86530588217SMike Christensen DS_DBG(CE_NOTE, "%s: handle 0x%llx not found", __func__,
86630588217SMike Christensen (u_longlong_t)hdl);
86730588217SMike Christensen return (ENXIO);
86830588217SMike Christensen }
86930588217SMike Christensen if (svc->port == NULL)
87030588217SMike Christensen *dhdlp = ds_my_domain_hdl;
87130588217SMike Christensen else
87230588217SMike Christensen *dhdlp = svc->port->domain_hdl;
87330588217SMike Christensen mutex_exit(&ds_svcs.lock);
87430588217SMike Christensen return (0);
87530588217SMike Christensen }
87630588217SMike Christensen
87730588217SMike Christensen /*
87830588217SMike Christensen * Interface for ds_hdl_isready in lds driver.
87930588217SMike Christensen */
88030588217SMike Christensen int
ds_hdl_isready(ds_svc_hdl_t hdl,uint_t * is_ready)88130588217SMike Christensen ds_hdl_isready(ds_svc_hdl_t hdl, uint_t *is_ready)
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 *is_ready = (svc->state == DS_SVC_ACTIVE);
89330588217SMike Christensen mutex_exit(&ds_svcs.lock);
89430588217SMike Christensen return (0);
89530588217SMike Christensen }
89630588217SMike Christensen
89730588217SMike Christensen /*
89830588217SMike Christensen * Interface for ds_dom_name_to_hdl in lds driver.
89930588217SMike Christensen */
90030588217SMike Christensen int
ds_dom_name_to_hdl(char * domain_name,ds_domain_hdl_t * dhdlp)90130588217SMike Christensen ds_dom_name_to_hdl(char *domain_name, ds_domain_hdl_t *dhdlp)
90230588217SMike Christensen {
90330588217SMike Christensen int i;
90430588217SMike Christensen ds_port_t *port;
90530588217SMike Christensen
906a600f50dSMike Christensen if (domain_name == NULL) {
907a600f50dSMike Christensen return (ENXIO);
908a600f50dSMike Christensen }
909a600f50dSMike Christensen if (ds_my_domain_name != NULL &&
910a600f50dSMike Christensen strcmp(ds_my_domain_name, domain_name) == 0) {
911a600f50dSMike Christensen *dhdlp = ds_my_domain_hdl;
912a600f50dSMike Christensen return (0);
913a600f50dSMike Christensen }
91430588217SMike Christensen for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) {
91530588217SMike Christensen if (port->state != DS_PORT_FREE &&
91630588217SMike Christensen port->domain_name != NULL &&
91730588217SMike Christensen strcmp(port->domain_name, domain_name) == 0) {
91830588217SMike Christensen *dhdlp = port->domain_hdl;
91930588217SMike Christensen return (0);
92030588217SMike Christensen }
92130588217SMike Christensen }
92230588217SMike Christensen return (ENXIO);
92330588217SMike Christensen }
92430588217SMike Christensen
92530588217SMike Christensen /*
92630588217SMike Christensen * Interface for ds_dom_hdl_to_name in lds driver.
92730588217SMike Christensen */
92830588217SMike Christensen int
ds_dom_hdl_to_name(ds_domain_hdl_t dhdl,char ** domain_namep)92930588217SMike Christensen ds_dom_hdl_to_name(ds_domain_hdl_t dhdl, char **domain_namep)
93030588217SMike Christensen {
93130588217SMike Christensen int i;
93230588217SMike Christensen ds_port_t *port;
93330588217SMike Christensen
934a600f50dSMike Christensen if (dhdl == ds_my_domain_hdl) {
935a600f50dSMike Christensen if (ds_my_domain_name != NULL) {
936a600f50dSMike Christensen *domain_namep = ds_my_domain_name;
937a600f50dSMike Christensen return (0);
938a600f50dSMike Christensen }
939a600f50dSMike Christensen return (ENXIO);
940a600f50dSMike Christensen }
94130588217SMike Christensen for (i = 0, port = ds_ports; i < DS_MAX_PORTS; i++, port++) {
94230588217SMike Christensen if (port->state != DS_PORT_FREE &&
94330588217SMike Christensen port->domain_hdl == dhdl) {
94430588217SMike Christensen *domain_namep = port->domain_name;
94530588217SMike Christensen return (0);
94630588217SMike Christensen }
94730588217SMike Christensen }
94830588217SMike Christensen return (ENXIO);
94930588217SMike Christensen }
95030588217SMike Christensen
95130588217SMike Christensen /*
95230588217SMike Christensen * Unregister all handles related to device open instance.
95330588217SMike Christensen */
95430588217SMike Christensen void
ds_unreg_all(int instance)95530588217SMike Christensen ds_unreg_all(int instance)
95630588217SMike Christensen {
95730588217SMike Christensen int idx;
95830588217SMike Christensen ds_svc_t *svc;
95930588217SMike Christensen ds_svc_hdl_t hdl;
96030588217SMike Christensen
96130588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: entered", __func__);
96230588217SMike Christensen
96330588217SMike Christensen /* walk every table entry */
96430588217SMike Christensen mutex_enter(&ds_svcs.lock);
96530588217SMike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
96630588217SMike Christensen svc = ds_svcs.tbl[idx];
96730588217SMike Christensen if (DS_SVC_ISFREE(svc))
96830588217SMike Christensen continue;
96930588217SMike Christensen if ((svc->flags & DSSF_ISUSER) != 0 && svc->drvi == instance) {
97030588217SMike Christensen hdl = svc->hdl;
97130588217SMike Christensen mutex_exit(&ds_svcs.lock);
97230588217SMike Christensen (void) ds_unreg_hdl(hdl);
97330588217SMike Christensen mutex_enter(&ds_svcs.lock);
97430588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: ds_unreg_hdl(0x%llx):",
97530588217SMike Christensen __func__, (u_longlong_t)hdl);
97630588217SMike Christensen }
97730588217SMike Christensen }
97830588217SMike Christensen mutex_exit(&ds_svcs.lock);
97930588217SMike Christensen }
98030588217SMike Christensen
98130588217SMike Christensen /*
98230588217SMike Christensen * Special callbacks to allow the lds module revision-independent access
98330588217SMike Christensen * to service structure data in the callback routines. This assumes that
98430588217SMike Christensen * we put a special "cookie" in the arg argument passed to those
98530588217SMike Christensen * routines (for now, a ptr to the svc structure, but it could be a svc
98630588217SMike Christensen * table index or something that we could get back to the svc table entry).
98730588217SMike Christensen */
98830588217SMike Christensen void
ds_cbarg_get_hdl(ds_cb_arg_t arg,ds_svc_hdl_t * hdlp)98930588217SMike Christensen ds_cbarg_get_hdl(ds_cb_arg_t arg, ds_svc_hdl_t *hdlp)
99030588217SMike Christensen {
99130588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
99230588217SMike Christensen
99330588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
99430588217SMike Christensen *hdlp = svc->hdl;
99530588217SMike Christensen }
99630588217SMike Christensen
99730588217SMike Christensen void
ds_cbarg_get_flags(ds_cb_arg_t arg,uint32_t * flagsp)99830588217SMike Christensen ds_cbarg_get_flags(ds_cb_arg_t arg, uint32_t *flagsp)
99930588217SMike Christensen {
100030588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
100130588217SMike Christensen
100230588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
100330588217SMike Christensen *flagsp = svc->flags;
100430588217SMike Christensen }
100530588217SMike Christensen
100630588217SMike Christensen void
ds_cbarg_get_drv_info(ds_cb_arg_t arg,int * drvip)100730588217SMike Christensen ds_cbarg_get_drv_info(ds_cb_arg_t arg, int *drvip)
100830588217SMike Christensen {
100930588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
101030588217SMike Christensen
101130588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
101230588217SMike Christensen *drvip = svc->drvi;
101330588217SMike Christensen }
101430588217SMike Christensen
101530588217SMike Christensen void
ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg,void ** dpspp)101630588217SMike Christensen ds_cbarg_get_drv_per_svc_ptr(ds_cb_arg_t arg, void **dpspp)
101730588217SMike Christensen {
101830588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
101930588217SMike Christensen
102030588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
102130588217SMike Christensen *dpspp = svc->drv_psp;
102230588217SMike Christensen }
102330588217SMike Christensen
102430588217SMike Christensen void
ds_cbarg_get_domain(ds_cb_arg_t arg,ds_domain_hdl_t * dhdlp)102530588217SMike Christensen ds_cbarg_get_domain(ds_cb_arg_t arg, ds_domain_hdl_t *dhdlp)
102630588217SMike Christensen {
102730588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
102830588217SMike Christensen
102930588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
103030588217SMike Christensen if (svc->port == NULL)
103130588217SMike Christensen *dhdlp = ds_my_domain_hdl;
103230588217SMike Christensen else
103330588217SMike Christensen *dhdlp = svc->port->domain_hdl;
103430588217SMike Christensen }
103530588217SMike Christensen
103630588217SMike Christensen void
ds_cbarg_get_service_id(ds_cb_arg_t arg,char ** servicep)103730588217SMike Christensen ds_cbarg_get_service_id(ds_cb_arg_t arg, char **servicep)
103830588217SMike Christensen {
103930588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
104030588217SMike Christensen
104130588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
104230588217SMike Christensen *servicep = svc->cap.svc_id;
104330588217SMike Christensen }
104430588217SMike Christensen
104530588217SMike Christensen void
ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg,void * dpsp)104630588217SMike Christensen ds_cbarg_set_drv_per_svc_ptr(ds_cb_arg_t arg, void *dpsp)
104730588217SMike Christensen {
104830588217SMike Christensen ds_svc_t *svc = (ds_svc_t *)arg;
104930588217SMike Christensen
105030588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
105130588217SMike Christensen svc->drv_psp = dpsp;
105230588217SMike Christensen }
105330588217SMike Christensen
105430588217SMike Christensen void
ds_cbarg_set_cookie(ds_svc_t * svc)105530588217SMike Christensen ds_cbarg_set_cookie(ds_svc_t *svc)
105630588217SMike Christensen {
105730588217SMike Christensen svc->ops.cb_arg = (ds_cb_arg_t)(svc);
105830588217SMike Christensen }
105930588217SMike Christensen
106030588217SMike Christensen int
ds_hdl_get_cbarg(ds_svc_hdl_t hdl,ds_cb_arg_t * cbargp)106130588217SMike Christensen ds_hdl_get_cbarg(ds_svc_hdl_t hdl, ds_cb_arg_t *cbargp)
106230588217SMike Christensen {
106330588217SMike Christensen ds_svc_t *svc;
106430588217SMike Christensen
106530588217SMike Christensen mutex_enter(&ds_svcs.lock);
106630588217SMike Christensen if ((svc = ds_get_svc(hdl)) != NULL &&
106730588217SMike Christensen (svc->flags & DSSF_ISUSER) != 0) {
106830588217SMike Christensen ASSERT(svc == (ds_svc_t *)svc->ops.cb_arg);
106930588217SMike Christensen *cbargp = svc->ops.cb_arg;
107030588217SMike Christensen mutex_exit(&ds_svcs.lock);
107130588217SMike Christensen return (0);
107230588217SMike Christensen }
107330588217SMike Christensen mutex_exit(&ds_svcs.lock);
107430588217SMike Christensen return (ENXIO);
107530588217SMike Christensen }
107630588217SMike Christensen
107730588217SMike Christensen int
ds_is_my_hdl(ds_svc_hdl_t hdl,int instance)107830588217SMike Christensen ds_is_my_hdl(ds_svc_hdl_t hdl, int instance)
107930588217SMike Christensen {
108030588217SMike Christensen ds_svc_t *svc;
108130588217SMike Christensen int rv = 0;
108230588217SMike Christensen
108330588217SMike Christensen mutex_enter(&ds_svcs.lock);
108430588217SMike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
108530588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: invalid hdl: 0x%llx\n", __func__,
108630588217SMike Christensen (u_longlong_t)hdl);
108730588217SMike Christensen rv = ENXIO;
108830588217SMike Christensen } else if (instance == DS_INVALID_INSTANCE) {
108930588217SMike Christensen if ((svc->flags & DSSF_ISUSER) != 0) {
109030588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n",
109130588217SMike Christensen __func__, (u_longlong_t)hdl);
109230588217SMike Christensen rv = EACCES;
109330588217SMike Christensen }
109430588217SMike Christensen } else if ((svc->flags & DSSF_ISUSER) == 0 || svc->drvi != instance) {
109530588217SMike Christensen DS_DBG_USR(CE_NOTE, "%s: unowned hdl: 0x%llx\n", __func__,
109630588217SMike Christensen (u_longlong_t)hdl);
109730588217SMike Christensen rv = EACCES;
109830588217SMike Christensen }
109930588217SMike Christensen mutex_exit(&ds_svcs.lock);
110030588217SMike Christensen return (rv);
110130588217SMike Christensen }
1102