xref: /onnv-gate/usr/src/uts/sun4v/promif/promif_prop.c (revision 11066:cebb50cbe4f9)
11991Sheppo /*
21991Sheppo  * CDDL HEADER START
31991Sheppo  *
41991Sheppo  * The contents of this file are subject to the terms of the
51991Sheppo  * Common Development and Distribution License (the "License").
61991Sheppo  * You may not use this file except in compliance with the License.
71991Sheppo  *
81991Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91991Sheppo  * or http://www.opensolaris.org/os/licensing.
101991Sheppo  * See the License for the specific language governing permissions
111991Sheppo  * and limitations under the License.
121991Sheppo  *
131991Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141991Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151991Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161991Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171991Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181991Sheppo  *
191991Sheppo  * CDDL HEADER END
201991Sheppo  */
211991Sheppo 
221991Sheppo /*
23*11066Srafael.vanoni@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241991Sheppo  * Use is subject to license terms.
251991Sheppo  */
261991Sheppo 
271991Sheppo #include <sys/types.h>
281991Sheppo #include <sys/ddi.h>
291991Sheppo #include <sys/sunddi.h>
301991Sheppo #include <sys/promif_impl.h>
311991Sheppo #include <sys/ds.h>
321991Sheppo #include <sys/modctl.h>
331991Sheppo #include <sys/ksynch.h>
341991Sheppo #include <sys/varconfig.h>
351991Sheppo 
361991Sheppo #ifndef _KMDB
371991Sheppo 
381991Sheppo #define	PROMIF_DS_TIMEOUT_SEC 15
391991Sheppo 
401991Sheppo static kmutex_t promif_prop_lock;
411991Sheppo static kcondvar_t promif_prop_cv;
421991Sheppo static var_config_msg_t promif_ds_resp;
431991Sheppo static var_config_resp_t *cfg_rsp = &promif_ds_resp.var_config_resp;
441991Sheppo static int (*ds_send)();
451991Sheppo static int (*ds_init)();
461991Sheppo 
471991Sheppo /*
481991Sheppo  * Domains Services interaction
491991Sheppo  */
501991Sheppo static ds_svc_hdl_t	ds_primary_handle;
511991Sheppo static ds_svc_hdl_t	ds_backup_handle;
521991Sheppo 
531991Sheppo static ds_ver_t		vc_version[] = { { 1, 0 } };
541991Sheppo 
551991Sheppo #define	VC_NVERS	(sizeof (vc_version) / sizeof (vc_version[0]))
561991Sheppo 
571991Sheppo static ds_capability_t vc_primary_cap = {
581991Sheppo 	"var-config",		/* svc_id */
591991Sheppo 	vc_version,		/* vers */
601991Sheppo 	VC_NVERS		/* nvers */
611991Sheppo };
621991Sheppo 
631991Sheppo static ds_capability_t vc_backup_cap = {
641991Sheppo 	"var-config-backup",	/* svc_id */
651991Sheppo 	vc_version,		/* vers */
661991Sheppo 	VC_NVERS		/* nvers */
671991Sheppo };
681991Sheppo 
691991Sheppo static void vc_reg_handler(ds_cb_arg_t, ds_ver_t *, ds_svc_hdl_t);
701991Sheppo static void vc_unreg_handler(ds_cb_arg_t);
711991Sheppo static void vc_data_handler(ds_cb_arg_t, void *, size_t);
721991Sheppo 
731991Sheppo static ds_clnt_ops_t vc_primary_ops = {
741991Sheppo 	vc_reg_handler,		/* ds_primary_reg_cb */
751991Sheppo 	vc_unreg_handler,	/* ds_primary_unreg_cb */
761991Sheppo 	vc_data_handler,	/* ds_data_cb */
771991Sheppo 	&ds_primary_handle	/* cb_arg */
781991Sheppo };
791991Sheppo 
801991Sheppo static ds_clnt_ops_t vc_backup_ops = {
811991Sheppo 	vc_reg_handler,		/* ds_backup_reg_cb */
821991Sheppo 	vc_unreg_handler,	/* ds_backup_unreg_cb */
831991Sheppo 	vc_data_handler,	/* ds_data_cb */
841991Sheppo 	&ds_backup_handle	/* cb_arg */
851991Sheppo };
861991Sheppo 
871991Sheppo static void
vc_reg_handler(ds_cb_arg_t arg,ds_ver_t * ver,ds_svc_hdl_t hdl)881991Sheppo vc_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
891991Sheppo {
901991Sheppo 	_NOTE(ARGUNUSED(ver))
911991Sheppo 
921991Sheppo 	if ((ds_svc_hdl_t *)arg == &ds_primary_handle)
931991Sheppo 		ds_primary_handle = hdl;
941991Sheppo 	else if ((ds_svc_hdl_t *)arg == &ds_backup_handle)
952600Sjm22469 		ds_backup_handle = hdl;
961991Sheppo }
971991Sheppo 
981991Sheppo static void
vc_unreg_handler(ds_cb_arg_t arg)991991Sheppo vc_unreg_handler(ds_cb_arg_t arg)
1001991Sheppo {
1011991Sheppo 	if ((ds_svc_hdl_t *)arg == &ds_primary_handle)
1021991Sheppo 		ds_primary_handle = DS_INVALID_HDL;
1031991Sheppo 	else if ((ds_svc_hdl_t *)arg == &ds_backup_handle)
1041991Sheppo 		ds_backup_handle = DS_INVALID_HDL;
1051991Sheppo }
1061991Sheppo 
1071991Sheppo static void
vc_data_handler(ds_cb_arg_t arg,void * buf,size_t buflen)1081991Sheppo vc_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen)
1091991Sheppo {
1101991Sheppo 	_NOTE(ARGUNUSED(arg))
1111991Sheppo 
1121991Sheppo 	bcopy(buf, &promif_ds_resp, buflen);
1131991Sheppo 	mutex_enter(&promif_prop_lock);
1141991Sheppo 	cv_signal(&promif_prop_cv);
1151991Sheppo 	mutex_exit(&promif_prop_lock);
1161991Sheppo }
1171991Sheppo 
1181991Sheppo /*
1191991Sheppo  * Initialize the linkage with DS (Domain Services).  We assume that
1201991Sheppo  * the DS module has already been loaded by the platmod.
1211991Sheppo  *
1221991Sheppo  * The call to the DS init functions will eventually result in the
1231991Sheppo  * invocation of our registration callback handlers, at which time DS
1241991Sheppo  * is able to accept requests.
1251991Sheppo  */
1261991Sheppo static void
promif_ds_init(void)1271991Sheppo promif_ds_init(void)
1281991Sheppo {
1291991Sheppo 	static char *me = "promif_ds_init";
1301991Sheppo 	int rv;
1311991Sheppo 
1321991Sheppo 	if ((ds_init =
1331991Sheppo 	    (int (*)())modgetsymvalue("ds_cap_init", 0)) == 0) {
1341991Sheppo 		cmn_err(CE_WARN, "%s: can't find ds_cap_init", me);
1351991Sheppo 		return;
1361991Sheppo 	}
1371991Sheppo 
1381991Sheppo 	if ((ds_send =
1391991Sheppo 	    (int (*)())modgetsymvalue("ds_cap_send", 0)) == 0) {
1401991Sheppo 		cmn_err(CE_WARN, "%s: can't find ds_cap_send", me);
1411991Sheppo 		return;
1421991Sheppo 	}
1431991Sheppo 
1441991Sheppo 	if ((rv = (*ds_init)(&vc_primary_cap, &vc_primary_ops)) != 0) {
1451991Sheppo 		cmn_err(CE_NOTE,
1461991Sheppo 		    "%s: ds_cap_init failed (primary): %d", me, rv);
1471991Sheppo 	}
1481991Sheppo 
1491991Sheppo 
1501991Sheppo 	if ((rv = (*ds_init)(&vc_backup_cap, &vc_backup_ops)) != 0) {
1511991Sheppo 		cmn_err(CE_NOTE,
1521991Sheppo 		    "%s: ds_cap_init failed (backup): %d", me, rv);
1531991Sheppo 	}
1541991Sheppo }
1551991Sheppo 
1561991Sheppo /*
1571991Sheppo  * Prepare for ldom variable requests.
1581991Sheppo  */
1591991Sheppo void
promif_prop_init(void)1601991Sheppo promif_prop_init(void)
1611991Sheppo {
1621991Sheppo 	mutex_init(&promif_prop_lock, NULL, MUTEX_DEFAULT, NULL);
1631991Sheppo 	cv_init(&promif_prop_cv, NULL, CV_DEFAULT, NULL);
1641991Sheppo 
1651991Sheppo 	promif_ds_init();
1661991Sheppo }
1671991Sheppo 
1681991Sheppo 
1691991Sheppo /*
1701991Sheppo  * Replace the current value of a property string given its name and
1711991Sheppo  * new value.
1721991Sheppo  */
1731991Sheppo int
promif_ldom_setprop(char * name,void * value,int valuelen)1741991Sheppo promif_ldom_setprop(char *name, void *value, int valuelen)
1751991Sheppo {
1761991Sheppo 	var_config_msg_t *req;
1771991Sheppo 	var_config_set_req_t *setp;
1781991Sheppo 	var_config_cmd_t cmd;
1791991Sheppo 	ds_svc_hdl_t ds_handle;
1801991Sheppo 	int rv;
1811991Sheppo 	int namelen = strlen(name);
1821991Sheppo 	int paylen = namelen + 1 + valuelen; /* valuelen includes the null */
1831991Sheppo 	static char *me = "promif_ldom_setprop";
1841991Sheppo 
1851991Sheppo 	if (ds_primary_handle != DS_INVALID_HDL)
1861991Sheppo 		ds_handle = ds_primary_handle;
1871991Sheppo 	else if (ds_backup_handle != DS_INVALID_HDL)
1881991Sheppo 		ds_handle = ds_backup_handle;
1891991Sheppo 	else
1901991Sheppo 		return (-1);
1911991Sheppo 
1925035Sjm22469 	/*
1935035Sjm22469 	 * Since we are emulating OBP, we must comply with the promif
1945035Sjm22469 	 * infrastructure and execute only on the originating cpu.
1955035Sjm22469 	 */
1965768Sjm22469 	thread_affinity_set(curthread, CPU->cpu_id);
1975035Sjm22469 
1981991Sheppo 	req = kmem_zalloc(sizeof (var_config_hdr_t) + paylen, KM_SLEEP);
1991991Sheppo 	req->var_config_cmd = VAR_CONFIG_SET_REQ;
2001991Sheppo 	setp = &req->var_config_set;
2011991Sheppo 	(void) strcpy(setp->name_and_value, name);
2021991Sheppo 	(void) strncpy(&setp->name_and_value[namelen + 1], value, valuelen);
2031991Sheppo 
2041991Sheppo 	if ((rv = (*ds_send)(ds_handle, req,
2051991Sheppo 	    sizeof (var_config_hdr_t) + paylen)) != 0) {
2061991Sheppo 		cmn_err(CE_WARN, "%s: ds_cap_send failed: %d", me, rv);
2071991Sheppo 		kmem_free(req, sizeof (var_config_hdr_t) + paylen);
2085035Sjm22469 		thread_affinity_clear(curthread);
2091991Sheppo 		return (-1);
2101991Sheppo 	}
2111991Sheppo 
2121991Sheppo 	kmem_free(req, sizeof (var_config_hdr_t) + paylen);
2131991Sheppo 
2141991Sheppo 	mutex_enter(&promif_prop_lock);
215*11066Srafael.vanoni@sun.com 	if (cv_reltimedwait(&promif_prop_cv, &promif_prop_lock,
216*11066Srafael.vanoni@sun.com 	    PROMIF_DS_TIMEOUT_SEC * hz, TR_CLOCK_TICK) == -1) {
2171991Sheppo 		cmn_err(CE_WARN, "%s: ds response timeout", me);
2181991Sheppo 		rv = -1;
2191991Sheppo 		goto out;
2201991Sheppo 	}
2211991Sheppo 
2221991Sheppo 	cmd = promif_ds_resp.vc_hdr.cmd;
2231991Sheppo 	if (cmd != VAR_CONFIG_SET_RESP) {
2241991Sheppo 		cmn_err(CE_WARN, "%s: bad response type: %d", me, cmd);
2251991Sheppo 		rv = -1;
2261991Sheppo 		goto out;
2271991Sheppo 	}
2281991Sheppo 	rv = (cfg_rsp->result == VAR_CONFIG_SUCCESS) ? valuelen : -1;
2291991Sheppo 
2301991Sheppo out:
2311991Sheppo 	mutex_exit(&promif_prop_lock);
2321991Sheppo 	thread_affinity_clear(curthread);
2331991Sheppo 	return (rv);
2341991Sheppo }
2351991Sheppo 
2361991Sheppo int
promif_setprop(void * p)2371991Sheppo promif_setprop(void *p)
2381991Sheppo {
2391991Sheppo 	cell_t	*ci = (cell_t *)p;
2401991Sheppo 	pnode_t node;
2411991Sheppo 	caddr_t	name;
2421991Sheppo 	caddr_t	value;
2431991Sheppo 	int	len;
2441991Sheppo 
2451991Sheppo 	ASSERT(ci[1] == 4);
2461991Sheppo 
2471991Sheppo 	node  = p1275_cell2dnode(ci[3]);
2481991Sheppo 	ASSERT(node == prom_optionsnode());
2491991Sheppo 	name  = p1275_cell2ptr(ci[4]);
2501991Sheppo 	value = p1275_cell2ptr(ci[5]);
2511991Sheppo 	len = p1275_cell2int(ci[6]);
2521991Sheppo 
2531991Sheppo 	if (promif_stree_getproplen(node, name) != -1)
2541991Sheppo 		len = promif_ldom_setprop(name, value, len);
2551991Sheppo 
2561991Sheppo 	if (len >= 0)
2571991Sheppo 		len = promif_stree_setprop(node, name, (void *)value, len);
2581991Sheppo 
2591991Sheppo 
2601991Sheppo 	ci[7] = p1275_int2cell(len);
2611991Sheppo 
2621991Sheppo 	return ((len == -1) ? len : 0);
2631991Sheppo }
2641991Sheppo 
2651991Sheppo #endif
2661991Sheppo 
2671991Sheppo int
promif_getprop(void * p)2681991Sheppo promif_getprop(void *p)
2691991Sheppo {
2701991Sheppo 	cell_t	*ci = (cell_t *)p;
2711991Sheppo 	pnode_t	node;
2721991Sheppo 	caddr_t	name;
2731991Sheppo 	caddr_t	value;
2741991Sheppo 	int	len;
2751991Sheppo 
2761991Sheppo 	ASSERT(ci[1] == 4);
2771991Sheppo 
2781991Sheppo 	node  = p1275_cell2dnode(ci[3]);
2791991Sheppo 	name  = p1275_cell2ptr(ci[4]);
2801991Sheppo 	value = p1275_cell2ptr(ci[5]);
2811991Sheppo 
2821991Sheppo 	len = promif_stree_getprop(node, name, value);
2831991Sheppo 
2841991Sheppo 	ci[7] = p1275_int2cell(len);
2851991Sheppo 
2861991Sheppo 	return ((len == -1) ? len : 0);
2871991Sheppo }
2881991Sheppo 
2891991Sheppo int
promif_getproplen(void * p)2901991Sheppo promif_getproplen(void *p)
2911991Sheppo {
2921991Sheppo 	cell_t	*ci = (cell_t *)p;
2931991Sheppo 	pnode_t	node;
2941991Sheppo 	caddr_t	name;
2951991Sheppo 	int	len;
2961991Sheppo 
2971991Sheppo 	ASSERT(ci[1] == 2);
2981991Sheppo 
2991991Sheppo 	node = p1275_cell2dnode(ci[3]);
3001991Sheppo 	name = p1275_cell2ptr(ci[4]);
3011991Sheppo 
3021991Sheppo 	len = promif_stree_getproplen(node, name);
3031991Sheppo 
3041991Sheppo 	ci[5] = p1275_int2cell(len);
3051991Sheppo 
3061991Sheppo 	return (0);
3071991Sheppo }
3081991Sheppo 
3091991Sheppo int
promif_nextprop(void * p)3101991Sheppo promif_nextprop(void *p)
3111991Sheppo {
3121991Sheppo 	cell_t	*ci = (cell_t *)p;
3131991Sheppo 	pnode_t	node;
3141991Sheppo 	caddr_t	prev;
3151991Sheppo 	caddr_t	next;
3161991Sheppo 
3171991Sheppo 	ASSERT(ci[1] == 3);
3181991Sheppo 
3191991Sheppo 	node = p1275_cell2dnode(ci[3]);
3201991Sheppo 	prev = p1275_cell2ptr(ci[4]);
3211991Sheppo 	next = p1275_cell2ptr(ci[5]);
3221991Sheppo 
3231991Sheppo 	(void) promif_stree_nextprop(node, prev, next);
3241991Sheppo 
3251991Sheppo 	return (0);
3261991Sheppo }
327