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
set_prop_info(ptree_propinfo_t * propinfo,int size,char * name,int type)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
prop_exists(picl_nodehdl_t node,char * name)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
add_md_prop(picl_nodehdl_t node,int size,char * name,void * value,int type)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
remove_old_segments(picl_nodehdl_t node,void * args)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
priplugin_init(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 *
pri_worker_thread(void * arg)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 *
pri_reader_thread(void * arg)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
priplugin_fini(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
priplugin_register(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
event_handler(const char * ename,const void * earg,size_t size,void * cookie)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
pri_debug(int level,char * fmt,...)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