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>
390dc974a9SCathy Zhou 
40*4dc92747SCheng Sean Ye extern void syseventd_err_print(char *, ...);
41*4dc92747SCheng Sean Ye 
42*4dc92747SCheng Sean Ye struct event_list {
43*4dc92747SCheng Sean Ye 	nvlist_t *ev;
44*4dc92747SCheng Sean Ye 	struct event_list *next;
45*4dc92747SCheng Sean Ye };
46*4dc92747SCheng Sean Ye 
470dc974a9SCathy Zhou static rcm_handle_t *rcm_hdl = NULL;
48*4dc92747SCheng Sean Ye static boolean_t dl_exiting;
49*4dc92747SCheng Sean Ye static thread_t dl_notify_tid;
50*4dc92747SCheng Sean Ye static mutex_t dl_mx;
51*4dc92747SCheng Sean Ye static cond_t dl_cv;
52*4dc92747SCheng Sean Ye static struct event_list *dl_events;
53*4dc92747SCheng Sean Ye 
54*4dc92747SCheng Sean Ye /* ARGSUSED */
55*4dc92747SCheng Sean Ye static void *
56*4dc92747SCheng Sean Ye datalink_notify_thread(void *arg)
57*4dc92747SCheng Sean Ye {
58*4dc92747SCheng Sean Ye 	struct event_list *tmp_events, *ep;
59*4dc92747SCheng Sean Ye 
60*4dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
61*4dc92747SCheng Sean Ye 
62*4dc92747SCheng Sean Ye 	while (! dl_exiting || dl_events != NULL) {
63*4dc92747SCheng Sean Ye 		if (dl_events == NULL) {
64*4dc92747SCheng Sean Ye 			(void) cond_wait(&dl_cv, &dl_mx);
65*4dc92747SCheng Sean Ye 			continue;
66*4dc92747SCheng Sean Ye 		}
67*4dc92747SCheng Sean Ye 
68*4dc92747SCheng Sean Ye 		tmp_events = dl_events;
69*4dc92747SCheng Sean Ye 		dl_events = NULL;
70*4dc92747SCheng Sean Ye 
71*4dc92747SCheng Sean Ye 		(void) mutex_unlock(&dl_mx);
72*4dc92747SCheng Sean Ye 
73*4dc92747SCheng Sean Ye 		while (tmp_events != NULL) {
74*4dc92747SCheng Sean Ye 			/*
75*4dc92747SCheng Sean Ye 			 * Send the PHYSLINK_NEW event to network_rcm to update
76*4dc92747SCheng Sean Ye 			 * the network devices cache accordingly.
77*4dc92747SCheng Sean Ye 			 */
78*4dc92747SCheng Sean Ye 			if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_PHYSLINK_NEW,
79*4dc92747SCheng Sean Ye 			    0, tmp_events->ev, NULL) != RCM_SUCCESS)
80*4dc92747SCheng Sean Ye 				syseventd_err_print("datalink_mod: Can not"
81*4dc92747SCheng Sean Ye 				    "notify event: %s\n", strerror(errno));
82*4dc92747SCheng Sean Ye 
83*4dc92747SCheng Sean Ye 			ep = tmp_events;
84*4dc92747SCheng Sean Ye 			tmp_events = tmp_events->next;
85*4dc92747SCheng Sean Ye 			nvlist_free(ep->ev);
86*4dc92747SCheng Sean Ye 			free(ep);
87*4dc92747SCheng Sean Ye 		}
88*4dc92747SCheng Sean Ye 
89*4dc92747SCheng Sean Ye 		(void) mutex_lock(&dl_mx);
90*4dc92747SCheng Sean Ye 	}
91*4dc92747SCheng Sean Ye 
92*4dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
93*4dc92747SCheng Sean Ye 
94*4dc92747SCheng Sean Ye 	return (NULL);
95*4dc92747SCheng Sean Ye }
960dc974a9SCathy Zhou 
970dc974a9SCathy Zhou /*ARGSUSED*/
980dc974a9SCathy Zhou static int
990dc974a9SCathy Zhou datalink_deliver_event(sysevent_t *ev, int unused)
1000dc974a9SCathy Zhou {
1010dc974a9SCathy Zhou 	const char *class = sysevent_get_class_name(ev);
1020dc974a9SCathy Zhou 	const char *subclass = sysevent_get_subclass_name(ev);
1030dc974a9SCathy Zhou 	nvlist_t *nvl;
104*4dc92747SCheng Sean Ye 	struct event_list *newp, **elpp;
1050dc974a9SCathy Zhou 
1060dc974a9SCathy Zhou 	if (strcmp(class, EC_DATALINK) != 0 ||
1070dc974a9SCathy Zhou 	    strcmp(subclass, ESC_DATALINK_PHYS_ADD) != 0) {
1080dc974a9SCathy Zhou 		return (0);
1090dc974a9SCathy Zhou 	}
1100dc974a9SCathy Zhou 
1110dc974a9SCathy Zhou 	if (sysevent_get_attr_list(ev, &nvl) != 0)
1120dc974a9SCathy Zhou 		return (EINVAL);
1130dc974a9SCathy Zhou 
1145093e103SCathy Zhou 	/*
115*4dc92747SCheng Sean Ye 	 * rcm_notify_event() needs to be called asynchronously otherwise when
116*4dc92747SCheng Sean Ye 	 * sysevent queue is full, deadlock will happen.
1175093e103SCathy Zhou 	 */
118*4dc92747SCheng Sean Ye 	if ((newp = malloc(sizeof (struct event_list))) == NULL)
119*4dc92747SCheng Sean Ye 		return (ENOMEM);
1200dc974a9SCathy Zhou 
121*4dc92747SCheng Sean Ye 	newp->ev = nvl;
122*4dc92747SCheng Sean Ye 	newp->next = NULL;
123*4dc92747SCheng Sean Ye 
124*4dc92747SCheng Sean Ye 	/*
125*4dc92747SCheng Sean Ye 	 * queue up at the end of the event list and signal notify_thread to
126*4dc92747SCheng Sean Ye 	 * process it.
127*4dc92747SCheng Sean Ye 	 */
128*4dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
129*4dc92747SCheng Sean Ye 	elpp = &dl_events;
130*4dc92747SCheng Sean Ye 	while (*elpp !=  NULL)
131*4dc92747SCheng Sean Ye 		elpp = &(*elpp)->next;
132*4dc92747SCheng Sean Ye 	*elpp = newp;
133*4dc92747SCheng Sean Ye 	(void) cond_signal(&dl_cv);
134*4dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
135*4dc92747SCheng Sean Ye 
136*4dc92747SCheng Sean Ye 	return (0);
1370dc974a9SCathy Zhou }
1380dc974a9SCathy Zhou 
1390dc974a9SCathy Zhou static struct slm_mod_ops datalink_mod_ops = {
1400dc974a9SCathy Zhou 	SE_MAJOR_VERSION,
1410dc974a9SCathy Zhou 	SE_MINOR_VERSION,
1420dc974a9SCathy Zhou 	SE_MAX_RETRY_LIMIT,
1430dc974a9SCathy Zhou 	datalink_deliver_event
1440dc974a9SCathy Zhou };
1450dc974a9SCathy Zhou 
1460dc974a9SCathy Zhou struct slm_mod_ops *
1470dc974a9SCathy Zhou slm_init()
1480dc974a9SCathy Zhou {
149*4dc92747SCheng Sean Ye 	dl_events = NULL;
150*4dc92747SCheng Sean Ye 	dl_exiting = B_FALSE;
151*4dc92747SCheng Sean Ye 
1520dc974a9SCathy Zhou 	if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
1530dc974a9SCathy Zhou 		return (NULL);
1540dc974a9SCathy Zhou 
155*4dc92747SCheng Sean Ye 	if (thr_create(NULL, 0,  datalink_notify_thread, NULL, 0,
156*4dc92747SCheng Sean Ye 	    &dl_notify_tid) != 0) {
157*4dc92747SCheng Sean Ye 		(void) rcm_free_handle(rcm_hdl);
158*4dc92747SCheng Sean Ye 		return (NULL);
159*4dc92747SCheng Sean Ye 	}
160*4dc92747SCheng Sean Ye 
161*4dc92747SCheng Sean Ye 	(void) mutex_init(&dl_mx, USYNC_THREAD, NULL);
162*4dc92747SCheng Sean Ye 	(void) cond_init(&dl_cv, USYNC_THREAD, NULL);
163*4dc92747SCheng Sean Ye 
1640dc974a9SCathy Zhou 	return (&datalink_mod_ops);
1650dc974a9SCathy Zhou }
1660dc974a9SCathy Zhou 
1670dc974a9SCathy Zhou void
1680dc974a9SCathy Zhou slm_fini()
1690dc974a9SCathy Zhou {
170*4dc92747SCheng Sean Ye 	(void) mutex_lock(&dl_mx);
171*4dc92747SCheng Sean Ye 	dl_exiting = B_TRUE;
172*4dc92747SCheng Sean Ye 	(void) cond_signal(&dl_cv);
173*4dc92747SCheng Sean Ye 	(void) mutex_unlock(&dl_mx);
174*4dc92747SCheng Sean Ye 	(void) thr_join(dl_notify_tid, NULL, NULL);
175*4dc92747SCheng Sean Ye 
176*4dc92747SCheng Sean Ye 	(void) mutex_destroy(&dl_mx);
177*4dc92747SCheng Sean Ye 	(void) cond_destroy(&dl_cv);
1780dc974a9SCathy Zhou 	(void) rcm_free_handle(rcm_hdl);
1790dc974a9SCathy Zhou 	rcm_hdl = NULL;
1800dc974a9SCathy Zhou }
181