xref: /onnv-gate/usr/src/uts/common/avs/ns/sdbc/sd_trace.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
28*7836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
29*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
30*7836SJohn.Forte@Sun.COM #include <sys/kmem.h>
31*7836SJohn.Forte@Sun.COM #include <sys/ddi.h>
32*7836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
33*7836SJohn.Forte@Sun.COM 
34*7836SJohn.Forte@Sun.COM #include "sd_bcache.h"
35*7836SJohn.Forte@Sun.COM #include "sd_trace.h"
36*7836SJohn.Forte@Sun.COM #include "sd_misc.h"
37*7836SJohn.Forte@Sun.COM 
38*7836SJohn.Forte@Sun.COM #ifndef _SD_NOTRACE
39*7836SJohn.Forte@Sun.COM 
40*7836SJohn.Forte@Sun.COM #ifndef SM_SDTRSEMA
41*7836SJohn.Forte@Sun.COM #define	SM_SDTRSEMA 1
42*7836SJohn.Forte@Sun.COM #define	SM_SDTRLCK  1
43*7836SJohn.Forte@Sun.COM #endif
44*7836SJohn.Forte@Sun.COM 
45*7836SJohn.Forte@Sun.COM int _sd_trace_mask = 0;
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM /*
48*7836SJohn.Forte@Sun.COM  * _sdbd_trace_t _sd_trace_table[-1, 0 .. sdbc_max_devs - 1]
49*7836SJohn.Forte@Sun.COM  *	allocate memory, shift pointer up by one.
50*7836SJohn.Forte@Sun.COM  */
51*7836SJohn.Forte@Sun.COM static _sdbc_trace_t	*_sd_trace_table;
52*7836SJohn.Forte@Sun.COM 
53*7836SJohn.Forte@Sun.COM static kcondvar_t	_sd_adump_cv;
54*7836SJohn.Forte@Sun.COM static int _sd_trace_configed;
55*7836SJohn.Forte@Sun.COM static kmutex_t  _sd_adump_lk;
56*7836SJohn.Forte@Sun.COM 
57*7836SJohn.Forte@Sun.COM static int		_alert_cd = SDT_ANY_CD;
58*7836SJohn.Forte@Sun.COM static int		_last_cd = SDT_ANY_CD;
59*7836SJohn.Forte@Sun.COM #define	XMEM(x, y)	(void)(x = y, y = (SDT_ANY_CD), x)
60*7836SJohn.Forte@Sun.COM 
61*7836SJohn.Forte@Sun.COM /*
62*7836SJohn.Forte@Sun.COM  * Forward declare all statics that are used before defined to enforce
63*7836SJohn.Forte@Sun.COM  * parameter checking.
64*7836SJohn.Forte@Sun.COM  * Some (if not all) of these could be removed if the code were reordered
65*7836SJohn.Forte@Sun.COM  */
66*7836SJohn.Forte@Sun.COM 
67*7836SJohn.Forte@Sun.COM static int _sd_set_adump(int cd, int flag, _sdtr_table_t *table);
68*7836SJohn.Forte@Sun.COM 
69*7836SJohn.Forte@Sun.COM /*
70*7836SJohn.Forte@Sun.COM  * _sdbc_tr_unload - cache is being unloaded. Release any memory/lock/sv's
71*7836SJohn.Forte@Sun.COM  * created by _sdbc_tr_unload and null the stale pointers.
72*7836SJohn.Forte@Sun.COM  *
73*7836SJohn.Forte@Sun.COM  */
74*7836SJohn.Forte@Sun.COM void
_sdbc_tr_unload(void)75*7836SJohn.Forte@Sun.COM _sdbc_tr_unload(void)
76*7836SJohn.Forte@Sun.COM {
77*7836SJohn.Forte@Sun.COM 	if (_sd_trace_table)
78*7836SJohn.Forte@Sun.COM 		nsc_kmem_free((_sd_trace_table - 1),
79*7836SJohn.Forte@Sun.COM 		    sizeof (_sdbc_trace_t) * (sdbc_max_devs + 1));
80*7836SJohn.Forte@Sun.COM 	cv_destroy(&_sd_adump_cv);
81*7836SJohn.Forte@Sun.COM 	mutex_destroy(&_sd_adump_lk);
82*7836SJohn.Forte@Sun.COM 
83*7836SJohn.Forte@Sun.COM 	_sd_trace_table = NULL;
84*7836SJohn.Forte@Sun.COM }
85*7836SJohn.Forte@Sun.COM 
86*7836SJohn.Forte@Sun.COM /*
87*7836SJohn.Forte@Sun.COM  * _sdbc_tr_load - cache is being loaded. Allocate the memory/lock/sv's
88*7836SJohn.Forte@Sun.COM  * which need to be present regardless of state of cache configuration.
89*7836SJohn.Forte@Sun.COM  *
90*7836SJohn.Forte@Sun.COM  */
91*7836SJohn.Forte@Sun.COM int
_sdbc_tr_load(void)92*7836SJohn.Forte@Sun.COM _sdbc_tr_load(void)
93*7836SJohn.Forte@Sun.COM {
94*7836SJohn.Forte@Sun.COM 	_sdbc_trace_t *m;
95*7836SJohn.Forte@Sun.COM 
96*7836SJohn.Forte@Sun.COM 	cv_init(&_sd_adump_cv, NULL, CV_DRIVER, NULL);
97*7836SJohn.Forte@Sun.COM 	mutex_init(&_sd_adump_lk, NULL, MUTEX_DRIVER, NULL);
98*7836SJohn.Forte@Sun.COM 
99*7836SJohn.Forte@Sun.COM 	/*
100*7836SJohn.Forte@Sun.COM 	 * this maybe ought to wait to see if traces are configured, but it
101*7836SJohn.Forte@Sun.COM 	 * is only 4k
102*7836SJohn.Forte@Sun.COM 	 */
103*7836SJohn.Forte@Sun.COM 
104*7836SJohn.Forte@Sun.COM 	m = (_sdbc_trace_t *)nsc_kmem_zalloc(
105*7836SJohn.Forte@Sun.COM 	    sizeof (_sdbc_trace_t) * (sdbc_max_devs + 1),
106*7836SJohn.Forte@Sun.COM 	    KM_NOSLEEP, sdbc_stats_mem);
107*7836SJohn.Forte@Sun.COM 
108*7836SJohn.Forte@Sun.COM 	if (m == NULL) {
109*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
110*7836SJohn.Forte@Sun.COM 		    "sdbc(_sdbc_tr_load) cannot allocate trace table");
111*7836SJohn.Forte@Sun.COM 		return (-1);
112*7836SJohn.Forte@Sun.COM 	}
113*7836SJohn.Forte@Sun.COM 	_sd_trace_table = m + 1;
114*7836SJohn.Forte@Sun.COM 
115*7836SJohn.Forte@Sun.COM 	return (0);
116*7836SJohn.Forte@Sun.COM 
117*7836SJohn.Forte@Sun.COM }
118*7836SJohn.Forte@Sun.COM 
119*7836SJohn.Forte@Sun.COM /*
120*7836SJohn.Forte@Sun.COM  * _sdbc_tr_configure - configure a trace area for the descriptor "cd".
121*7836SJohn.Forte@Sun.COM  * Unlike other ..._configure routines this routine is called multiple
122*7836SJohn.Forte@Sun.COM  * times since there will be an unknown number of open descriptors. At
123*7836SJohn.Forte@Sun.COM  * cache config time if tracing is enabled only the slot for SDT_INV_CD
124*7836SJohn.Forte@Sun.COM  * is created.
125*7836SJohn.Forte@Sun.COM  *
126*7836SJohn.Forte@Sun.COM  * Allocate the SD cache trace area (per device)
127*7836SJohn.Forte@Sun.COM  */
128*7836SJohn.Forte@Sun.COM 
129*7836SJohn.Forte@Sun.COM int
_sdbc_tr_configure(int cd)130*7836SJohn.Forte@Sun.COM _sdbc_tr_configure(int cd)
131*7836SJohn.Forte@Sun.COM {
132*7836SJohn.Forte@Sun.COM 	int size;
133*7836SJohn.Forte@Sun.COM 	_sdtr_table_t *t;
134*7836SJohn.Forte@Sun.COM 	kmutex_t *lk;
135*7836SJohn.Forte@Sun.COM 
136*7836SJohn.Forte@Sun.COM 	if (!_sd_cache_config.trace_size)
137*7836SJohn.Forte@Sun.COM 		return (0);
138*7836SJohn.Forte@Sun.COM 
139*7836SJohn.Forte@Sun.COM 	if (cd == SDT_INV_CD)
140*7836SJohn.Forte@Sun.COM 		_sd_trace_configed = 1;
141*7836SJohn.Forte@Sun.COM 
142*7836SJohn.Forte@Sun.COM 	if (_sd_trace_table[cd].tbl)
143*7836SJohn.Forte@Sun.COM 		return (0);
144*7836SJohn.Forte@Sun.COM 
145*7836SJohn.Forte@Sun.COM 	size = sizeof (_sdtr_table_t) +
146*7836SJohn.Forte@Sun.COM 	    _sd_cache_config.trace_size * sizeof (_sdtr_t);
147*7836SJohn.Forte@Sun.COM 
148*7836SJohn.Forte@Sun.COM 	if ((t = (_sdtr_table_t *)nsc_kmem_zalloc(size,
149*7836SJohn.Forte@Sun.COM 	    KM_NOSLEEP, sdbc_stats_mem)) == NULL) {
150*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "sdbc(_sdbc_tr_configure) failed to "
151*7836SJohn.Forte@Sun.COM 		    "allocate %d bytes for trace, cd=%d", size, cd);
152*7836SJohn.Forte@Sun.COM 		return (-1);
153*7836SJohn.Forte@Sun.COM 	}
154*7836SJohn.Forte@Sun.COM 
155*7836SJohn.Forte@Sun.COM 	lk = nsc_kmem_zalloc(sizeof (kmutex_t), KM_NOSLEEP, sdbc_local_mem);
156*7836SJohn.Forte@Sun.COM 	if (!lk) {
157*7836SJohn.Forte@Sun.COM 		nsc_kmem_free(t, size);
158*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "sdbc(_sdbc_tr_configure) cannot "
159*7836SJohn.Forte@Sun.COM 		    "alloc trace lock for cd %d", cd);
160*7836SJohn.Forte@Sun.COM 		return (-1);
161*7836SJohn.Forte@Sun.COM 	}
162*7836SJohn.Forte@Sun.COM 	mutex_init(lk, NULL, MUTEX_DRIVER, NULL);
163*7836SJohn.Forte@Sun.COM 
164*7836SJohn.Forte@Sun.COM 	_sd_trace_table[cd].t_lock = lk;
165*7836SJohn.Forte@Sun.COM 	t->tt_cd   = cd;
166*7836SJohn.Forte@Sun.COM 	t->tt_max  = _sd_cache_config.trace_size;
167*7836SJohn.Forte@Sun.COM 	t->tt_mask = _sd_cache_config.trace_mask;
168*7836SJohn.Forte@Sun.COM 	t->tt_lbolt = (char)_sd_cache_config.trace_lbolt;
169*7836SJohn.Forte@Sun.COM 	t->tt_good = (char)_sd_cache_config.trace_good;
170*7836SJohn.Forte@Sun.COM 	_sd_trace_mask |= t->tt_mask;
171*7836SJohn.Forte@Sun.COM 	_sd_trace_table[cd].tbl = t;
172*7836SJohn.Forte@Sun.COM 	return (0);
173*7836SJohn.Forte@Sun.COM }
174*7836SJohn.Forte@Sun.COM 
175*7836SJohn.Forte@Sun.COM 
176*7836SJohn.Forte@Sun.COM /*
177*7836SJohn.Forte@Sun.COM  * _sdbc_tr_deconfigure
178*7836SJohn.Forte@Sun.COM  *	free all trace memory (regions) when deconfiguring cache
179*7836SJohn.Forte@Sun.COM  */
180*7836SJohn.Forte@Sun.COM void
_sdbc_tr_deconfigure(void)181*7836SJohn.Forte@Sun.COM _sdbc_tr_deconfigure(void)
182*7836SJohn.Forte@Sun.COM {
183*7836SJohn.Forte@Sun.COM 	int i, size;
184*7836SJohn.Forte@Sun.COM 	_sdbc_trace_t *tt;
185*7836SJohn.Forte@Sun.COM 
186*7836SJohn.Forte@Sun.COM 	if (!_sd_cache_config.trace_size || !_sd_trace_configed)
187*7836SJohn.Forte@Sun.COM 		return;
188*7836SJohn.Forte@Sun.COM 
189*7836SJohn.Forte@Sun.COM 	mutex_enter(&_sd_adump_lk);
190*7836SJohn.Forte@Sun.COM 	_sd_trace_configed = 0;
191*7836SJohn.Forte@Sun.COM 	cv_broadcast(&_sd_adump_cv);
192*7836SJohn.Forte@Sun.COM 	mutex_exit(&_sd_adump_lk);
193*7836SJohn.Forte@Sun.COM 
194*7836SJohn.Forte@Sun.COM 	for (i = -1, tt = &_sd_trace_table[-1]; i < sdbc_max_devs; i++, tt++) {
195*7836SJohn.Forte@Sun.COM 		if (tt->tbl == NULL) continue;
196*7836SJohn.Forte@Sun.COM 		size = tt->tbl->tt_max * sizeof (_sdtr_t) +
197*7836SJohn.Forte@Sun.COM 		    sizeof (_sdtr_table_t);
198*7836SJohn.Forte@Sun.COM 		if (tt->t_lock) {
199*7836SJohn.Forte@Sun.COM 			mutex_destroy(tt->t_lock);
200*7836SJohn.Forte@Sun.COM 			nsc_kmem_free(tt->t_lock, sizeof (kmutex_t));
201*7836SJohn.Forte@Sun.COM 		}
202*7836SJohn.Forte@Sun.COM 		nsc_kmem_free(tt->tbl, size);
203*7836SJohn.Forte@Sun.COM 		tt->t_lock = NULL;
204*7836SJohn.Forte@Sun.COM 		tt->tbl = NULL;
205*7836SJohn.Forte@Sun.COM 	}
206*7836SJohn.Forte@Sun.COM 	_alert_cd = SDT_ANY_CD;
207*7836SJohn.Forte@Sun.COM 	_last_cd = SDT_ANY_CD;
208*7836SJohn.Forte@Sun.COM }
209*7836SJohn.Forte@Sun.COM 
210*7836SJohn.Forte@Sun.COM static int first_alert = 0;
211*7836SJohn.Forte@Sun.COM /*
212*7836SJohn.Forte@Sun.COM  * SDALERT(f,cd,len,fba,flg,ret) \
213*7836SJohn.Forte@Sun.COM  *	_sd_alert(f,cd,len,fba,flg,ret)
214*7836SJohn.Forte@Sun.COM  *  Build a ALERT trace entry and place it into the trace table.
215*7836SJohn.Forte@Sun.COM  */
216*7836SJohn.Forte@Sun.COM void
_sd_alert(int f,int cd,int len,nsc_off_t fba,int flg,int ret)217*7836SJohn.Forte@Sun.COM _sd_alert(int f, int cd, int len, nsc_off_t fba, int flg, int ret)
218*7836SJohn.Forte@Sun.COM {
219*7836SJohn.Forte@Sun.COM 	int tin;
220*7836SJohn.Forte@Sun.COM 	_sdtr_t *tp;
221*7836SJohn.Forte@Sun.COM 	_sdtr_table_t *t;
222*7836SJohn.Forte@Sun.COM 	kmutex_t *lk;
223*7836SJohn.Forte@Sun.COM 
224*7836SJohn.Forte@Sun.COM 	if (!first_alert) {
225*7836SJohn.Forte@Sun.COM 		first_alert++;
226*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
227*7836SJohn.Forte@Sun.COM 		    "sdbc(_sd_alert) cd=%x f=%x len=%x fba=%" NSC_SZFMT
228*7836SJohn.Forte@Sun.COM 		    " flg=%x ret=%x", cd, f, len, fba, flg, ret);
229*7836SJohn.Forte@Sun.COM 
230*7836SJohn.Forte@Sun.COM 	}
231*7836SJohn.Forte@Sun.COM 
232*7836SJohn.Forte@Sun.COM 	/* Watch out for negative error codes or simply bogus cd's */
233*7836SJohn.Forte@Sun.COM 
234*7836SJohn.Forte@Sun.COM 	if (cd < -1 || cd >= sdbc_max_devs) {
235*7836SJohn.Forte@Sun.COM 		/*
236*7836SJohn.Forte@Sun.COM 		 * no device trace buffer -- use SDT_INV_CD table?
237*7836SJohn.Forte@Sun.COM 		 */
238*7836SJohn.Forte@Sun.COM 		if ((t = _sd_trace_table[-1].tbl) == NULL)
239*7836SJohn.Forte@Sun.COM 			return;
240*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[-1].t_lock;
241*7836SJohn.Forte@Sun.COM 	} else {
242*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[cd].t_lock;
243*7836SJohn.Forte@Sun.COM 		if ((t = _sd_trace_table[cd].tbl) == NULL) {
244*7836SJohn.Forte@Sun.COM 			/*
245*7836SJohn.Forte@Sun.COM 			 * no device trace buffer -- use SDT_INV_CD table?
246*7836SJohn.Forte@Sun.COM 			 */
247*7836SJohn.Forte@Sun.COM 			if ((t = _sd_trace_table[-1].tbl) == NULL)
248*7836SJohn.Forte@Sun.COM 				return;
249*7836SJohn.Forte@Sun.COM 			lk = _sd_trace_table[-1].t_lock;
250*7836SJohn.Forte@Sun.COM 		}
251*7836SJohn.Forte@Sun.COM 	}
252*7836SJohn.Forte@Sun.COM 
253*7836SJohn.Forte@Sun.COM 	if (!(t->tt_mask & ST_ALERT))
254*7836SJohn.Forte@Sun.COM 		return;	/* check per-device mask */
255*7836SJohn.Forte@Sun.COM 
256*7836SJohn.Forte@Sun.COM 	if (t->tt_good) mutex_enter(lk);
257*7836SJohn.Forte@Sun.COM 	t->tt_alert++;	/* alert on this device */
258*7836SJohn.Forte@Sun.COM 	t->tt_cnt++;	/* overwritten entries if (tt_cnt >= tt_max) */
259*7836SJohn.Forte@Sun.COM 
260*7836SJohn.Forte@Sun.COM 	tin = t->tt_in++;
261*7836SJohn.Forte@Sun.COM 	if (tin >= t->tt_max) tin = t->tt_in = 0;
262*7836SJohn.Forte@Sun.COM 	tp = &t->tt_buf[tin];
263*7836SJohn.Forte@Sun.COM 	tp->t_time = 0;		/* not filled in yet */
264*7836SJohn.Forte@Sun.COM 	if (t->tt_good) mutex_exit(lk);
265*7836SJohn.Forte@Sun.COM 
266*7836SJohn.Forte@Sun.COM 	tp->t_func = (ushort_t)f | ST_ALERT;
267*7836SJohn.Forte@Sun.COM 	tp->t_len = (ushort_t)len;
268*7836SJohn.Forte@Sun.COM 	tp->t_fba = fba;
269*7836SJohn.Forte@Sun.COM 	tp->t_flg = flg;
270*7836SJohn.Forte@Sun.COM 	tp->t_ret = ret;
271*7836SJohn.Forte@Sun.COM 	/*
272*7836SJohn.Forte@Sun.COM 	 * On LP64 systems we will only capture the low 32 bits of the
273*7836SJohn.Forte@Sun.COM 	 * time this really should be good enough for our purposes.
274*7836SJohn.Forte@Sun.COM 	 *
275*7836SJohn.Forte@Sun.COM 	 */
276*7836SJohn.Forte@Sun.COM 	if (t->tt_lbolt)
277*7836SJohn.Forte@Sun.COM 		tp->t_time = (int)nsc_lbolt();
278*7836SJohn.Forte@Sun.COM 	else
279*7836SJohn.Forte@Sun.COM 		tp->t_time = (int)nsc_usec();
280*7836SJohn.Forte@Sun.COM 
281*7836SJohn.Forte@Sun.COM 	/* wakeup trace daemon, with hint */
282*7836SJohn.Forte@Sun.COM 	_alert_cd = cd;
283*7836SJohn.Forte@Sun.COM 
284*7836SJohn.Forte@Sun.COM 	if (_sd_trace_configed)
285*7836SJohn.Forte@Sun.COM 		cv_signal(&_sd_adump_cv);
286*7836SJohn.Forte@Sun.COM }
287*7836SJohn.Forte@Sun.COM 
288*7836SJohn.Forte@Sun.COM 
289*7836SJohn.Forte@Sun.COM /*
290*7836SJohn.Forte@Sun.COM  * SDTRACE(f,cd,len,fba,flg,ret) \
291*7836SJohn.Forte@Sun.COM  *	if (_sd_trace_mask & (f)) _sd_trace(f,cd,len,fba,flg,ret)
292*7836SJohn.Forte@Sun.COM  *  Build a trace entry and place it into the trace table.
293*7836SJohn.Forte@Sun.COM  */
294*7836SJohn.Forte@Sun.COM void
_sd_trace(int f,int cd,int len,nsc_off_t fba,int flg,int ret)295*7836SJohn.Forte@Sun.COM _sd_trace(int f, int cd, int len, nsc_off_t fba, int flg, int ret)
296*7836SJohn.Forte@Sun.COM {
297*7836SJohn.Forte@Sun.COM 	int tin;
298*7836SJohn.Forte@Sun.COM 	_sdtr_t *tp;
299*7836SJohn.Forte@Sun.COM 	_sdtr_table_t *t;
300*7836SJohn.Forte@Sun.COM 	kmutex_t *lk;
301*7836SJohn.Forte@Sun.COM 
302*7836SJohn.Forte@Sun.COM 	/* Watch out for negative error codes or simply bogus cd's */
303*7836SJohn.Forte@Sun.COM 
304*7836SJohn.Forte@Sun.COM 	if (cd < -1 || cd >= sdbc_max_devs) {
305*7836SJohn.Forte@Sun.COM 		/*
306*7836SJohn.Forte@Sun.COM 		 * no device trace buffer -- use SDT_INV_CD table?
307*7836SJohn.Forte@Sun.COM 		 */
308*7836SJohn.Forte@Sun.COM 		if ((t = _sd_trace_table[-1].tbl) == NULL)
309*7836SJohn.Forte@Sun.COM 			return;
310*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[-1].t_lock;
311*7836SJohn.Forte@Sun.COM 	} else {
312*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[cd].t_lock;
313*7836SJohn.Forte@Sun.COM 		if ((t = _sd_trace_table[cd].tbl) == NULL)
314*7836SJohn.Forte@Sun.COM 			return;
315*7836SJohn.Forte@Sun.COM 	}
316*7836SJohn.Forte@Sun.COM 
317*7836SJohn.Forte@Sun.COM 	if (!(t->tt_mask & f))
318*7836SJohn.Forte@Sun.COM 		return;	/* check per-device mask */
319*7836SJohn.Forte@Sun.COM 
320*7836SJohn.Forte@Sun.COM 	/*
321*7836SJohn.Forte@Sun.COM 	 * Don't overwrite if alert signaled (count lost instead)
322*7836SJohn.Forte@Sun.COM 	 * Locking only if 'trace_good' parameter set.
323*7836SJohn.Forte@Sun.COM 	 */
324*7836SJohn.Forte@Sun.COM 	if (t->tt_good) mutex_enter(lk);
325*7836SJohn.Forte@Sun.COM 	if (t->tt_alert && (t->tt_cnt >= t->tt_max)) {
326*7836SJohn.Forte@Sun.COM 		t->tt_lost++; /* lost during alert */
327*7836SJohn.Forte@Sun.COM 		if (t->tt_good) mutex_exit(lk);
328*7836SJohn.Forte@Sun.COM 		return;
329*7836SJohn.Forte@Sun.COM 	}
330*7836SJohn.Forte@Sun.COM 	t->tt_cnt++;	/* overwritten entries if (tt_cnt >= tt_max) */
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	tin = t->tt_in++;
333*7836SJohn.Forte@Sun.COM 	if (tin >= t->tt_max) tin = t->tt_in = 0;
334*7836SJohn.Forte@Sun.COM 	tp = &t->tt_buf[tin];
335*7836SJohn.Forte@Sun.COM 	tp->t_time = 0;		/* not filled in yet */
336*7836SJohn.Forte@Sun.COM 	if (t->tt_good) mutex_exit(lk);
337*7836SJohn.Forte@Sun.COM 
338*7836SJohn.Forte@Sun.COM 	tp->t_func = (ushort_t)f;
339*7836SJohn.Forte@Sun.COM 	tp->t_len = (ushort_t)len;
340*7836SJohn.Forte@Sun.COM 	tp->t_fba = fba;
341*7836SJohn.Forte@Sun.COM 	tp->t_flg = flg;
342*7836SJohn.Forte@Sun.COM 	tp->t_ret = ret;
343*7836SJohn.Forte@Sun.COM 	/*
344*7836SJohn.Forte@Sun.COM 	 * On LP64 systems we will only capture the low 32 bits of the
345*7836SJohn.Forte@Sun.COM 	 * time this really should be good enough for our purposes.
346*7836SJohn.Forte@Sun.COM 	 *
347*7836SJohn.Forte@Sun.COM 	 */
348*7836SJohn.Forte@Sun.COM 	if (t->tt_lbolt)
349*7836SJohn.Forte@Sun.COM 		tp->t_time = (int)nsc_lbolt();
350*7836SJohn.Forte@Sun.COM 	else
351*7836SJohn.Forte@Sun.COM 		tp->t_time = (int)nsc_usec();
352*7836SJohn.Forte@Sun.COM }
353*7836SJohn.Forte@Sun.COM 
354*7836SJohn.Forte@Sun.COM /*
355*7836SJohn.Forte@Sun.COM  * _sd_scan_alert -- search for device with trace alert
356*7836SJohn.Forte@Sun.COM  */
357*7836SJohn.Forte@Sun.COM static int
_sd_scan_alert(void)358*7836SJohn.Forte@Sun.COM _sd_scan_alert(void)
359*7836SJohn.Forte@Sun.COM {
360*7836SJohn.Forte@Sun.COM 	int cd;
361*7836SJohn.Forte@Sun.COM 
362*7836SJohn.Forte@Sun.COM 	XMEM(cd, _alert_cd);
363*7836SJohn.Forte@Sun.COM 	if ((cd != SDT_ANY_CD) && _sd_trace_table[cd].tbl->tt_alert)
364*7836SJohn.Forte@Sun.COM 		return (cd);
365*7836SJohn.Forte@Sun.COM 	for (cd = _last_cd + 1; cd < sdbc_max_devs; cd++)
366*7836SJohn.Forte@Sun.COM 		if (_sd_trace_table[cd].tbl &&
367*7836SJohn.Forte@Sun.COM 		    _sd_trace_table[cd].tbl->tt_alert)
368*7836SJohn.Forte@Sun.COM 			return (_last_cd = cd);
369*7836SJohn.Forte@Sun.COM 	for (cd = SDT_INV_CD; cd <= _last_cd; cd++)
370*7836SJohn.Forte@Sun.COM 		if (_sd_trace_table[cd].tbl &&
371*7836SJohn.Forte@Sun.COM 		    _sd_trace_table[cd].tbl->tt_alert)
372*7836SJohn.Forte@Sun.COM 			return (_last_cd = cd);
373*7836SJohn.Forte@Sun.COM 	return (SDT_ANY_CD);
374*7836SJohn.Forte@Sun.COM }
375*7836SJohn.Forte@Sun.COM 
376*7836SJohn.Forte@Sun.COM /*
377*7836SJohn.Forte@Sun.COM  * _sd_scan_entries -- search for next device with trace entries
378*7836SJohn.Forte@Sun.COM  */
379*7836SJohn.Forte@Sun.COM static int
_sd_scan_entries(void)380*7836SJohn.Forte@Sun.COM _sd_scan_entries(void)
381*7836SJohn.Forte@Sun.COM {
382*7836SJohn.Forte@Sun.COM 	int cd;
383*7836SJohn.Forte@Sun.COM 
384*7836SJohn.Forte@Sun.COM 	for (cd = _last_cd + 1; cd < sdbc_max_devs; cd++)
385*7836SJohn.Forte@Sun.COM 		if (_sd_trace_table[cd].tbl && _sd_trace_table[cd].tbl->tt_cnt)
386*7836SJohn.Forte@Sun.COM 			return (_last_cd = cd);
387*7836SJohn.Forte@Sun.COM 	for (cd = SDT_INV_CD; cd <= _last_cd; cd++)
388*7836SJohn.Forte@Sun.COM 		if (_sd_trace_table[cd].tbl && _sd_trace_table[cd].tbl->tt_cnt)
389*7836SJohn.Forte@Sun.COM 			return (_last_cd = cd);
390*7836SJohn.Forte@Sun.COM 	return (SDT_ANY_CD);
391*7836SJohn.Forte@Sun.COM }
392*7836SJohn.Forte@Sun.COM 
393*7836SJohn.Forte@Sun.COM 
394*7836SJohn.Forte@Sun.COM /*
395*7836SJohn.Forte@Sun.COM  * _sd_adump
396*7836SJohn.Forte@Sun.COM  *	copy information about new trace records to trace daemon,
397*7836SJohn.Forte@Sun.COM  *	or modify trace parameters.
398*7836SJohn.Forte@Sun.COM  *
399*7836SJohn.Forte@Sun.COM  * Some tracing parameters can be modified
400*7836SJohn.Forte@Sun.COM  * [Either per-device if cd specified, or the defaults if cd = SDT_ANY_CD]
401*7836SJohn.Forte@Sun.COM  *  SD_LOGSIZE:   table.tt_max (size for future opens)
402*7836SJohn.Forte@Sun.COM  *  SD_SET_LBOLT: table.tt_lbolt
403*7836SJohn.Forte@Sun.COM  *  SD_SET_MASK:  table.tt_mask
404*7836SJohn.Forte@Sun.COM  *  SD_SET_GOOD:  table.tt_good
405*7836SJohn.Forte@Sun.COM  *
406*7836SJohn.Forte@Sun.COM  * if (cd >= 0) dump specific device records;
407*7836SJohn.Forte@Sun.COM  * if (cd == SDT_INV_CD) dump records which don't apply to any one device.
408*7836SJohn.Forte@Sun.COM  * if (cd == SDT_ANY_CD), then choose a device:
409*7836SJohn.Forte@Sun.COM  *	1) most recent alert, block if (flag & SD_ALERT_WAIT)
410*7836SJohn.Forte@Sun.COM  *	2) "next" device with unprocessed records.
411*7836SJohn.Forte@Sun.COM  */
412*7836SJohn.Forte@Sun.COM int
_sd_adump(void * args,int * rvp)413*7836SJohn.Forte@Sun.COM _sd_adump(void *args, int *rvp)
414*7836SJohn.Forte@Sun.COM {
415*7836SJohn.Forte@Sun.COM 	struct a {
416*7836SJohn.Forte@Sun.COM 		long cd;
417*7836SJohn.Forte@Sun.COM 		_sdtr_table_t *table;
418*7836SJohn.Forte@Sun.COM 		_sdtr_t *buf;
419*7836SJohn.Forte@Sun.COM 		long size;
420*7836SJohn.Forte@Sun.COM 		long flag;
421*7836SJohn.Forte@Sun.COM 	} *uap = (struct a *)args;
422*7836SJohn.Forte@Sun.COM 	_sdtr_t *ubuf;
423*7836SJohn.Forte@Sun.COM 	_sdtr_table_t tt, *t;
424*7836SJohn.Forte@Sun.COM 	kmutex_t *lk;
425*7836SJohn.Forte@Sun.COM 	int cd, count, lost, new_cnt;
426*7836SJohn.Forte@Sun.COM 
427*7836SJohn.Forte@Sun.COM 	if (uap->flag & (SD_SET_SIZE|SD_SET_MASK|SD_SET_LBOLT|SD_SET_GOOD)) {
428*7836SJohn.Forte@Sun.COM 		return (_sd_set_adump(uap->cd, uap->flag, uap->table));
429*7836SJohn.Forte@Sun.COM 	}
430*7836SJohn.Forte@Sun.COM 	if (! _sd_trace_configed) {
431*7836SJohn.Forte@Sun.COM 		return (EINVAL); /* not initialized yet */
432*7836SJohn.Forte@Sun.COM 	}
433*7836SJohn.Forte@Sun.COM 	if (uap->cd >= SDT_INV_CD) {
434*7836SJohn.Forte@Sun.COM 		/* specific device: check if configured. dump current state. */
435*7836SJohn.Forte@Sun.COM 		if ((uap->cd > (long)sdbc_max_devs) ||
436*7836SJohn.Forte@Sun.COM 		    !(t = _sd_trace_table[uap->cd].tbl)) {
437*7836SJohn.Forte@Sun.COM 			return (ENOSPC); /* no space configured */
438*7836SJohn.Forte@Sun.COM 		}
439*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[uap->cd].t_lock;
440*7836SJohn.Forte@Sun.COM 		cd = uap->cd;
441*7836SJohn.Forte@Sun.COM 	} else {
442*7836SJohn.Forte@Sun.COM 		/*
443*7836SJohn.Forte@Sun.COM 		 * SDT_ANY_CD:
444*7836SJohn.Forte@Sun.COM 		 * SD_ALERT_WAIT - wait for alert
445*7836SJohn.Forte@Sun.COM 		 */
446*7836SJohn.Forte@Sun.COM 	scan:
447*7836SJohn.Forte@Sun.COM 		if ((cd = _sd_scan_alert()) != SDT_ANY_CD)
448*7836SJohn.Forte@Sun.COM 			goto dump;
449*7836SJohn.Forte@Sun.COM 		if ((uap->flag & SD_ALERT_WAIT)) {
450*7836SJohn.Forte@Sun.COM 			mutex_enter(&_sd_adump_lk);
451*7836SJohn.Forte@Sun.COM 			if (!_sd_trace_configed) {
452*7836SJohn.Forte@Sun.COM 				mutex_exit(&_sd_adump_lk);
453*7836SJohn.Forte@Sun.COM 				return (EINVAL);
454*7836SJohn.Forte@Sun.COM 			}
455*7836SJohn.Forte@Sun.COM 
456*7836SJohn.Forte@Sun.COM 			if (!cv_wait_sig(&_sd_adump_cv, &_sd_adump_lk)) {
457*7836SJohn.Forte@Sun.COM 				mutex_exit(&_sd_adump_lk);
458*7836SJohn.Forte@Sun.COM 				return (EINTR);
459*7836SJohn.Forte@Sun.COM 			}
460*7836SJohn.Forte@Sun.COM 			mutex_exit(&_sd_adump_lk);
461*7836SJohn.Forte@Sun.COM 
462*7836SJohn.Forte@Sun.COM 			if (!_sd_trace_configed || !_sd_cache_initialized) {
463*7836SJohn.Forte@Sun.COM 				return (EIDRM);
464*7836SJohn.Forte@Sun.COM 			}
465*7836SJohn.Forte@Sun.COM 			goto scan;
466*7836SJohn.Forte@Sun.COM 		}
467*7836SJohn.Forte@Sun.COM 		/* any device with entries */
468*7836SJohn.Forte@Sun.COM 		if ((cd = _sd_scan_entries()) == SDT_INV_CD)
469*7836SJohn.Forte@Sun.COM 			return (0);		/* no new entries */
470*7836SJohn.Forte@Sun.COM 
471*7836SJohn.Forte@Sun.COM 	dump:
472*7836SJohn.Forte@Sun.COM 		lk = _sd_trace_table[cd].t_lock;
473*7836SJohn.Forte@Sun.COM 		if ((t = _sd_trace_table[cd].tbl) == NULL) {
474*7836SJohn.Forte@Sun.COM 			if (uap->flag & SD_ALERT_WAIT) {
475*7836SJohn.Forte@Sun.COM 				t = _sd_trace_table[-1].tbl;
476*7836SJohn.Forte@Sun.COM 				lk = _sd_trace_table[-1].t_lock;
477*7836SJohn.Forte@Sun.COM 			} else {
478*7836SJohn.Forte@Sun.COM 				return (ENOSPC); /* no space configured */
479*7836SJohn.Forte@Sun.COM 			}
480*7836SJohn.Forte@Sun.COM 		}
481*7836SJohn.Forte@Sun.COM 	}
482*7836SJohn.Forte@Sun.COM 
483*7836SJohn.Forte@Sun.COM 	/*
484*7836SJohn.Forte@Sun.COM 	 * take a snapshot of the table state
485*7836SJohn.Forte@Sun.COM 	 */
486*7836SJohn.Forte@Sun.COM 	if (t->tt_good)
487*7836SJohn.Forte@Sun.COM 		mutex_enter(lk);
488*7836SJohn.Forte@Sun.COM 	tt = *t;
489*7836SJohn.Forte@Sun.COM 	if (t->tt_good)
490*7836SJohn.Forte@Sun.COM 		mutex_exit(lk);
491*7836SJohn.Forte@Sun.COM 
492*7836SJohn.Forte@Sun.COM 	/*
493*7836SJohn.Forte@Sun.COM 	 * copy trace log entries to daemon
494*7836SJohn.Forte@Sun.COM 	 *
495*7836SJohn.Forte@Sun.COM 	 * size:   entries in user-level 'buf'
496*7836SJohn.Forte@Sun.COM 	 * count:  how many entries to copy [force count <= size]
497*7836SJohn.Forte@Sun.COM 	 * tt_max: size of kernel buffer
498*7836SJohn.Forte@Sun.COM 	 * tt_cnt: written entries [lossage if tt_cnt > tt_max]
499*7836SJohn.Forte@Sun.COM 	 * cnt:    for wrap-around calculations
500*7836SJohn.Forte@Sun.COM 	 */
501*7836SJohn.Forte@Sun.COM 	if ((count = tt.tt_cnt) > tt.tt_max) { /* lost from beginning */
502*7836SJohn.Forte@Sun.COM 		tt.tt_out = tt.tt_in;
503*7836SJohn.Forte@Sun.COM 		count = tt.tt_max;
504*7836SJohn.Forte@Sun.COM 		lost = tt.tt_cnt - tt.tt_max;
505*7836SJohn.Forte@Sun.COM 	} else
506*7836SJohn.Forte@Sun.COM 		lost = 0;
507*7836SJohn.Forte@Sun.COM 	if (count <= 0)
508*7836SJohn.Forte@Sun.COM 		return (0);
509*7836SJohn.Forte@Sun.COM 	if ((long)count > uap->size)
510*7836SJohn.Forte@Sun.COM 		count = uap->size;
511*7836SJohn.Forte@Sun.COM 	ubuf = uap->buf;
512*7836SJohn.Forte@Sun.COM 	if ((tt.tt_out + count) > tt.tt_max) {
513*7836SJohn.Forte@Sun.COM 		int cnt = tt.tt_max - tt.tt_out;
514*7836SJohn.Forte@Sun.COM 		if (cnt > count)
515*7836SJohn.Forte@Sun.COM 			cnt = count;
516*7836SJohn.Forte@Sun.COM 		if (copyout(&(t->tt_buf[tt.tt_out]), ubuf,
517*7836SJohn.Forte@Sun.COM 		    cnt * sizeof (_sdtr_t))) {
518*7836SJohn.Forte@Sun.COM 			return (EFAULT);
519*7836SJohn.Forte@Sun.COM 		}
520*7836SJohn.Forte@Sun.COM 		ubuf += cnt;
521*7836SJohn.Forte@Sun.COM 		cnt = count - cnt;
522*7836SJohn.Forte@Sun.COM 		if (copyout(&(t->tt_buf[0]), ubuf, cnt * sizeof (_sdtr_t))) {
523*7836SJohn.Forte@Sun.COM 			return (EFAULT);
524*7836SJohn.Forte@Sun.COM 		}
525*7836SJohn.Forte@Sun.COM 		tt.tt_out = cnt;
526*7836SJohn.Forte@Sun.COM 	} else {
527*7836SJohn.Forte@Sun.COM 		if (copyout(&(t->tt_buf[tt.tt_out]), ubuf,
528*7836SJohn.Forte@Sun.COM 		    count * sizeof (_sdtr_t))) {
529*7836SJohn.Forte@Sun.COM 			return (EFAULT);
530*7836SJohn.Forte@Sun.COM 		}
531*7836SJohn.Forte@Sun.COM 		tt.tt_out += count;
532*7836SJohn.Forte@Sun.COM 		if (tt.tt_out == tt.tt_max)
533*7836SJohn.Forte@Sun.COM 			tt.tt_out = 0;
534*7836SJohn.Forte@Sun.COM 	}
535*7836SJohn.Forte@Sun.COM 
536*7836SJohn.Forte@Sun.COM 	/*
537*7836SJohn.Forte@Sun.COM 	 * tt_alert uses fuzzy counting.
538*7836SJohn.Forte@Sun.COM 	 * if multiple alerts signaled, leave it at 1.
539*7836SJohn.Forte@Sun.COM 	 */
540*7836SJohn.Forte@Sun.COM 	if (t->tt_alert)
541*7836SJohn.Forte@Sun.COM 		t->tt_alert = (t->tt_alert > 1) ? 1 : 0;
542*7836SJohn.Forte@Sun.COM 
543*7836SJohn.Forte@Sun.COM 	/*
544*7836SJohn.Forte@Sun.COM 	 * tt_cntout is tt_cnt after dump
545*7836SJohn.Forte@Sun.COM 	 * update tt_cnt for copied entries
546*7836SJohn.Forte@Sun.COM 	 */
547*7836SJohn.Forte@Sun.COM 	if (t->tt_good)
548*7836SJohn.Forte@Sun.COM 		mutex_enter(lk);
549*7836SJohn.Forte@Sun.COM 	tt.tt_cntout = t->tt_cnt;
550*7836SJohn.Forte@Sun.COM 	t->tt_out = tt.tt_out;
551*7836SJohn.Forte@Sun.COM 	new_cnt = t->tt_cnt;
552*7836SJohn.Forte@Sun.COM 	if ((new_cnt -= count+lost) < 0)
553*7836SJohn.Forte@Sun.COM 		new_cnt = 0;
554*7836SJohn.Forte@Sun.COM 	t->tt_cnt = new_cnt;	/* race with new traces if not "tt_good" */
555*7836SJohn.Forte@Sun.COM 	if (t->tt_good)
556*7836SJohn.Forte@Sun.COM 		mutex_exit(lk);
557*7836SJohn.Forte@Sun.COM 
558*7836SJohn.Forte@Sun.COM 	if (copyout(&tt, uap->table, sizeof (tt) - sizeof (_sdtr_t))) {
559*7836SJohn.Forte@Sun.COM 		return (EFAULT);
560*7836SJohn.Forte@Sun.COM 	}
561*7836SJohn.Forte@Sun.COM 	*rvp = count;
562*7836SJohn.Forte@Sun.COM 
563*7836SJohn.Forte@Sun.COM 	first_alert = 0;
564*7836SJohn.Forte@Sun.COM 	return (0);
565*7836SJohn.Forte@Sun.COM }
566*7836SJohn.Forte@Sun.COM 
567*7836SJohn.Forte@Sun.COM 
568*7836SJohn.Forte@Sun.COM /* set size, mask, lbolt, or good(locks) */
569*7836SJohn.Forte@Sun.COM static int
_sd_set_adump(int cd,int flag,_sdtr_table_t * table)570*7836SJohn.Forte@Sun.COM _sd_set_adump(int cd, int flag, _sdtr_table_t *table)
571*7836SJohn.Forte@Sun.COM {
572*7836SJohn.Forte@Sun.COM 	_sdtr_table_t tt, *t;
573*7836SJohn.Forte@Sun.COM 
574*7836SJohn.Forte@Sun.COM 	if (copyin(table, &tt, sizeof (tt) - sizeof (_sdtr_t))) {
575*7836SJohn.Forte@Sun.COM 		return (EFAULT);
576*7836SJohn.Forte@Sun.COM 	}
577*7836SJohn.Forte@Sun.COM 	if (cd == SDT_ANY_CD) {		/* modify config parameter */
578*7836SJohn.Forte@Sun.COM 		if (flag & SD_SET_SIZE)
579*7836SJohn.Forte@Sun.COM 			_sd_cache_config.trace_size = tt.tt_max;
580*7836SJohn.Forte@Sun.COM 		if (flag & SD_SET_MASK) {
581*7836SJohn.Forte@Sun.COM 			_sd_cache_config.trace_mask = tt.tt_mask;
582*7836SJohn.Forte@Sun.COM 			/* explicitly set global mask, not bitwise or */
583*7836SJohn.Forte@Sun.COM 			_sd_trace_mask = tt.tt_mask;
584*7836SJohn.Forte@Sun.COM 		}
585*7836SJohn.Forte@Sun.COM 		if (flag & SD_SET_LBOLT)
586*7836SJohn.Forte@Sun.COM 			_sd_cache_config.trace_lbolt = tt.tt_lbolt;
587*7836SJohn.Forte@Sun.COM 		if (flag & SD_SET_GOOD)
588*7836SJohn.Forte@Sun.COM 			_sd_cache_config.trace_good = tt.tt_good;
589*7836SJohn.Forte@Sun.COM 		return (0);
590*7836SJohn.Forte@Sun.COM 	}
591*7836SJohn.Forte@Sun.COM 	if (flag & SD_SET_SIZE)
592*7836SJohn.Forte@Sun.COM 		_sd_cache_config.trace_size = tt.tt_max;
593*7836SJohn.Forte@Sun.COM 	/* modify particular device parameters */
594*7836SJohn.Forte@Sun.COM 	if (!_sd_trace_table[cd].tbl)
595*7836SJohn.Forte@Sun.COM 		(void) _sdbc_tr_configure(cd);
596*7836SJohn.Forte@Sun.COM 	if ((t = _sd_trace_table[cd].tbl) == NULL)
597*7836SJohn.Forte@Sun.COM 		return (0);
598*7836SJohn.Forte@Sun.COM 	if (flag & SD_SET_MASK) {
599*7836SJohn.Forte@Sun.COM 		t->tt_mask = tt.tt_mask;
600*7836SJohn.Forte@Sun.COM 		_sd_trace_mask |= tt.tt_mask; /* or-ed with global mask */
601*7836SJohn.Forte@Sun.COM 	}
602*7836SJohn.Forte@Sun.COM 	if (flag & SD_SET_LBOLT)
603*7836SJohn.Forte@Sun.COM 		t->tt_lbolt = tt.tt_lbolt;
604*7836SJohn.Forte@Sun.COM 	if (flag & SD_SET_GOOD)
605*7836SJohn.Forte@Sun.COM 		t->tt_good = tt.tt_good;
606*7836SJohn.Forte@Sun.COM 	if (copyout(t, table, sizeof (*t) - sizeof (_sdtr_t))) {
607*7836SJohn.Forte@Sun.COM 		return (EFAULT);
608*7836SJohn.Forte@Sun.COM 	}
609*7836SJohn.Forte@Sun.COM 	return (0);
610*7836SJohn.Forte@Sun.COM }
611*7836SJohn.Forte@Sun.COM 
612*7836SJohn.Forte@Sun.COM #else /* ! _SD_NOTRACE */
613*7836SJohn.Forte@Sun.COM 
_sd_adump()614*7836SJohn.Forte@Sun.COM int _sd_adump() 	{ return (ENOSYS); }
_sdbc_tr_load(void)615*7836SJohn.Forte@Sun.COM int _sdbc_tr_load(void) 	{ return (0); }
_sdbc_tr_configure(void)616*7836SJohn.Forte@Sun.COM int _sdbc_tr_configure(void) 	{ return (0); }
_sdbc_tr_deconfigure(void)617*7836SJohn.Forte@Sun.COM void _sdbc_tr_deconfigure(void)	{ return; }
_sdbc_tr_unload(void)618*7836SJohn.Forte@Sun.COM void _sdbc_tr_unload(void) { return; }
619*7836SJohn.Forte@Sun.COM 
620*7836SJohn.Forte@Sun.COM #endif /* ! _SD_NOTRACE */
621