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