10dc974a9SCathy Zhou /*
20dc974a9SCathy Zhou  * CDDL HEADER START
30dc974a9SCathy Zhou  *
40dc974a9SCathy Zhou  * The contents of this file are subject to the terms of the
50dc974a9SCathy Zhou  * Common Development and Distribution License (the "License").
60dc974a9SCathy Zhou  * You may not use this file except in compliance with the License.
70dc974a9SCathy Zhou  *
80dc974a9SCathy Zhou  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90dc974a9SCathy Zhou  * or http://www.opensolaris.org/os/licensing.
100dc974a9SCathy Zhou  * See the License for the specific language governing permissions
110dc974a9SCathy Zhou  * and limitations under the License.
120dc974a9SCathy Zhou  *
130dc974a9SCathy Zhou  * When distributing Covered Code, include this CDDL HEADER in each
140dc974a9SCathy Zhou  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150dc974a9SCathy Zhou  * If applicable, add the following below this CDDL HEADER, with the
160dc974a9SCathy Zhou  * fields enclosed by brackets "[]" replaced with your own identifying
170dc974a9SCathy Zhou  * information: Portions Copyright [yyyy] [name of copyright owner]
180dc974a9SCathy Zhou  *
190dc974a9SCathy Zhou  * CDDL HEADER END
200dc974a9SCathy Zhou  */
210dc974a9SCathy Zhou /*
225093e103SCathy Zhou  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230dc974a9SCathy Zhou  * Use is subject to license terms.
240dc974a9SCathy Zhou  */
250dc974a9SCathy Zhou 
260dc974a9SCathy Zhou /*
270dc974a9SCathy Zhou  * datalink syseventd module.
280dc974a9SCathy Zhou  *
290dc974a9SCathy Zhou  * The purpose of this module is to identify all datalink related events,
300dc974a9SCathy Zhou  * and react accordingly.
310dc974a9SCathy Zhou  */
320dc974a9SCathy Zhou 
330dc974a9SCathy Zhou #include <errno.h>
340dc974a9SCathy Zhou #include <sys/sysevent/eventdefs.h>
350dc974a9SCathy Zhou #include <string.h>
360dc974a9SCathy Zhou #include <libnvpair.h>
370dc974a9SCathy Zhou #include <librcm.h>
380dc974a9SCathy Zhou #include <libsysevent.h>
39*5ad1f010SStephen Hanson #include "sysevent_signal.h"
400dc974a9SCathy Zhou 
414dc92747SCheng Sean Ye extern void syseventd_err_print(char *, ...);
424dc92747SCheng Sean Ye 
434dc92747SCheng Sean Ye struct event_list {
444dc92747SCheng Sean Ye 	nvlist_t *ev;
454dc92747SCheng Sean Ye 	struct event_list *next;
464dc92747SCheng Sean Ye };
474dc92747SCheng Sean Ye 
480dc974a9SCathy Zhou static rcm_handle_t *rcm_hdl = NULL;
494dc92747SCheng Sean Ye static boolean_t dl_exiting;
504dc92747SCheng Sean Ye static thread_t dl_notify_tid;
514dc92747SCheng Sean Ye static mutex_t dl_mx;
524dc92747SCheng Sean Ye static cond_t dl_cv;
534dc92747SCheng Sean Ye static struct event_list *dl_events;
544dc92747SCheng Sean Ye 
554dc92747SCheng Sean Ye /* ARGSUSED */
564dc92747SCheng Sean Ye static void *
574dc92747SCheng Sean Ye datalink_notify_thread(void *arg)
584dc92747SCheng Sean Ye {
594dc92747SCheng Sean Ye 	struct event_list *tmp_events, *ep;
604dc92747SCheng Sean Ye 
614dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
624dc92747SCheng Sean Ye 
634dc92747SCheng Sean Ye 	while (! dl_exiting || dl_events != NULL) {
644dc92747SCheng Sean Ye 		if (dl_events == NULL) {
654dc92747SCheng Sean Ye 			(void) cond_wait(&dl_cv, &dl_mx);
664dc92747SCheng Sean Ye 			continue;
674dc92747SCheng Sean Ye 		}
684dc92747SCheng Sean Ye 
694dc92747SCheng Sean Ye 		tmp_events = dl_events;
704dc92747SCheng Sean Ye 		dl_events = NULL;
714dc92747SCheng Sean Ye 
724dc92747SCheng Sean Ye 		(void) mutex_unlock(&dl_mx);
734dc92747SCheng Sean Ye 
744dc92747SCheng Sean Ye 		while (tmp_events != NULL) {
75*5ad1f010SStephen Hanson 			struct sigaction cbuf, dfl;
76*5ad1f010SStephen Hanson 
77*5ad1f010SStephen Hanson 			/*
78*5ad1f010SStephen Hanson 			 * Ignore SIGCLD for the
79*5ad1f010SStephen Hanson 			 * duration of the rcm_notify_event call.
80*5ad1f010SStephen Hanson 			 */
81*5ad1f010SStephen Hanson 			(void) memset(&dfl, 0, sizeof (dfl));
82*5ad1f010SStephen Hanson 			dfl.sa_handler = SIG_IGN;
83*5ad1f010SStephen Hanson 			(void) sigaction(SIGCHLD, &dfl, &cbuf);
84*5ad1f010SStephen Hanson 
854dc92747SCheng Sean Ye 			/*
864dc92747SCheng Sean Ye 			 * Send the PHYSLINK_NEW event to network_rcm to update
874dc92747SCheng Sean Ye 			 * the network devices cache accordingly.
884dc92747SCheng Sean Ye 			 */
894dc92747SCheng Sean Ye 			if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_PHYSLINK_NEW,
904dc92747SCheng Sean Ye 			    0, tmp_events->ev, NULL) != RCM_SUCCESS)
914dc92747SCheng Sean Ye 				syseventd_err_print("datalink_mod: Can not "
924dc92747SCheng Sean Ye 				    "notify event: %s\n", strerror(errno));
934dc92747SCheng Sean Ye 
94*5ad1f010SStephen Hanson 			(void) sigaction(SIGCHLD, &cbuf, NULL);
954dc92747SCheng Sean Ye 			ep = tmp_events;
964dc92747SCheng Sean Ye 			tmp_events = tmp_events->next;
974dc92747SCheng Sean Ye 			nvlist_free(ep->ev);
984dc92747SCheng Sean Ye 			free(ep);
994dc92747SCheng Sean Ye 		}
1004dc92747SCheng Sean Ye 
1014dc92747SCheng Sean Ye 		(void) mutex_lock(&dl_mx);
1024dc92747SCheng Sean Ye 	}
1034dc92747SCheng Sean Ye 
1044dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
1054dc92747SCheng Sean Ye 
1064dc92747SCheng Sean Ye 	return (NULL);
1074dc92747SCheng Sean Ye }
1080dc974a9SCathy Zhou 
1090dc974a9SCathy Zhou /*ARGSUSED*/
1100dc974a9SCathy Zhou static int
1110dc974a9SCathy Zhou datalink_deliver_event(sysevent_t *ev, int unused)
1120dc974a9SCathy Zhou {
1130dc974a9SCathy Zhou 	const char *class = sysevent_get_class_name(ev);
1140dc974a9SCathy Zhou 	const char *subclass = sysevent_get_subclass_name(ev);
1150dc974a9SCathy Zhou 	nvlist_t *nvl;
1164dc92747SCheng Sean Ye 	struct event_list *newp, **elpp;
1170dc974a9SCathy Zhou 
1180dc974a9SCathy Zhou 	if (strcmp(class, EC_DATALINK) != 0 ||
1190dc974a9SCathy Zhou 	    strcmp(subclass, ESC_DATALINK_PHYS_ADD) != 0) {
1200dc974a9SCathy Zhou 		return (0);
1210dc974a9SCathy Zhou 	}
1220dc974a9SCathy Zhou 
1230dc974a9SCathy Zhou 	if (sysevent_get_attr_list(ev, &nvl) != 0)
1240dc974a9SCathy Zhou 		return (EINVAL);
1250dc974a9SCathy Zhou 
1265093e103SCathy Zhou 	/*
1274dc92747SCheng Sean Ye 	 * rcm_notify_event() needs to be called asynchronously otherwise when
1284dc92747SCheng Sean Ye 	 * sysevent queue is full, deadlock will happen.
1295093e103SCathy Zhou 	 */
1304dc92747SCheng Sean Ye 	if ((newp = malloc(sizeof (struct event_list))) == NULL)
1314dc92747SCheng Sean Ye 		return (ENOMEM);
1320dc974a9SCathy Zhou 
1334dc92747SCheng Sean Ye 	newp->ev = nvl;
1344dc92747SCheng Sean Ye 	newp->next = NULL;
1354dc92747SCheng Sean Ye 
1364dc92747SCheng Sean Ye 	/*
1374dc92747SCheng Sean Ye 	 * queue up at the end of the event list and signal notify_thread to
1384dc92747SCheng Sean Ye 	 * process it.
1394dc92747SCheng Sean Ye 	 */
1404dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
1414dc92747SCheng Sean Ye 	elpp = &dl_events;
1424dc92747SCheng Sean Ye 	while (*elpp !=  NULL)
1434dc92747SCheng Sean Ye 		elpp = &(*elpp)->next;
1444dc92747SCheng Sean Ye 	*elpp = newp;
1454dc92747SCheng Sean Ye 	(void) cond_signal(&dl_cv);
1464dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
1474dc92747SCheng Sean Ye 
1484dc92747SCheng Sean Ye 	return (0);
1490dc974a9SCathy Zhou }
1500dc974a9SCathy Zhou 
1510dc974a9SCathy Zhou static struct slm_mod_ops datalink_mod_ops = {
1520dc974a9SCathy Zhou 	SE_MAJOR_VERSION,
1530dc974a9SCathy Zhou 	SE_MINOR_VERSION,
1540dc974a9SCathy Zhou 	SE_MAX_RETRY_LIMIT,
1550dc974a9SCathy Zhou 	datalink_deliver_event
1560dc974a9SCathy Zhou };
1570dc974a9SCathy Zhou 
1580dc974a9SCathy Zhou struct slm_mod_ops *
1590dc974a9SCathy Zhou slm_init()
1600dc974a9SCathy Zhou {
1614dc92747SCheng Sean Ye 	dl_events = NULL;
1624dc92747SCheng Sean Ye 	dl_exiting = B_FALSE;
1634dc92747SCheng Sean Ye 
1640dc974a9SCathy Zhou 	if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
1650dc974a9SCathy Zhou 		return (NULL);
1660dc974a9SCathy Zhou 
1674dc92747SCheng Sean Ye 	if (thr_create(NULL, 0,  datalink_notify_thread, NULL, 0,
1684dc92747SCheng Sean Ye 	    &dl_notify_tid) != 0) {
1694dc92747SCheng Sean Ye 		(void) rcm_free_handle(rcm_hdl);
1704dc92747SCheng Sean Ye 		return (NULL);
1714dc92747SCheng Sean Ye 	}
1724dc92747SCheng Sean Ye 
1734dc92747SCheng Sean Ye 	(void) mutex_init(&dl_mx, USYNC_THREAD, NULL);
1744dc92747SCheng Sean Ye 	(void) cond_init(&dl_cv, USYNC_THREAD, NULL);
1754dc92747SCheng Sean Ye 
1760dc974a9SCathy Zhou 	return (&datalink_mod_ops);
1770dc974a9SCathy Zhou }
1780dc974a9SCathy Zhou 
1790dc974a9SCathy Zhou void
1800dc974a9SCathy Zhou slm_fini()
1810dc974a9SCathy Zhou {
1824dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
1834dc92747SCheng Sean Ye 	dl_exiting = B_TRUE;
1844dc92747SCheng Sean Ye 	(void) cond_signal(&dl_cv);
1854dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
1864dc92747SCheng Sean Ye 	(void) thr_join(dl_notify_tid, NULL, NULL);
1874dc92747SCheng Sean Ye 
1884dc92747SCheng Sean Ye 	(void) mutex_destroy(&dl_mx);
1894dc92747SCheng Sean Ye 	(void) cond_destroy(&dl_cv);
1900dc974a9SCathy Zhou 	(void) rcm_free_handle(rcm_hdl);
1910dc974a9SCathy Zhou 	rcm_hdl = NULL;
1920dc974a9SCathy Zhou }
193