xref: /titanic_44/usr/src/lib/scsi/libsmp/common/smp_plugin.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1ac88567aSHyon Kim /*
2ac88567aSHyon Kim  * CDDL HEADER START
3ac88567aSHyon Kim  *
4ac88567aSHyon Kim  * The contents of this file are subject to the terms of the
5ac88567aSHyon Kim  * Common Development and Distribution License (the "License").
6ac88567aSHyon Kim  * You may not use this file except in compliance with the License.
7ac88567aSHyon Kim  *
8ac88567aSHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ac88567aSHyon Kim  * or http://www.opensolaris.org/os/licensing.
10ac88567aSHyon Kim  * See the License for the specific language governing permissions
11ac88567aSHyon Kim  * and limitations under the License.
12ac88567aSHyon Kim  *
13ac88567aSHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
14ac88567aSHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ac88567aSHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
16ac88567aSHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
17ac88567aSHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
18ac88567aSHyon Kim  *
19ac88567aSHyon Kim  * CDDL HEADER END
20ac88567aSHyon Kim  */
21ac88567aSHyon Kim 
22ac88567aSHyon Kim /*
23ac88567aSHyon Kim  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24ac88567aSHyon Kim  */
25ac88567aSHyon Kim 
26ac88567aSHyon Kim #include <sys/types.h>
27ac88567aSHyon Kim #include <sys/systeminfo.h>
28ac88567aSHyon Kim #include <sys/scsi/generic/commands.h>
29ac88567aSHyon Kim #include <sys/scsi/impl/commands.h>
30ac88567aSHyon Kim 
31ac88567aSHyon Kim #include <scsi/libsmp.h>
32ac88567aSHyon Kim #include <scsi/libsmp_plugin.h>
33ac88567aSHyon Kim 
34ac88567aSHyon Kim #include <dlfcn.h>
35ac88567aSHyon Kim #include <link.h>
36ac88567aSHyon Kim #include <dirent.h>
37ac88567aSHyon Kim #include <string.h>
38ac88567aSHyon Kim #include <strings.h>
39ac88567aSHyon Kim #include <limits.h>
40ac88567aSHyon Kim 
41ac88567aSHyon Kim #include "smp_impl.h"
42ac88567aSHyon Kim 
43ac88567aSHyon Kim static boolean_t _libsmp_plugin_dlclose;
44ac88567aSHyon Kim 
45ac88567aSHyon Kim /*
46ac88567aSHyon Kim  * As part of basic initialization, we always retrieve the REPORT GENERAL
47ac88567aSHyon Kim  * data so that we will know whether this target supports the long response
48ac88567aSHyon Kim  * format.
49ac88567aSHyon Kim  */
50ac88567aSHyon Kim static int
smp_report_general(smp_target_t * tp)51ac88567aSHyon Kim smp_report_general(smp_target_t *tp)
52ac88567aSHyon Kim {
53ac88567aSHyon Kim 	smp_action_t *ap;
54ac88567aSHyon Kim 	smp_report_general_resp_t *rp;
55ac88567aSHyon Kim 	smp_result_t result;
56ac88567aSHyon Kim 	size_t len;
57ac88567aSHyon Kim 
58ac88567aSHyon Kim 	if ((ap = smp_action_alloc(SMP_FUNC_REPORT_GENERAL, tp, 0)) == NULL)
59ac88567aSHyon Kim 		return (-1);
60ac88567aSHyon Kim 
61ac88567aSHyon Kim 	if (smp_exec(ap, tp) != 0) {
62ac88567aSHyon Kim 		smp_action_free(ap);
63ac88567aSHyon Kim 		return (smp_set_errno(ESMP_REPGEN_FAILED));
64ac88567aSHyon Kim 	}
65ac88567aSHyon Kim 
66ac88567aSHyon Kim 	smp_action_get_response(ap, &result, (void **)&rp, &len);
67ac88567aSHyon Kim 
68ac88567aSHyon Kim 	if (result != SMP_RES_FUNCTION_ACCEPTED || len < 24) {
69ac88567aSHyon Kim 		smp_action_free(ap);
70ac88567aSHyon Kim 		return (smp_set_errno(ESMP_REPGEN_FAILED));
71ac88567aSHyon Kim 	}
72ac88567aSHyon Kim 
73ac88567aSHyon Kim 	bcopy(rp, &tp->st_repgen, sizeof (tp->st_repgen));
74ac88567aSHyon Kim 
75ac88567aSHyon Kim 	smp_action_free(ap);
76ac88567aSHyon Kim 
77ac88567aSHyon Kim 	return (0);
78ac88567aSHyon Kim }
79ac88567aSHyon Kim 
80ac88567aSHyon Kim static int
smp_report_manufacturer_information(smp_target_t * tp)81ac88567aSHyon Kim smp_report_manufacturer_information(smp_target_t *tp)
82ac88567aSHyon Kim {
83ac88567aSHyon Kim 	smp_action_t *ap;
84ac88567aSHyon Kim 	smp_report_manufacturer_info_resp_t *rp;
85ac88567aSHyon Kim 	smp_result_t result;
86ac88567aSHyon Kim 	size_t len;
87ac88567aSHyon Kim 
88ac88567aSHyon Kim 	ap = smp_action_alloc(SMP_FUNC_REPORT_MANUFACTURER_INFO, tp, 0);
89ac88567aSHyon Kim 	if (ap == NULL)
90ac88567aSHyon Kim 		return (-1);
91ac88567aSHyon Kim 
92ac88567aSHyon Kim 	if (smp_exec(ap, tp) != 0) {
93ac88567aSHyon Kim 		smp_action_free(ap);
94ac88567aSHyon Kim 		return (smp_set_errno(ESMP_REPGEN_FAILED));
95ac88567aSHyon Kim 	}
96ac88567aSHyon Kim 
97ac88567aSHyon Kim 	smp_action_get_response(ap, &result, (void **)&rp, &len);
98ac88567aSHyon Kim 
99ac88567aSHyon Kim 	if (result != SMP_RES_FUNCTION_ACCEPTED ||
100ac88567aSHyon Kim 	    len != sizeof (smp_report_manufacturer_info_resp_t)) {
101ac88567aSHyon Kim 		smp_action_free(ap);
102ac88567aSHyon Kim 		return (0);	/* Not supported */
103ac88567aSHyon Kim 	}
104ac88567aSHyon Kim 
105ac88567aSHyon Kim 	tp->st_vendor = smp_trim_strdup(rp->srmir_vendor_identification,
106ac88567aSHyon Kim 	    sizeof (rp->srmir_vendor_identification));
107ac88567aSHyon Kim 	tp->st_product = smp_trim_strdup(rp->srmir_product_identification,
108ac88567aSHyon Kim 	    sizeof (rp->srmir_product_identification));
109ac88567aSHyon Kim 	tp->st_revision = smp_trim_strdup(rp->srmir_product_revision_level,
110ac88567aSHyon Kim 	    sizeof (rp->srmir_product_revision_level));
111ac88567aSHyon Kim 
112ac88567aSHyon Kim 	if (rp->srmir_sas_1_1_format) {
113ac88567aSHyon Kim 		tp->st_component_vendor =
114ac88567aSHyon Kim 		    smp_trim_strdup(rp->srmir_component_vendor_identification,
115ac88567aSHyon Kim 		    sizeof (rp->srmir_component_vendor_identification));
116ac88567aSHyon Kim 
117ac88567aSHyon Kim 		tp->st_component_id = SCSI_READ16(&rp->srmir_component_id);
118ac88567aSHyon Kim 		tp->st_component_revision = rp->srmir_component_revision_level;
119ac88567aSHyon Kim 	}
120ac88567aSHyon Kim 
121ac88567aSHyon Kim 	if (tp->st_vendor == NULL || tp->st_product == NULL ||
122ac88567aSHyon Kim 	    tp->st_revision == NULL ||
123ac88567aSHyon Kim 	    (rp->srmir_sas_1_1_format && tp->st_component_vendor == NULL)) {
124ac88567aSHyon Kim 		smp_action_free(ap);
125ac88567aSHyon Kim 		return (smp_set_errno(ESMP_NOMEM));
126ac88567aSHyon Kim 	}
127ac88567aSHyon Kim 
128ac88567aSHyon Kim 	smp_action_free(ap);
129ac88567aSHyon Kim 
130ac88567aSHyon Kim 	return (0);
131ac88567aSHyon Kim }
132ac88567aSHyon Kim 
133ac88567aSHyon Kim static int
smp_target_fill(smp_target_t * tp)134ac88567aSHyon Kim smp_target_fill(smp_target_t *tp)
135ac88567aSHyon Kim {
136ac88567aSHyon Kim 	if (smp_report_general(tp) != 0 ||
137ac88567aSHyon Kim 	    smp_report_manufacturer_information(tp) != 0)
138ac88567aSHyon Kim 		return (-1);
139ac88567aSHyon Kim 
140ac88567aSHyon Kim 	return (0);
141ac88567aSHyon Kim }
142ac88567aSHyon Kim 
143ac88567aSHyon Kim const smp_function_def_t *
smp_get_funcdef(smp_target_t * tp,int fn)144ac88567aSHyon Kim smp_get_funcdef(smp_target_t *tp, int fn)
145ac88567aSHyon Kim {
146ac88567aSHyon Kim 	smp_plugin_t *pp;
147ac88567aSHyon Kim 	const smp_function_def_t *dp;
148ac88567aSHyon Kim 
149ac88567aSHyon Kim 	for (pp = tp->st_plugin_first; pp != NULL; pp = pp->sp_next) {
150ac88567aSHyon Kim 		if (pp->sp_functions == NULL)
151ac88567aSHyon Kim 			continue;
152ac88567aSHyon Kim 
153ac88567aSHyon Kim 		for (dp = &pp->sp_functions[0]; dp->sfd_rq_len != NULL; dp++) {
154ac88567aSHyon Kim 			if (dp->sfd_function == fn)
155ac88567aSHyon Kim 				return (dp);
156ac88567aSHyon Kim 		}
157ac88567aSHyon Kim 	}
158ac88567aSHyon Kim 
159ac88567aSHyon Kim 	(void) smp_error(ESMP_BADFUNC, "failed to find function 0x%x", fn);
160ac88567aSHyon Kim 	return (NULL);
161ac88567aSHyon Kim }
162ac88567aSHyon Kim 
163ac88567aSHyon Kim int
smp_plugin_register(smp_plugin_t * pp,int version,const smp_plugin_config_t * pcp)164ac88567aSHyon Kim smp_plugin_register(smp_plugin_t *pp, int version,
165ac88567aSHyon Kim     const smp_plugin_config_t *pcp)
166ac88567aSHyon Kim {
167ac88567aSHyon Kim 	if (version != LIBSMP_PLUGIN_VERSION)
168ac88567aSHyon Kim 		return (smp_set_errno(ESMP_VERSION));
169ac88567aSHyon Kim 
170ac88567aSHyon Kim 	pp->sp_functions = pcp->spc_functions;
171ac88567aSHyon Kim 
172ac88567aSHyon Kim 	return (0);
173ac88567aSHyon Kim }
174ac88567aSHyon Kim 
175ac88567aSHyon Kim void
smp_plugin_setspecific(smp_plugin_t * pp,void * data)176ac88567aSHyon Kim smp_plugin_setspecific(smp_plugin_t *pp, void *data)
177ac88567aSHyon Kim {
178ac88567aSHyon Kim 	pp->sp_data = data;
179ac88567aSHyon Kim }
180ac88567aSHyon Kim 
181ac88567aSHyon Kim void *
smp_plugin_getspecific(smp_plugin_t * pp)182ac88567aSHyon Kim smp_plugin_getspecific(smp_plugin_t *pp)
183ac88567aSHyon Kim {
184ac88567aSHyon Kim 	return (pp->sp_data);
185ac88567aSHyon Kim }
186ac88567aSHyon Kim 
187ac88567aSHyon Kim static void
smp_plugin_cleanstr(char * s)188ac88567aSHyon Kim smp_plugin_cleanstr(char *s)
189ac88567aSHyon Kim {
190ac88567aSHyon Kim 	while (*s != '\0') {
191ac88567aSHyon Kim 		if (*s == ' ' || *s == '/')
192ac88567aSHyon Kim 			*s = '-';
193ac88567aSHyon Kim 		s++;
194ac88567aSHyon Kim 	}
195ac88567aSHyon Kim }
196ac88567aSHyon Kim 
197ac88567aSHyon Kim static void
smp_plugin_destroy(smp_plugin_t * pp)198ac88567aSHyon Kim smp_plugin_destroy(smp_plugin_t *pp)
199ac88567aSHyon Kim {
200ac88567aSHyon Kim 	if (pp->sp_initialized && pp->sp_fini != NULL)
201ac88567aSHyon Kim 		pp->sp_fini(pp);
202ac88567aSHyon Kim 
203ac88567aSHyon Kim 	if (_libsmp_plugin_dlclose)
204ac88567aSHyon Kim 		(void) dlclose(pp->sp_object);
205ac88567aSHyon Kim 
206ac88567aSHyon Kim 	smp_free(pp);
207ac88567aSHyon Kim }
208ac88567aSHyon Kim 
209ac88567aSHyon Kim static int
smp_plugin_loadone(smp_target_t * tp,const char * path,uint32_t pass)210ac88567aSHyon Kim smp_plugin_loadone(smp_target_t *tp, const char *path, uint32_t pass)
211ac88567aSHyon Kim {
212ac88567aSHyon Kim 	smp_plugin_t *pp, **loc;
213ac88567aSHyon Kim 	void *obj;
214ac88567aSHyon Kim 	int (*smp_priority)(void);
215ac88567aSHyon Kim 
216ac88567aSHyon Kim 	if ((obj = dlopen(path, RTLD_PARENT | RTLD_LOCAL | RTLD_LAZY)) == NULL)
217ac88567aSHyon Kim 		return (0);
218ac88567aSHyon Kim 
219ac88567aSHyon Kim 	if ((pp = smp_zalloc(sizeof (smp_plugin_t))) == NULL) {
220ac88567aSHyon Kim 		(void) dlclose(obj);
221ac88567aSHyon Kim 		return (-1);
222ac88567aSHyon Kim 	}
223ac88567aSHyon Kim 
224ac88567aSHyon Kim 	pp->sp_object = obj;
225ac88567aSHyon Kim 	pp->sp_init = (int (*)())dlsym(obj, "_smp_init");
226ac88567aSHyon Kim 	pp->sp_fini = (void (*)())dlsym(obj, "_smp_fini");
227ac88567aSHyon Kim 	pp->sp_target = tp;
228ac88567aSHyon Kim 
229ac88567aSHyon Kim 	if (pp->sp_init == NULL) {
230ac88567aSHyon Kim 		smp_plugin_destroy(pp);
231ac88567aSHyon Kim 		return (0);
232ac88567aSHyon Kim 	}
233ac88567aSHyon Kim 
234ac88567aSHyon Kim 	/*
235ac88567aSHyon Kim 	 * Framework modules can establish an explicit prioritying by declaring
236ac88567aSHyon Kim 	 * the '_smp_priority' symbol, which returns an integer used to create
237ac88567aSHyon Kim 	 * an explicit ordering between plugins.
238ac88567aSHyon Kim 	 */
239ac88567aSHyon Kim 	if ((smp_priority = (int (*)())dlsym(obj, "_smp_priority")) != NULL)
240ac88567aSHyon Kim 		pp->sp_priority = smp_priority();
241ac88567aSHyon Kim 
242ac88567aSHyon Kim 	pp->sp_priority |= (uint64_t)pass << 32;
243ac88567aSHyon Kim 
244ac88567aSHyon Kim 	for (loc = &tp->st_plugin_first; *loc != NULL; loc = &(*loc)->sp_next) {
245ac88567aSHyon Kim 		if ((*loc)->sp_priority > pp->sp_priority)
246ac88567aSHyon Kim 			break;
247ac88567aSHyon Kim 	}
248ac88567aSHyon Kim 
249ac88567aSHyon Kim 	if (*loc != NULL)
250ac88567aSHyon Kim 		(*loc)->sp_prev = pp;
251ac88567aSHyon Kim 	else
252ac88567aSHyon Kim 		tp->st_plugin_last = pp;
253ac88567aSHyon Kim 
254ac88567aSHyon Kim 	pp->sp_next = *loc;
255ac88567aSHyon Kim 	*loc = pp;
256ac88567aSHyon Kim 
257ac88567aSHyon Kim 	if (pp->sp_init(pp) != 0)
258ac88567aSHyon Kim 		return (-1);
259ac88567aSHyon Kim 	pp->sp_initialized = B_TRUE;
260ac88567aSHyon Kim 
261ac88567aSHyon Kim 	return (0);
262ac88567aSHyon Kim }
263ac88567aSHyon Kim 
264ac88567aSHyon Kim static int
smp_plugin_load_dir(smp_target_t * tp,const char * pluginroot)265ac88567aSHyon Kim smp_plugin_load_dir(smp_target_t *tp, const char *pluginroot)
266ac88567aSHyon Kim {
267ac88567aSHyon Kim 	char path[PATH_MAX];
268ac88567aSHyon Kim 	DIR *dirp;
269ac88567aSHyon Kim 	struct dirent64 *dp;
270ac88567aSHyon Kim 	char *c_vendor, *vendor, *product, *revision;
271ac88567aSHyon Kim 	char isa[257];
272ac88567aSHyon Kim 
273ac88567aSHyon Kim 	(void) snprintf(path, sizeof (path), "%s/%s",
274ac88567aSHyon Kim 	    pluginroot, LIBSMP_PLUGIN_FRAMEWORK);
275ac88567aSHyon Kim 
276ac88567aSHyon Kim #if defined(_LP64)
277ac88567aSHyon Kim 	if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
278ac88567aSHyon Kim 		isa[0] = '\0';
279ac88567aSHyon Kim #else
280ac88567aSHyon Kim 	isa[0] = '\0';
281ac88567aSHyon Kim #endif
282ac88567aSHyon Kim 
283ac88567aSHyon Kim 	if ((dirp = opendir(path)) != NULL) {
284ac88567aSHyon Kim 		while ((dp = readdir64(dirp)) != NULL) {
285ac88567aSHyon Kim 			if (strcmp(dp->d_name, ".") == 0 ||
286ac88567aSHyon Kim 			    strcmp(dp->d_name, "..") == 0)
287ac88567aSHyon Kim 				continue;
288ac88567aSHyon Kim 
289ac88567aSHyon Kim 			(void) snprintf(path, sizeof (path), "%s/%s/%s/%s",
290ac88567aSHyon Kim 			    pluginroot, LIBSMP_PLUGIN_FRAMEWORK,
291ac88567aSHyon Kim 			    isa, dp->d_name);
292ac88567aSHyon Kim 
293ac88567aSHyon Kim 			if (smp_plugin_loadone(tp, path, 0) != 0) {
294ac88567aSHyon Kim 				(void) closedir(dirp);
295ac88567aSHyon Kim 				return (-1);
296ac88567aSHyon Kim 			}
297ac88567aSHyon Kim 		}
298ac88567aSHyon Kim 
299ac88567aSHyon Kim 		(void) closedir(dirp);
300ac88567aSHyon Kim 	}
301ac88567aSHyon Kim 
302ac88567aSHyon Kim 	/*
303ac88567aSHyon Kim 	 * Now attempt to load platform-specific plugins.  The framework
304ac88567aSHyon Kim 	 * plugins had better give us the ability to perform basic SMP
305ac88567aSHyon Kim 	 * functions like REPORT GENERAL and REPORT MANUFACTURER INFORMATION;
306ac88567aSHyon Kim 	 * if not, we're toast anyway.  If the latter is not supported, we
307ac88567aSHyon Kim 	 * will not be able to use any vendor-specific plugins.  Note that
308ac88567aSHyon Kim 	 * there are actually two possible specifications for vendor plugins:
309ac88567aSHyon Kim 	 * those matching the vendor/product/revision fields, and those
310ac88567aSHyon Kim 	 * matching the component vendor/id/revision fields.  The component is
311ac88567aSHyon Kim 	 * less specific, so we try to load those first.
312ac88567aSHyon Kim 	 */
313ac88567aSHyon Kim 
314ac88567aSHyon Kim 	if (smp_target_fill(tp) != 0)
315ac88567aSHyon Kim 		return (-1);
316ac88567aSHyon Kim 
317ac88567aSHyon Kim 	if (tp->st_vendor == NULL)
318ac88567aSHyon Kim 		return (0);
319ac88567aSHyon Kim 
320ac88567aSHyon Kim 	if (tp->st_component_vendor != NULL) {
321*23a1cceaSRoger A. Faulkner 		c_vendor = strdupa(tp->st_component_vendor);
322ac88567aSHyon Kim 		smp_plugin_cleanstr(c_vendor);
323ac88567aSHyon Kim 	}
324ac88567aSHyon Kim 
325*23a1cceaSRoger A. Faulkner 	vendor = strdupa(tp->st_vendor);
326*23a1cceaSRoger A. Faulkner 	product = strdupa(tp->st_product);
327*23a1cceaSRoger A. Faulkner 	revision = strdupa(tp->st_revision);
328ac88567aSHyon Kim 
329ac88567aSHyon Kim 	smp_plugin_cleanstr(vendor);
330ac88567aSHyon Kim 	smp_plugin_cleanstr(product);
331ac88567aSHyon Kim 	smp_plugin_cleanstr(revision);
332ac88567aSHyon Kim 
333ac88567aSHyon Kim 	if (tp->st_component_vendor != NULL) {
334ac88567aSHyon Kim 		(void) snprintf(path, sizeof (path), "%s/%s/%s/component_%s%s",
335ac88567aSHyon Kim 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
336ac88567aSHyon Kim 		    LIBSMP_PLUGIN_EXT);
337ac88567aSHyon Kim 		if (smp_plugin_loadone(tp, path, 1) != 0)
338ac88567aSHyon Kim 			return (-1);
339ac88567aSHyon Kim 
340ac88567aSHyon Kim 		(void) snprintf(path, sizeof (path),
341ac88567aSHyon Kim 		    "%s/%s/%s/component_%s-%04x%s",
342ac88567aSHyon Kim 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
343ac88567aSHyon Kim 		    tp->st_component_id, LIBSMP_PLUGIN_EXT);
344ac88567aSHyon Kim 		if (smp_plugin_loadone(tp, path, 2) != 0)
345ac88567aSHyon Kim 			return (-1);
346ac88567aSHyon Kim 
347ac88567aSHyon Kim 		(void) snprintf(path, sizeof (path),
348ac88567aSHyon Kim 		    "%s/%s/%s/component_%s-%04x-%02x%s",
349ac88567aSHyon Kim 		    pluginroot, LIBSMP_PLUGIN_VENDOR, isa, c_vendor,
350ac88567aSHyon Kim 		    tp->st_component_id, tp->st_component_revision,
351ac88567aSHyon Kim 		    LIBSMP_PLUGIN_EXT);
352ac88567aSHyon Kim 		if (smp_plugin_loadone(tp, path, 3) != 0)
353ac88567aSHyon Kim 			return (-1);
354ac88567aSHyon Kim 	}
355ac88567aSHyon Kim 
356ac88567aSHyon Kim 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s%s", pluginroot,
357ac88567aSHyon Kim 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, LIBSMP_PLUGIN_EXT);
358ac88567aSHyon Kim 	if (smp_plugin_loadone(tp, path, 4) != 0)
359ac88567aSHyon Kim 		return (-1);
360ac88567aSHyon Kim 
361ac88567aSHyon Kim 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s%s", pluginroot,
362ac88567aSHyon Kim 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, product, LIBSMP_PLUGIN_EXT);
363ac88567aSHyon Kim 	if (smp_plugin_loadone(tp, path, 5) != 0)
364ac88567aSHyon Kim 		return (-1);
365ac88567aSHyon Kim 
366ac88567aSHyon Kim 	(void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s-%s%s", pluginroot,
367ac88567aSHyon Kim 	    LIBSMP_PLUGIN_VENDOR, isa, vendor, product,
368ac88567aSHyon Kim 	    revision, LIBSMP_PLUGIN_EXT);
369ac88567aSHyon Kim 	if (smp_plugin_loadone(tp, path, 6) != 0)
370ac88567aSHyon Kim 		return (-1);
371ac88567aSHyon Kim 
372ac88567aSHyon Kim 	return (0);
373ac88567aSHyon Kim }
374ac88567aSHyon Kim 
375ac88567aSHyon Kim int
smp_plugin_load(smp_target_t * tp)376ac88567aSHyon Kim smp_plugin_load(smp_target_t *tp)
377ac88567aSHyon Kim {
378ac88567aSHyon Kim 	char pluginroot[PATH_MAX];
379ac88567aSHyon Kim 	const char *pluginpath, *p, *q;
380ac88567aSHyon Kim 
381ac88567aSHyon Kim 	if ((pluginpath = getenv("SMP_PLUGINPATH")) == NULL)
382ac88567aSHyon Kim 		pluginpath = LIBSMP_DEFAULT_PLUGINDIR;
383ac88567aSHyon Kim 	_libsmp_plugin_dlclose = (getenv("SMP_NODLCLOSE") == NULL);
384ac88567aSHyon Kim 
385ac88567aSHyon Kim 	for (p = pluginpath; p != NULL; p = q) {
386ac88567aSHyon Kim 		if ((q = strchr(p, ':')) != NULL) {
387ac88567aSHyon Kim 			ptrdiff_t len = q - p;
388ac88567aSHyon Kim 			(void) strncpy(pluginroot, p, len);
389ac88567aSHyon Kim 			pluginroot[len] = '\0';
390ac88567aSHyon Kim 			while (*q == ':')
391ac88567aSHyon Kim 				++q;
392ac88567aSHyon Kim 			if (*q == '\0')
393ac88567aSHyon Kim 				q = NULL;
394ac88567aSHyon Kim 			if (len == 0)
395ac88567aSHyon Kim 				continue;
396ac88567aSHyon Kim 		} else {
397ac88567aSHyon Kim 			(void) strcpy(pluginroot, p);
398ac88567aSHyon Kim 		}
399ac88567aSHyon Kim 
400ac88567aSHyon Kim 		if (pluginroot[0] != '/')
401ac88567aSHyon Kim 			continue;
402ac88567aSHyon Kim 
403ac88567aSHyon Kim 		if (smp_plugin_load_dir(tp, pluginroot) != 0)
404ac88567aSHyon Kim 			return (-1);
405ac88567aSHyon Kim 	}
406ac88567aSHyon Kim 
407ac88567aSHyon Kim 	if (tp->st_plugin_first == NULL)
408ac88567aSHyon Kim 		return (smp_error(ESMP_PLUGIN, "no plugins found"));
409ac88567aSHyon Kim 
410ac88567aSHyon Kim 	return (0);
411ac88567aSHyon Kim }
412ac88567aSHyon Kim 
413ac88567aSHyon Kim void
smp_plugin_unload(smp_target_t * tp)414ac88567aSHyon Kim smp_plugin_unload(smp_target_t *tp)
415ac88567aSHyon Kim {
416ac88567aSHyon Kim 	smp_plugin_t *pp;
417ac88567aSHyon Kim 
418ac88567aSHyon Kim 	while ((pp = tp->st_plugin_first) != NULL) {
419ac88567aSHyon Kim 		tp->st_plugin_first = pp->sp_next;
420ac88567aSHyon Kim 		smp_plugin_destroy(pp);
421ac88567aSHyon Kim 	}
422ac88567aSHyon Kim }
423