4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/isa_defs.h>
28 #include <sys/systeminfo.h>
29 #include <sys/scsi/generic/smp_frames.h>
41 #include <scsi/libsmp.h>
44 static pthread_mutex_t _libsmp_lock
= PTHREAD_MUTEX_INITIALIZER
;
45 static smp_engine_t
*_libsmp_engines
;
46 static int _libsmp_refcnt
;
48 static boolean_t _libsmp_engine_dlclose
;
51 smp_engine_free(smp_engine_t
*ep
)
56 smp_free(ep
->se_name
);
61 smp_engine_destroy(smp_engine_t
*ep
)
65 ASSERT(MUTEX_HELD(&_libsmp_lock
));
67 if (ep
->se_fini
!= NULL
)
70 if (_libsmp_engine_dlclose
)
71 (void) dlclose(ep
->se_object
);
73 ASSERT(ep
->se_refcnt
== 0);
74 for (pp
= &_libsmp_engines
; *pp
!= NULL
; pp
= &((*pp
)->se_next
))
87 (void) pthread_mutex_lock(&_libsmp_lock
);
89 (void) pthread_mutex_unlock(&_libsmp_lock
);
97 (void) pthread_mutex_lock(&_libsmp_lock
);
98 ASSERT(_libsmp_refcnt
> 0);
99 if (--_libsmp_refcnt
== 0) {
100 while (_libsmp_engines
!= NULL
) {
101 ep
= _libsmp_engines
;
102 _libsmp_engines
= ep
->se_next
;
103 smp_engine_destroy(ep
);
106 (void) pthread_mutex_unlock(&_libsmp_lock
);
110 smp_engine_loadone(const char *path
)
115 ASSERT(MUTEX_HELD(&_libsmp_lock
));
117 if ((obj
= dlopen(path
, RTLD_PARENT
| RTLD_LOCAL
| RTLD_LAZY
)) == NULL
)
118 return (smp_set_errno(ESMP_NOENGINE
));
120 if ((ep
= smp_zalloc(sizeof (smp_engine_t
))) == NULL
) {
126 ep
->se_init
= (int (*)())dlsym(obj
, "_smp_init");
127 ep
->se_fini
= (void (*)())dlsym(obj
, "_smp_fini");
129 if (ep
->se_init
== NULL
) {
131 return (smp_set_errno(ESMP_BADENGINE
));
134 if (ep
->se_init(ep
) != 0) {
143 smp_engine_register(smp_engine_t
*ep
, int version
,
144 const smp_engine_config_t
*ecp
)
146 ASSERT(MUTEX_HELD(&_libsmp_lock
));
148 if (version
!= LIBSMP_ENGINE_VERSION
)
149 return (smp_set_errno(ESMP_VERSION
));
151 ep
->se_ops
= ecp
->sec_ops
;
152 ep
->se_name
= smp_strdup(ecp
->sec_name
);
154 if (ep
->se_name
== NULL
)
157 ep
->se_next
= _libsmp_engines
;
158 _libsmp_engines
= ep
;
163 static smp_engine_t
*
164 smp_engine_hold_cached(const char *name
)
168 ASSERT(MUTEX_HELD(&_libsmp_lock
));
170 for (ep
= _libsmp_engines
; ep
!= NULL
; ep
= ep
->se_next
) {
171 if (strcmp(ep
->se_name
, name
) == 0) {
177 (void) smp_set_errno(ESMP_NOENGINE
);
181 static smp_engine_t
*
182 smp_engine_hold(const char *name
)
185 const char *pluginpath
, *p
, *q
;
186 char pluginroot
[PATH_MAX
];
190 (void) pthread_mutex_lock(&_libsmp_lock
);
191 ep
= smp_engine_hold_cached(name
);
193 (void) pthread_mutex_unlock(&_libsmp_lock
);
203 if ((pluginpath
= getenv("SMP_PLUGINPATH")) == NULL
)
204 pluginpath
= LIBSMP_DEFAULT_PLUGINDIR
;
206 _libsmp_engine_dlclose
= (getenv("SMP_NODLCLOSE") == NULL
);
208 for (p
= pluginpath
; p
!= NULL
; p
= q
) {
209 if ((q
= strchr(p
, ':')) != NULL
) {
210 ptrdiff_t len
= q
- p
;
211 (void) strncpy(pluginroot
, p
, len
);
212 pluginroot
[len
] = '\0';
220 (void) strcpy(pluginroot
, p
);
223 if (pluginroot
[0] != '/')
226 (void) snprintf(path
, PATH_MAX
, "%s/%s/%s/%s%s",
227 pluginroot
, LIBSMP_PLUGIN_ENGINE
,
228 isa
, name
, LIBSMP_PLUGIN_EXT
);
230 if (smp_engine_loadone(path
) == 0) {
231 ep
= smp_engine_hold_cached(name
);
232 (void) pthread_mutex_unlock(&_libsmp_lock
);
241 smp_engine_rele(smp_engine_t
*ep
)
243 (void) pthread_mutex_lock(&_libsmp_lock
);
244 ASSERT(ep
->se_refcnt
> 0);
246 (void) pthread_mutex_unlock(&_libsmp_lock
);
250 smp_parse_mtbf(const char *envvar
, uint_t
*intp
)
255 if ((strval
= getenv(envvar
)) != NULL
&&
256 (intval
= atoi(strval
)) > 0) {
257 srand48(gethrtime());
263 smp_open(const smp_target_def_t
*tdp
)
270 if ((engine
= tdp
->std_engine
) == NULL
) {
271 if ((engine
= getenv("LIBSMP_DEFAULT_ENGINE")) == NULL
)
272 engine
= LIBSMP_DEFAULT_ENGINE
;
275 if ((ep
= smp_engine_hold(engine
)) == NULL
)
278 if ((tp
= smp_zalloc(sizeof (smp_target_t
))) == NULL
) {
283 if ((private = ep
->se_ops
->seo_open(tdp
->std_def
)) == NULL
) {
289 smp_parse_mtbf("LIBSMP_MTBF_REQUEST", &tp
->st_mtbf_request
);
290 smp_parse_mtbf("LIBSMP_MTBF_RESPONSE", &tp
->st_mtbf_response
);
293 tp
->st_priv
= private;
295 if (smp_plugin_load(tp
) != 0) {
304 smp_target_name(const smp_target_t
*tp
, char *buf
, size_t len
)
306 tp
->st_engine
->se_ops
->seo_target_name(tp
->st_priv
, buf
, len
);
310 smp_target_addr(const smp_target_t
*tp
)
312 return (tp
->st_engine
->se_ops
->seo_target_addr(tp
->st_priv
));
316 smp_target_vendor(const smp_target_t
*tp
)
318 return (tp
->st_vendor
);
322 smp_target_product(const smp_target_t
*tp
)
324 return (tp
->st_product
);
328 smp_target_revision(const smp_target_t
*tp
)
330 return (tp
->st_revision
);
334 smp_target_component_vendor(const smp_target_t
*tp
)
336 return (tp
->st_component_vendor
);
340 smp_target_component_id(const smp_target_t
*tp
)
342 return (tp
->st_component_id
);
346 smp_target_component_revision(const smp_target_t
*tp
)
348 return (tp
->st_component_revision
);
352 smp_target_getcap(const smp_target_t
*tp
)
356 if (tp
->st_repgen
.srgr_long_response
)
357 cap
|= SMP_TARGET_C_LONG_RESP
;
359 if (tp
->st_repgen
.srgr_zoning_supported
)
360 cap
|= SMP_TARGET_C_ZONING
;
362 if (tp
->st_repgen
.srgr_number_of_zone_grps
== SMP_ZONE_GROUPS_256
)
363 cap
|= SMP_TARGET_C_ZG_256
;
369 smp_target_set_change_count(smp_target_t
*tp
, uint16_t cc
)
371 tp
->st_change_count
= cc
;
375 smp_target_get_change_count(const smp_target_t
*tp
)
377 return (tp
->st_change_count
);
381 smp_target_get_number_of_phys(const smp_target_t
*tp
)
383 return (tp
->st_repgen
.srgr_number_of_phys
);
387 smp_target_get_exp_route_indexes(const smp_target_t
*tp
)
389 return (tp
->st_repgen
.srgr_exp_route_indexes
);
393 smp_close(smp_target_t
*tp
)
395 smp_free(tp
->st_vendor
);
396 smp_free(tp
->st_product
);
397 smp_free(tp
->st_revision
);
398 smp_free(tp
->st_component_vendor
);
400 smp_plugin_unload(tp
);
402 tp
->st_engine
->se_ops
->seo_close(tp
->st_priv
);
403 smp_engine_rele(tp
->st_engine
);
409 * Set the timeout in seconds for this action. If no timeout is specified
410 * or if the timeout is set to 0, an implementation-specific timeout will be
411 * used (which may vary based on the target, command or other variables).
412 * Not all engines support all timeout values. Setting the timeout to a value
413 * not supported by the engine will cause engine-defined behavior when the
414 * action is executed.
417 smp_action_set_timeout(smp_action_t
*ap
, uint32_t timeout
)
419 ap
->sa_timeout
= timeout
;
423 * Obtain the timeout setting for this action.
426 smp_action_get_timeout(const smp_action_t
*ap
)
428 return (ap
->sa_timeout
);
431 const smp_function_def_t
*
432 smp_action_get_function_def(const smp_action_t
*ap
)
438 * Obtain the user-requested request allocation size. Note that the
439 * interpretation of this is function-dependent.
442 smp_action_get_rqsd(const smp_action_t
*ap
)
444 return (ap
->sa_request_rqsd
);
448 * Obtains the address and amount of space allocated for the portion of the
449 * request data that lies between the header (if any) and the CRC.
452 smp_action_get_request(const smp_action_t
*ap
, void **reqp
, size_t *dlenp
)
455 if (ap
->sa_request_data_off
>= 0) {
456 *reqp
= ap
->sa_request
+ ap
->sa_request_data_off
;
463 *dlenp
= ap
->sa_request_alloc_len
-
464 (ap
->sa_request_data_off
+ sizeof (smp_crc_t
));
468 * Obtains the address and amount of valid response data (that part of the
469 * response frame, if any, that lies between the header and the CRC). The
470 * result, if any, is also returned in the location pointed to by result.
473 smp_action_get_response(const smp_action_t
*ap
, smp_result_t
*resultp
,
474 void **respp
, size_t *dlenp
)
477 *resultp
= ap
->sa_result
;
480 *respp
= (ap
->sa_response_data_len
> 0) ?
481 (ap
->sa_response
+ ap
->sa_response_data_off
) : NULL
;
484 *dlenp
= ap
->sa_response_data_len
;
488 * Obtains the entire request frame and the amount of space allocated for it.
489 * This is intended only for use by plugins; front-end consumers should use
490 * smp_action_get_request() instead.
493 smp_action_get_request_frame(const smp_action_t
*ap
, void **reqp
, size_t *alenp
)
496 *reqp
= ap
->sa_request
;
499 *alenp
= ap
->sa_request_alloc_len
;
503 * Obtains the entire response frame and the amount of space allocated for it.
504 * This is intended only for use by plugins; front-end consumers should use
505 * smp_action_get_response() instead.
508 smp_action_get_response_frame(const smp_action_t
*ap
,
509 void **respp
, size_t *lenp
)
512 *respp
= ap
->sa_response
;
515 if (ap
->sa_flags
& SMP_ACTION_F_EXEC
)
516 *lenp
= ap
->sa_response_engine_len
;
518 *lenp
= ap
->sa_response_alloc_len
;
523 * Set the total response frame length as determined by the engine. This
524 * should never be called by consumers or plugins other than engines.
527 smp_action_set_response_len(smp_action_t
*ap
, size_t elen
)
529 ap
->sa_response_engine_len
= elen
;
533 smp_action_set_result(smp_action_t
*ap
, smp_result_t result
)
535 ap
->sa_result
= result
;
539 * Allocate an action object. The object will contain a request buffer
540 * to hold the frame to be transmitted to the target, a response buffer
541 * for the frame to be received from it, and auxiliary private information.
543 * For the request, callers may specify:
545 * - An externally-allocated buffer and its size in bytes, or
546 * - NULL and a function-specific size descriptor, or
548 * Note that for some functions, the size descriptor may be 0, indicating that
549 * a default buffer length will be used. It is the caller's responsibility
550 * to correctly interpret function-specific buffer lengths. See appropriate
551 * plugin documentation for information on buffer sizes and buffer content
554 * For the response, callers may specify:
556 * - An externally-allocated buffer and its size in bytes, or
557 * - NULL and 0, to use a guaranteed-sufficient buffer.
559 * If an invalid request size descriptor is provided, or a preallocated
560 * buffer is provided and it is insufficiently large, this function will
561 * fail with ESMP_RANGE.
563 * Callers are discouraged from allocating their own buffers and must be
564 * aware of the consequences of specifying non-default lengths.
567 smp_action_xalloc(smp_function_t fn
, smp_target_t
*tp
,
568 void *rq
, size_t rqsd
, void *rs
, size_t rslen
)
571 const smp_function_def_t
*dp
= NULL
;
578 cap
= smp_target_getcap(tp
);
580 for (pp
= tp
->st_plugin_first
; pp
!= NULL
; pp
= pp
->sp_next
) {
581 if (pp
->sp_functions
== NULL
)
584 for (i
= 0; pp
->sp_functions
[i
].sfd_rq_len
!= NULL
; i
++) {
585 dp
= &pp
->sp_functions
[i
];
586 if (dp
->sfd_function
== fn
&&
587 ((cap
& dp
->sfd_capmask
) == dp
->sfd_capset
))
593 (void) smp_set_errno(ESMP_BADFUNC
);
598 if ((rqlen
= dp
->sfd_rq_len(rqsd
, tp
)) == 0)
600 } else if (rqlen
< SMP_REQ_MINLEN
) {
601 (void) smp_set_errno(ESMP_RANGE
);
606 rslen
= 1020 + SMP_RESP_MINLEN
;
607 } else if (rslen
< SMP_RESP_MINLEN
) {
608 (void) smp_set_errno(ESMP_RANGE
);
612 len
= offsetof(smp_action_t
, sa_buf
[0]);
618 if ((ap
= smp_zalloc(len
)) == NULL
)
625 ap
->sa_request
= alloc
;
628 ap
->sa_request_alloc_len
= rqlen
;
631 ap
->sa_response
= alloc
;
634 ap
->sa_response_alloc_len
= rslen
;
636 ASSERT(alloc
- (uint8_t *)ap
== len
);
638 ap
->sa_request_data_off
= dp
->sfd_rq_dataoff(ap
, tp
);
639 ap
->sa_flags
|= SMP_ACTION_F_OFFSET
;
645 * Simplified action allocator. All buffers are allocated for the
646 * caller. The request buffer size will be based on the function-specific
647 * interpretation of the rqsize parameter. The response buffer size will be
648 * a function-specific value sufficiently large to capture any response.
651 smp_action_alloc(smp_function_t fn
, smp_target_t
*tp
, size_t rqsd
)
653 return (smp_action_xalloc(fn
, tp
, NULL
, rqsd
, NULL
, 0));
657 smp_action_free(smp_action_t
*ap
)
666 * For testing purposes, we allow data to be corrupted via an environment
667 * variable setting. This helps ensure that higher level software can cope with
668 * arbitrarily broken targets. The mtbf value represents the number of bytes we
669 * will see, on average, in between each failure. Therefore, for each N bytes,
670 * we would expect to see (N / mtbf) bytes of corruption.
673 smp_inject_errors(void *data
, size_t len
, uint_t mtbf
)
682 prob
= (double)len
/ mtbf
;
685 index
= lrand48() % len
;
686 buf
[index
] = (lrand48() % 256);
690 if (drand48() <= prob
) {
691 index
= lrand48() % len
;
692 buf
[index
] = (lrand48() % 256);
697 smp_exec(smp_action_t
*ap
, smp_target_t
*tp
)
699 const smp_function_def_t
*dp
;
703 dp
->sfd_rq_setframe(ap
, tp
);
705 if (tp
->st_mtbf_request
!= 0) {
706 smp_inject_errors(ap
->sa_request
, ap
->sa_request_alloc_len
,
707 tp
->st_mtbf_request
);
710 ret
= tp
->st_engine
->se_ops
->seo_exec(tp
->st_priv
, ap
);
712 if (ret
== 0 && tp
->st_mtbf_response
!= 0) {
713 smp_inject_errors(ap
->sa_response
, ap
->sa_response_engine_len
,
714 tp
->st_mtbf_response
);
720 ap
->sa_flags
|= SMP_ACTION_F_EXEC
;
723 * Obtain the data length and offset from the underlying plugins.
724 * Then offer the plugins the opportunity to set any parameters in the
725 * target to reflect state observed in the response.
727 ap
->sa_response_data_len
= dp
->sfd_rs_datalen(ap
, tp
);
728 ap
->sa_response_data_off
= dp
->sfd_rs_dataoff(ap
, tp
);
729 dp
->sfd_rs_getparams(ap
, tp
);
731 ap
->sa_flags
|= SMP_ACTION_F_DECODE
;