xref: /titanic_51/usr/src/cmd/picl/plugins/sun4v/pri/priplugin.c (revision cb851c14591d546883d36d5a8c0d2d8cb55cce33)
10d63ce2bSvenki /*
20d63ce2bSvenki  * CDDL HEADER START
30d63ce2bSvenki  *
40d63ce2bSvenki  * The contents of this file are subject to the terms of the
50d63ce2bSvenki  * Common Development and Distribution License (the "License").
60d63ce2bSvenki  * You may not use this file except in compliance with the License.
70d63ce2bSvenki  *
80d63ce2bSvenki  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90d63ce2bSvenki  * or http://www.opensolaris.org/os/licensing.
100d63ce2bSvenki  * See the License for the specific language governing permissions
110d63ce2bSvenki  * and limitations under the License.
120d63ce2bSvenki  *
130d63ce2bSvenki  * When distributing Covered Code, include this CDDL HEADER in each
140d63ce2bSvenki  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150d63ce2bSvenki  * If applicable, add the following below this CDDL HEADER, with the
160d63ce2bSvenki  * fields enclosed by brackets "[]" replaced with your own identifying
170d63ce2bSvenki  * information: Portions Copyright [yyyy] [name of copyright owner]
180d63ce2bSvenki  *
190d63ce2bSvenki  * CDDL HEADER END
200d63ce2bSvenki  */
210d63ce2bSvenki 
220d63ce2bSvenki /*
23*cb851c14Sfw157321  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240d63ce2bSvenki  * Use is subject to license terms.
250d63ce2bSvenki  */
260d63ce2bSvenki 
270d63ce2bSvenki #pragma ident	"%Z%%M%	%I%	%E% SMI"
280d63ce2bSvenki 
29a90d965dSfw157321 #include <pri.h>
300d63ce2bSvenki #include "priplugin.h"
310d63ce2bSvenki 
320d63ce2bSvenki #pragma init(priplugin_register)	/* place in .init section */
330d63ce2bSvenki 
34a90d965dSfw157321 static md_t *mdp;
350d63ce2bSvenki 
36d2b9c676Sfw157321 static mutex_t	rebuild_lock;
37d2b9c676Sfw157321 static cond_t	rebuild_cv;
38d2b9c676Sfw157321 
39d2b9c676Sfw157321 static thread_t pri_worker_thread_id, pri_reader_thread_id;
40d2b9c676Sfw157321 static boolean_t all_thr_exit = B_FALSE;
41*cb851c14Sfw157321 static boolean_t event_caught = B_FALSE;
42d2b9c676Sfw157321 
43d2b9c676Sfw157321 static void priplugin_init(void);
44d2b9c676Sfw157321 static void priplugin_fini(void);
45a90d965dSfw157321 static void
46a90d965dSfw157321 event_handler(const char *ename, const void *earg, size_t size, void *cookie);
47d2b9c676Sfw157321 static void *pri_worker_thread(void *arg);
48d2b9c676Sfw157321 static void *pri_reader_thread(void *arg);
49d2b9c676Sfw157321 static int remove_old_segments(picl_nodehdl_t node, void *args);
50d2b9c676Sfw157321 
510d63ce2bSvenki 
520d63ce2bSvenki picld_plugin_reg_t priplugin_reg = {
530d63ce2bSvenki 	PICLD_PLUGIN_VERSION_1,
540d63ce2bSvenki 	PICLD_PLUGIN_CRITICAL,
550d63ce2bSvenki 	"pri_plugin",
560d63ce2bSvenki 	priplugin_init,
570d63ce2bSvenki 	priplugin_fini
580d63ce2bSvenki };
590d63ce2bSvenki 
60d2b9c676Sfw157321 static void
610d63ce2bSvenki set_prop_info(ptree_propinfo_t *propinfo, int size, char *name, int type)
620d63ce2bSvenki {
630d63ce2bSvenki 	propinfo->version = PICLD_PLUGIN_VERSION_1;
640d63ce2bSvenki 	propinfo->read = NULL;
650d63ce2bSvenki 	propinfo->write = NULL;
660d63ce2bSvenki 	propinfo->piclinfo.type = type;
670d63ce2bSvenki 	propinfo->piclinfo.accessmode = PICL_READ;
680d63ce2bSvenki 	propinfo->piclinfo.size = size;
694c5e0fdeSvivek 	(void) strlcpy(propinfo->piclinfo.name, name,
700d63ce2bSvenki 	    sizeof (propinfo->piclinfo.name));
710d63ce2bSvenki }
720d63ce2bSvenki 
730d63ce2bSvenki boolean_t
740d63ce2bSvenki prop_exists(picl_nodehdl_t node, char *name)
750d63ce2bSvenki {
760d63ce2bSvenki 	int status;
770d63ce2bSvenki 	picl_prophdl_t proph;
780d63ce2bSvenki 
790d63ce2bSvenki 	status = ptree_get_prop_by_name(node, name, &proph);
800d63ce2bSvenki 	if (status == PICL_SUCCESS)
810d63ce2bSvenki 		return (B_TRUE);
820d63ce2bSvenki 	else
830d63ce2bSvenki 		return (B_FALSE);
840d63ce2bSvenki }
850d63ce2bSvenki 
860d63ce2bSvenki void
870d63ce2bSvenki add_md_prop(picl_nodehdl_t node, int size, char *name, void* value, int type)
880d63ce2bSvenki {
890d63ce2bSvenki 	ptree_propinfo_t propinfo;
900d63ce2bSvenki 	picl_prophdl_t proph;
910d63ce2bSvenki 
920d63ce2bSvenki 	if (!prop_exists(node, name)) {
930d63ce2bSvenki 		set_prop_info(&propinfo, size, name, type);
940d63ce2bSvenki 
950d63ce2bSvenki 		(void) ptree_create_and_add_prop(node, &propinfo,
960d63ce2bSvenki 		    value, &proph);
970d63ce2bSvenki 	}
980d63ce2bSvenki }
990d63ce2bSvenki 
100d2b9c676Sfw157321 /*ARGSUSED*/
101d2b9c676Sfw157321 static int
102d2b9c676Sfw157321 remove_old_segments(picl_nodehdl_t node, void *args)
103d2b9c676Sfw157321 {
104d2b9c676Sfw157321 	int status;
105d2b9c676Sfw157321 
106d2b9c676Sfw157321 	if ((status = ptree_delete_node(node)) == PICL_SUCCESS)
107d2b9c676Sfw157321 		ptree_destroy_node(node);
108d2b9c676Sfw157321 	else
109d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "remove_old_segments: can't delete "
110d2b9c676Sfw157321 		    "segment node: %s\n", picl_strerror(status));
111d2b9c676Sfw157321 
112d2b9c676Sfw157321 	return (PICL_WALK_CONTINUE);
113d2b9c676Sfw157321 }
114d2b9c676Sfw157321 
115d2b9c676Sfw157321 static void
1160d63ce2bSvenki priplugin_init(void)
1170d63ce2bSvenki {
1180d63ce2bSvenki 	int status;
1190d63ce2bSvenki 
120a90d965dSfw157321 	pri_debug(LOG_NOTICE, "priplugin: mem tree and io label thread "
121a90d965dSfw157321 	    "being created; callbacks being registered\n");
122a90d965dSfw157321 
123d2b9c676Sfw157321 	all_thr_exit = B_FALSE;
124*cb851c14Sfw157321 	event_caught = B_FALSE;
125d2b9c676Sfw157321 
126d2b9c676Sfw157321 	(void) mutex_init(&rebuild_lock, USYNC_THREAD, NULL);
127d2b9c676Sfw157321 	(void) cond_init(&rebuild_cv, USYNC_THREAD, NULL);
128d2b9c676Sfw157321 
129d2b9c676Sfw157321 	if ((status = thr_create(NULL, NULL, pri_worker_thread, NULL, THR_BOUND,
130d2b9c676Sfw157321 	    &pri_worker_thread_id)) < 0) {
131d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "priplugin: can't create worker thread: "
132d2b9c676Sfw157321 		    "%d\n", status);
133d2b9c676Sfw157321 		all_thr_exit = B_TRUE;
134d2b9c676Sfw157321 		(void) mutex_destroy(&rebuild_lock);
135d2b9c676Sfw157321 		(void) cond_destroy(&rebuild_cv);
136d2b9c676Sfw157321 	} else if ((status = thr_create(NULL, NULL, pri_reader_thread, NULL,
137d2b9c676Sfw157321 	    THR_BOUND, &pri_reader_thread_id)) < 0) {
138d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "priplugin: can't create reader thread: "
139d2b9c676Sfw157321 		    "%d\n", status);
140d2b9c676Sfw157321 		(void) mutex_lock(&rebuild_lock);
141d2b9c676Sfw157321 		all_thr_exit = B_TRUE;
142d2b9c676Sfw157321 		(void) cond_signal(&rebuild_cv);
143d2b9c676Sfw157321 		(void) mutex_unlock(&rebuild_lock);
144d2b9c676Sfw157321 		(void) thr_join(pri_worker_thread_id, NULL, NULL);
145d2b9c676Sfw157321 		(void) mutex_destroy(&rebuild_lock);
146d2b9c676Sfw157321 		(void) cond_destroy(&rebuild_cv);
147d2b9c676Sfw157321 	} else {
148d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "priplugin_init: worker and reader "
149d2b9c676Sfw157321 		    "threads created - registering event handlers\n");
150a90d965dSfw157321 		/*
151d2b9c676Sfw157321 		 * register event_handler for both "sysevent-device-added",
152d2b9c676Sfw157321 		 * "sysevent_device_removed", and for
153d2b9c676Sfw157321 		 * "sysevent-dr-app-state-change" PICL events
154a90d965dSfw157321 		 */
155a90d965dSfw157321 		(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
156a90d965dSfw157321 		    event_handler, NULL);
157d2b9c676Sfw157321 		(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
158d2b9c676Sfw157321 		    event_handler, NULL);
159a90d965dSfw157321 		(void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
160a90d965dSfw157321 		    event_handler, NULL);
161a90d965dSfw157321 	}
162a90d965dSfw157321 }
163a90d965dSfw157321 
164d2b9c676Sfw157321 /*
165d2b9c676Sfw157321  * This thread handles the main processing of PRI data.  It is woken
166d2b9c676Sfw157321  * up by either the event handler, to process a PICL event, or it is
167d2b9c676Sfw157321  * woken up by the PRI reader thread which has just fetched a new
168d2b9c676Sfw157321  * copy of the PRI.
169d2b9c676Sfw157321  */
170a90d965dSfw157321 /*ARGSUSED*/
171a90d965dSfw157321 static void *
172d2b9c676Sfw157321 pri_worker_thread(void *arg)
173a90d965dSfw157321 {
174a90d965dSfw157321 	int status;
175d2b9c676Sfw157321 	picl_nodehdl_t picl_root_node;
176a90d965dSfw157321 
177d2b9c676Sfw157321 	pri_debug(LOG_NOTICE, "pri_worker_thread: start\n");
178d2b9c676Sfw157321 
179d2b9c676Sfw157321 	(void) mutex_lock(&rebuild_lock);
180*cb851c14Sfw157321 	/*LINTED E_FUNC_RET_MAYBE_IGNORED2*/
181d2b9c676Sfw157321 	while (1) {
182d2b9c676Sfw157321 		(void) cond_wait(&rebuild_cv, &rebuild_lock);
183d2b9c676Sfw157321 
184d2b9c676Sfw157321 		if (all_thr_exit == B_TRUE) {
185d2b9c676Sfw157321 			(void) mutex_unlock(&rebuild_lock);
186d2b9c676Sfw157321 			pri_debug(LOG_NOTICE, "pri_worker_thread: time to "
187d2b9c676Sfw157321 			    "exit\n");
188d2b9c676Sfw157321 			break;
189a90d965dSfw157321 		}
190a90d965dSfw157321 
191*cb851c14Sfw157321 		/*
192*cb851c14Sfw157321 		 * We don't get events for changes to system memory,
193*cb851c14Sfw157321 		 * and we do not want to interfere with other plug-ins
194*cb851c14Sfw157321 		 * by making changes to the picl tree.  So if we were
195*cb851c14Sfw157321 		 * woken up by a thread then do not destroy and rebuild
196*cb851c14Sfw157321 		 * the memory info.  Just go fix the labels.
197*cb851c14Sfw157321 		 */
198*cb851c14Sfw157321 		if (event_caught == B_FALSE) {
199d2b9c676Sfw157321 			status = ptree_get_root(&picl_root_node);
2000d63ce2bSvenki 			if (status != PICL_SUCCESS) {
201d2b9c676Sfw157321 				pri_debug(LOG_NOTICE, "pri_worker_thread: "
202d2b9c676Sfw157321 				    "can't get picl tree root node: %s\n",
203d2b9c676Sfw157321 				    picl_strerror(status));
204d2b9c676Sfw157321 				continue;
2050d63ce2bSvenki 			}
2060d63ce2bSvenki 
207*cb851c14Sfw157321 			pri_debug(LOG_NOTICE, "pri_worker_thread: have root "
208*cb851c14Sfw157321 			    "picl and PRI nodes\n");
2090d63ce2bSvenki 
210d2b9c676Sfw157321 			status = ptree_walk_tree_by_class(picl_root_node,
211d2b9c676Sfw157321 			    "memory-segment", NULL, remove_old_segments);
212d2b9c676Sfw157321 			if (status != PICL_SUCCESS) {
213*cb851c14Sfw157321 				pri_debug(LOG_NOTICE, "pri_worker_thread: "
214*cb851c14Sfw157321 				    "can't remove old memory segments: \n",
215*cb851c14Sfw157321 				    picl_strerror(status));
216d2b9c676Sfw157321 			} else
217*cb851c14Sfw157321 				pri_debug(LOG_NOTICE, "pri_worker_thread: "
218*cb851c14Sfw157321 				    "old memory segments removed\n");
2190d63ce2bSvenki 
220*cb851c14Sfw157321 			status = ptree_walk_tree_by_class(picl_root_node,
221*cb851c14Sfw157321 			    "memory", (void *) mdp, add_mem_prop);
2220d63ce2bSvenki 			if (status != PICL_SUCCESS) {
223*cb851c14Sfw157321 				pri_debug(LOG_NOTICE, "pri_worker_thread: "
224*cb851c14Sfw157321 				    "memory segments walk failed: \n",
225*cb851c14Sfw157321 				    picl_strerror(status));
2260d63ce2bSvenki 			} else
227*cb851c14Sfw157321 				pri_debug(LOG_NOTICE, "pri_worker_thread: "
228*cb851c14Sfw157321 				    "success walking memory node\n");
229*cb851c14Sfw157321 		} else
230*cb851c14Sfw157321 			event_caught = B_FALSE;
2310d63ce2bSvenki 
232a90d965dSfw157321 		io_dev_addlabel(mdp);
233a90d965dSfw157321 	}
234d2b9c676Sfw157321 	pri_debug(LOG_NOTICE, "pri_worker_thread: exiting\n");
235a90d965dSfw157321 	return (NULL);
2360d63ce2bSvenki }
2370d63ce2bSvenki 
238d2b9c676Sfw157321 /*
239d2b9c676Sfw157321  * This thread camps out in the PRI driver, waiting for it to return
240d2b9c676Sfw157321  * the contents of a new PRI.  When the PRI is changed this thread
241d2b9c676Sfw157321  * reads that data and prepares it for processing by the worker thread.
242d2b9c676Sfw157321  * It then signals the worker thread to process the new PRI data.
243d2b9c676Sfw157321  */
244d2b9c676Sfw157321 /*ARGSUSED*/
245d2b9c676Sfw157321 static void *
246d2b9c676Sfw157321 pri_reader_thread(void *arg)
247d2b9c676Sfw157321 {
248d2b9c676Sfw157321 	uint64_t tok;
249d2b9c676Sfw157321 	int status, count;
250d2b9c676Sfw157321 
251d2b9c676Sfw157321 	pri_debug(LOG_NOTICE, "pri_reader_thread: thread start\n");
252d2b9c676Sfw157321 
253d2b9c676Sfw157321 	if (pri_init() != 0) {
254d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "pri_reader_thread: pri_init failed\n");
255d2b9c676Sfw157321 		return (NULL);
256d2b9c676Sfw157321 	}
257d2b9c676Sfw157321 
258d2b9c676Sfw157321 	/*
259d2b9c676Sfw157321 	 * It's entirely possible that a new PRI may get pushed while
260d2b9c676Sfw157321 	 * the worker thread is processing the previous PRI.  We will
261d2b9c676Sfw157321 	 * wait until the worker is finished, then flush the old contents
262d2b9c676Sfw157321 	 * and wake up the worker again to process the new data.
263d2b9c676Sfw157321 	 */
264d2b9c676Sfw157321 	mdp = NULL;
265d2b9c676Sfw157321 	tok = 0;
266d2b9c676Sfw157321 	count = 0;
267*cb851c14Sfw157321 	/*LINTED E_FUNC_RET_MAYBE_IGNORED2*/
268d2b9c676Sfw157321 	while (1) {
269d2b9c676Sfw157321 		/*
270d2b9c676Sfw157321 		 * The _fini() function will close the PRI's fd, which will
271d2b9c676Sfw157321 		 * cause this function to break out of waiting in the PRI
272d2b9c676Sfw157321 		 * driver and return an error.
273d2b9c676Sfw157321 		 */
274d2b9c676Sfw157321 		status = pri_devinit(&tok);
275d2b9c676Sfw157321 
276d2b9c676Sfw157321 		(void) mutex_lock(&rebuild_lock);
277d2b9c676Sfw157321 		if (all_thr_exit == B_TRUE) {
278d2b9c676Sfw157321 			(void) mutex_unlock(&rebuild_lock);
279d2b9c676Sfw157321 			pri_debug(LOG_NOTICE, "pri_reader_thread: time to "
280d2b9c676Sfw157321 			    "exit\n");
281d2b9c676Sfw157321 			break;
282d2b9c676Sfw157321 		}
283d2b9c676Sfw157321 
284d2b9c676Sfw157321 		/*
285d2b9c676Sfw157321 		 * Wait until the worker is idle before swapping in the
286d2b9c676Sfw157321 		 * new PRI contents, then signal the worker to process
287d2b9c676Sfw157321 		 * that new data.
288d2b9c676Sfw157321 		 */
289d2b9c676Sfw157321 		if (status == 0) {
290d2b9c676Sfw157321 			pri_debug(LOG_NOTICE, "pri_reader_thread: got PRI\n");
291d2b9c676Sfw157321 
292d2b9c676Sfw157321 			/* old buffer will be freed by pri_bufinit() */
293d2b9c676Sfw157321 			mdp = pri_bufinit(mdp);
294d2b9c676Sfw157321 			if (mdp != NULL) {
295d2b9c676Sfw157321 				(void) cond_signal(&rebuild_cv);
296d2b9c676Sfw157321 				count = 0;
297d2b9c676Sfw157321 			} else {
298d2b9c676Sfw157321 				pri_debug(LOG_NOTICE, "pri_reader_thread: "
299d2b9c676Sfw157321 				    "NULL mdp!\n");
300d2b9c676Sfw157321 				status = -1;
301d2b9c676Sfw157321 			}
302d2b9c676Sfw157321 		}
303d2b9c676Sfw157321 
304d2b9c676Sfw157321 		/*
305d2b9c676Sfw157321 		 * Try to handle SP resets or other unexplained errors
306d2b9c676Sfw157321 		 * from ds by closing down and re-opening the PRI driver.
307d2b9c676Sfw157321 		 */
308d2b9c676Sfw157321 		if (status == -1) {
309d2b9c676Sfw157321 			if (errno != 0) {
310d2b9c676Sfw157321 				pri_debug(LOG_NOTICE, "pri_reader_thread: "
311d2b9c676Sfw157321 				    "can't get PRI contents: %s\n",
312d2b9c676Sfw157321 				    strerror(errno));
313d2b9c676Sfw157321 			}
314d2b9c676Sfw157321 			if (++count > 6) {
315d2b9c676Sfw157321 				pri_debug(LOG_NOTICE, "pci_reader_thread: "
316d2b9c676Sfw157321 				    "can't process PRI data\n");
317d2b9c676Sfw157321 				(void) mutex_unlock(&rebuild_lock);
318d2b9c676Sfw157321 				break;
319d2b9c676Sfw157321 			}
320d2b9c676Sfw157321 			/* old buffer will be freed by pri_fini() */
321d2b9c676Sfw157321 			pri_fini();
322d2b9c676Sfw157321 			tok = 0;
323d2b9c676Sfw157321 			sleep(10);
324d2b9c676Sfw157321 			if (pri_init() != 0) {
325d2b9c676Sfw157321 				pri_debug(LOG_NOTICE, "pci_reader_thread: "
326d2b9c676Sfw157321 				    "can't reinitialize PRI driver\n");
327d2b9c676Sfw157321 				(void) mutex_unlock(&rebuild_lock);
328d2b9c676Sfw157321 				break;
329d2b9c676Sfw157321 			}
330d2b9c676Sfw157321 		}
331d2b9c676Sfw157321 		(void) mutex_unlock(&rebuild_lock);
332d2b9c676Sfw157321 	}
333d2b9c676Sfw157321 
334d2b9c676Sfw157321 	pri_debug(LOG_NOTICE, "pri_reader_thread: thread exiting\n");
335d2b9c676Sfw157321 	return (NULL);
336d2b9c676Sfw157321 }
337d2b9c676Sfw157321 
338d2b9c676Sfw157321 static void
3390d63ce2bSvenki priplugin_fini(void)
3400d63ce2bSvenki {
341d2b9c676Sfw157321 	pri_debug(LOG_NOTICE, "priplugin_fini: called\n");
342d2b9c676Sfw157321 
343d2b9c676Sfw157321 	if (all_thr_exit == B_TRUE)
344d2b9c676Sfw157321 		return;
345d2b9c676Sfw157321 
346d2b9c676Sfw157321 	/* unregister the event handlers */
347a90d965dSfw157321 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
348a90d965dSfw157321 	    event_handler, NULL);
349d2b9c676Sfw157321 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
350d2b9c676Sfw157321 	    event_handler, NULL);
351a90d965dSfw157321 	(void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
352a90d965dSfw157321 	    event_handler, NULL);
353d2b9c676Sfw157321 
354d2b9c676Sfw157321 	/*
355d2b9c676Sfw157321 	 * Set the exit flag to tell the worker thread to quit and wake
356d2b9c676Sfw157321 	 * up that thread.  Once that thread is reaped then pull the rug
357d2b9c676Sfw157321 	 * out from the PRI reader thread by calling pri_fini(), which
358d2b9c676Sfw157321 	 * closes the PRI fd.  That wakes the PRI reader thread and it
359d2b9c676Sfw157321 	 * will then exit as well.
360d2b9c676Sfw157321 	 */
361d2b9c676Sfw157321 	(void) mutex_lock(&rebuild_lock);
362d2b9c676Sfw157321 	all_thr_exit = B_TRUE;
363d2b9c676Sfw157321 	(void) cond_signal(&rebuild_cv);
364d2b9c676Sfw157321 	(void) mutex_unlock(&rebuild_lock);
365d2b9c676Sfw157321 
366d2b9c676Sfw157321 	(void) thr_join(pri_worker_thread_id, NULL, NULL);
367d2b9c676Sfw157321 
368d2b9c676Sfw157321 	pri_devfini(mdp);
369d2b9c676Sfw157321 	mdp = NULL;
370d2b9c676Sfw157321 	pri_fini();
371d2b9c676Sfw157321 	(void) thr_join(pri_reader_thread_id, NULL, NULL);
372d2b9c676Sfw157321 
373d2b9c676Sfw157321 	(void) mutex_destroy(&rebuild_lock);
374d2b9c676Sfw157321 	(void) cond_destroy(&rebuild_cv);
3750d63ce2bSvenki }
3760d63ce2bSvenki 
3770d63ce2bSvenki void
3780d63ce2bSvenki priplugin_register(void)
3790d63ce2bSvenki {
3800d63ce2bSvenki 	picld_plugin_register(&priplugin_reg);
3810d63ce2bSvenki }
3820d63ce2bSvenki 
383a90d965dSfw157321 /*
384a90d965dSfw157321  * Discovery event handler
385a90d965dSfw157321  * respond to the picl events:
386a90d965dSfw157321  *      PICLEVENT_SYSEVENT_DEVICE_ADDED
387d2b9c676Sfw157321  *      PICLEVENT_SYSEVENT_DEVICE_REMOVED
388a90d965dSfw157321  *      PICLEVENT_DR_AP_STATE_CHANGE
389a90d965dSfw157321  *
390a90d965dSfw157321  * We can't do much of anything fancy since the event data doesn't contain
391a90d965dSfw157321  * a nac for the device.  Nothing to do for remove - the devtree plug-in
392a90d965dSfw157321  * will have removed the node for us.  For add we have to go back and
393a90d965dSfw157321  * add labels again.
394a90d965dSfw157321  */
395a90d965dSfw157321 static void
396a90d965dSfw157321 event_handler(const char *ename, const void *earg, size_t size, void *cookie)
397a90d965dSfw157321 {
398*cb851c14Sfw157321 
399a90d965dSfw157321 	pri_debug(LOG_NOTICE, "pri: event_handler: caught event "
400d2b9c676Sfw157321 	    "%s\n", ename);
401d2b9c676Sfw157321 	if ((strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) ||
402d2b9c676Sfw157321 	    (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) ||
403d2b9c676Sfw157321 	    (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) == 0)) {
404d2b9c676Sfw157321 		pri_debug(LOG_NOTICE, "pri: event_handler: handle event "
405d2b9c676Sfw157321 		    "%s; waking worker thread\n", ename);
406*cb851c14Sfw157321 
407d2b9c676Sfw157321 		(void) mutex_lock(&rebuild_lock);
408d2b9c676Sfw157321 
409*cb851c14Sfw157321 		if (all_thr_exit == B_FALSE) {
410*cb851c14Sfw157321 			/*
411*cb851c14Sfw157321 			 * Tell the worker thread to only re-examine the
412*cb851c14Sfw157321 			 * IO device labels.
413*cb851c14Sfw157321 			 */
414*cb851c14Sfw157321 			event_caught = B_TRUE;
415d2b9c676Sfw157321 			(void) cond_signal(&rebuild_cv);
416*cb851c14Sfw157321 		}
417d2b9c676Sfw157321 
418d2b9c676Sfw157321 		(void) mutex_unlock(&rebuild_lock);
419a90d965dSfw157321 	}
420a90d965dSfw157321 }
421a90d965dSfw157321 
4220d63ce2bSvenki /*VARARGS2*/
4230d63ce2bSvenki void
4240d63ce2bSvenki pri_debug(int level, char *fmt, ...)
4250d63ce2bSvenki {
4260d63ce2bSvenki #if (PRI_DEBUG != 0)
4270d63ce2bSvenki 	va_list	ap;
4280d63ce2bSvenki 
4290d63ce2bSvenki 	va_start(ap, fmt);
4300d63ce2bSvenki 	vsyslog(level, fmt, ap);
4310d63ce2bSvenki 	va_end(ap);
4320d63ce2bSvenki #endif
4330d63ce2bSvenki }
434