17323SCathy.Zhou@Sun.COM /*
27323SCathy.Zhou@Sun.COM * CDDL HEADER START
37323SCathy.Zhou@Sun.COM *
47323SCathy.Zhou@Sun.COM * The contents of this file are subject to the terms of the
57323SCathy.Zhou@Sun.COM * Common Development and Distribution License (the "License").
67323SCathy.Zhou@Sun.COM * You may not use this file except in compliance with the License.
77323SCathy.Zhou@Sun.COM *
87323SCathy.Zhou@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97323SCathy.Zhou@Sun.COM * or http://www.opensolaris.org/os/licensing.
107323SCathy.Zhou@Sun.COM * See the License for the specific language governing permissions
117323SCathy.Zhou@Sun.COM * and limitations under the License.
127323SCathy.Zhou@Sun.COM *
137323SCathy.Zhou@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147323SCathy.Zhou@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157323SCathy.Zhou@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167323SCathy.Zhou@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177323SCathy.Zhou@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187323SCathy.Zhou@Sun.COM *
197323SCathy.Zhou@Sun.COM * CDDL HEADER END
207323SCathy.Zhou@Sun.COM */
217323SCathy.Zhou@Sun.COM /*
228698SCathy.Zhou@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237323SCathy.Zhou@Sun.COM * Use is subject to license terms.
247323SCathy.Zhou@Sun.COM */
257323SCathy.Zhou@Sun.COM
267323SCathy.Zhou@Sun.COM /*
277323SCathy.Zhou@Sun.COM * datalink syseventd module.
287323SCathy.Zhou@Sun.COM *
297323SCathy.Zhou@Sun.COM * The purpose of this module is to identify all datalink related events,
307323SCathy.Zhou@Sun.COM * and react accordingly.
317323SCathy.Zhou@Sun.COM */
327323SCathy.Zhou@Sun.COM
337323SCathy.Zhou@Sun.COM #include <errno.h>
347323SCathy.Zhou@Sun.COM #include <sys/sysevent/eventdefs.h>
357323SCathy.Zhou@Sun.COM #include <string.h>
367323SCathy.Zhou@Sun.COM #include <libnvpair.h>
377323SCathy.Zhou@Sun.COM #include <librcm.h>
387323SCathy.Zhou@Sun.COM #include <libsysevent.h>
39*10371SStephen.Hanson@Sun.COM #include "sysevent_signal.h"
407323SCathy.Zhou@Sun.COM
418827SSean.Ye@Sun.COM extern void syseventd_err_print(char *, ...);
428827SSean.Ye@Sun.COM
438827SSean.Ye@Sun.COM struct event_list {
448827SSean.Ye@Sun.COM nvlist_t *ev;
458827SSean.Ye@Sun.COM struct event_list *next;
468827SSean.Ye@Sun.COM };
478827SSean.Ye@Sun.COM
487323SCathy.Zhou@Sun.COM static rcm_handle_t *rcm_hdl = NULL;
498827SSean.Ye@Sun.COM static boolean_t dl_exiting;
508827SSean.Ye@Sun.COM static thread_t dl_notify_tid;
518827SSean.Ye@Sun.COM static mutex_t dl_mx;
528827SSean.Ye@Sun.COM static cond_t dl_cv;
538827SSean.Ye@Sun.COM static struct event_list *dl_events;
548827SSean.Ye@Sun.COM
558827SSean.Ye@Sun.COM /* ARGSUSED */
568827SSean.Ye@Sun.COM static void *
datalink_notify_thread(void * arg)578827SSean.Ye@Sun.COM datalink_notify_thread(void *arg)
588827SSean.Ye@Sun.COM {
598827SSean.Ye@Sun.COM struct event_list *tmp_events, *ep;
608827SSean.Ye@Sun.COM
618827SSean.Ye@Sun.COM (void) mutex_lock(&dl_mx);
628827SSean.Ye@Sun.COM
638827SSean.Ye@Sun.COM while (! dl_exiting || dl_events != NULL) {
648827SSean.Ye@Sun.COM if (dl_events == NULL) {
658827SSean.Ye@Sun.COM (void) cond_wait(&dl_cv, &dl_mx);
668827SSean.Ye@Sun.COM continue;
678827SSean.Ye@Sun.COM }
688827SSean.Ye@Sun.COM
698827SSean.Ye@Sun.COM tmp_events = dl_events;
708827SSean.Ye@Sun.COM dl_events = NULL;
718827SSean.Ye@Sun.COM
728827SSean.Ye@Sun.COM (void) mutex_unlock(&dl_mx);
738827SSean.Ye@Sun.COM
748827SSean.Ye@Sun.COM while (tmp_events != NULL) {
75*10371SStephen.Hanson@Sun.COM struct sigaction cbuf, dfl;
76*10371SStephen.Hanson@Sun.COM
77*10371SStephen.Hanson@Sun.COM /*
78*10371SStephen.Hanson@Sun.COM * Ignore SIGCLD for the
79*10371SStephen.Hanson@Sun.COM * duration of the rcm_notify_event call.
80*10371SStephen.Hanson@Sun.COM */
81*10371SStephen.Hanson@Sun.COM (void) memset(&dfl, 0, sizeof (dfl));
82*10371SStephen.Hanson@Sun.COM dfl.sa_handler = SIG_IGN;
83*10371SStephen.Hanson@Sun.COM (void) sigaction(SIGCHLD, &dfl, &cbuf);
84*10371SStephen.Hanson@Sun.COM
858827SSean.Ye@Sun.COM /*
868827SSean.Ye@Sun.COM * Send the PHYSLINK_NEW event to network_rcm to update
878827SSean.Ye@Sun.COM * the network devices cache accordingly.
888827SSean.Ye@Sun.COM */
898827SSean.Ye@Sun.COM if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_PHYSLINK_NEW,
908827SSean.Ye@Sun.COM 0, tmp_events->ev, NULL) != RCM_SUCCESS)
91*10371SStephen.Hanson@Sun.COM syseventd_err_print("datalink_mod: Can not "
928827SSean.Ye@Sun.COM "notify event: %s\n", strerror(errno));
938827SSean.Ye@Sun.COM
94*10371SStephen.Hanson@Sun.COM (void) sigaction(SIGCHLD, &cbuf, NULL);
958827SSean.Ye@Sun.COM ep = tmp_events;
968827SSean.Ye@Sun.COM tmp_events = tmp_events->next;
978827SSean.Ye@Sun.COM nvlist_free(ep->ev);
988827SSean.Ye@Sun.COM free(ep);
998827SSean.Ye@Sun.COM }
1008827SSean.Ye@Sun.COM
1018827SSean.Ye@Sun.COM (void) mutex_lock(&dl_mx);
1028827SSean.Ye@Sun.COM }
1038827SSean.Ye@Sun.COM
1048827SSean.Ye@Sun.COM (void) mutex_unlock(&dl_mx);
1058827SSean.Ye@Sun.COM
1068827SSean.Ye@Sun.COM return (NULL);
1078827SSean.Ye@Sun.COM }
1087323SCathy.Zhou@Sun.COM
1097323SCathy.Zhou@Sun.COM /*ARGSUSED*/
1107323SCathy.Zhou@Sun.COM static int
datalink_deliver_event(sysevent_t * ev,int unused)1117323SCathy.Zhou@Sun.COM datalink_deliver_event(sysevent_t *ev, int unused)
1127323SCathy.Zhou@Sun.COM {
1137323SCathy.Zhou@Sun.COM const char *class = sysevent_get_class_name(ev);
1147323SCathy.Zhou@Sun.COM const char *subclass = sysevent_get_subclass_name(ev);
1157323SCathy.Zhou@Sun.COM nvlist_t *nvl;
1168827SSean.Ye@Sun.COM struct event_list *newp, **elpp;
1177323SCathy.Zhou@Sun.COM
1187323SCathy.Zhou@Sun.COM if (strcmp(class, EC_DATALINK) != 0 ||
1197323SCathy.Zhou@Sun.COM strcmp(subclass, ESC_DATALINK_PHYS_ADD) != 0) {
1207323SCathy.Zhou@Sun.COM return (0);
1217323SCathy.Zhou@Sun.COM }
1227323SCathy.Zhou@Sun.COM
1237323SCathy.Zhou@Sun.COM if (sysevent_get_attr_list(ev, &nvl) != 0)
1247323SCathy.Zhou@Sun.COM return (EINVAL);
1257323SCathy.Zhou@Sun.COM
1268698SCathy.Zhou@Sun.COM /*
1278827SSean.Ye@Sun.COM * rcm_notify_event() needs to be called asynchronously otherwise when
1288827SSean.Ye@Sun.COM * sysevent queue is full, deadlock will happen.
1298698SCathy.Zhou@Sun.COM */
1308827SSean.Ye@Sun.COM if ((newp = malloc(sizeof (struct event_list))) == NULL)
1318827SSean.Ye@Sun.COM return (ENOMEM);
1328827SSean.Ye@Sun.COM
1338827SSean.Ye@Sun.COM newp->ev = nvl;
1348827SSean.Ye@Sun.COM newp->next = NULL;
1357323SCathy.Zhou@Sun.COM
1368827SSean.Ye@Sun.COM /*
1378827SSean.Ye@Sun.COM * queue up at the end of the event list and signal notify_thread to
1388827SSean.Ye@Sun.COM * process it.
1398827SSean.Ye@Sun.COM */
1408827SSean.Ye@Sun.COM (void) mutex_lock(&dl_mx);
1418827SSean.Ye@Sun.COM elpp = &dl_events;
1428827SSean.Ye@Sun.COM while (*elpp != NULL)
1438827SSean.Ye@Sun.COM elpp = &(*elpp)->next;
1448827SSean.Ye@Sun.COM *elpp = newp;
1458827SSean.Ye@Sun.COM (void) cond_signal(&dl_cv);
1468827SSean.Ye@Sun.COM (void) mutex_unlock(&dl_mx);
1478827SSean.Ye@Sun.COM
1488827SSean.Ye@Sun.COM return (0);
1497323SCathy.Zhou@Sun.COM }
1507323SCathy.Zhou@Sun.COM
1517323SCathy.Zhou@Sun.COM static struct slm_mod_ops datalink_mod_ops = {
1527323SCathy.Zhou@Sun.COM SE_MAJOR_VERSION,
1537323SCathy.Zhou@Sun.COM SE_MINOR_VERSION,
1547323SCathy.Zhou@Sun.COM SE_MAX_RETRY_LIMIT,
1557323SCathy.Zhou@Sun.COM datalink_deliver_event
1567323SCathy.Zhou@Sun.COM };
1577323SCathy.Zhou@Sun.COM
1587323SCathy.Zhou@Sun.COM struct slm_mod_ops *
slm_init()1597323SCathy.Zhou@Sun.COM slm_init()
1607323SCathy.Zhou@Sun.COM {
1618827SSean.Ye@Sun.COM dl_events = NULL;
1628827SSean.Ye@Sun.COM dl_exiting = B_FALSE;
1638827SSean.Ye@Sun.COM
1647323SCathy.Zhou@Sun.COM if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
1657323SCathy.Zhou@Sun.COM return (NULL);
1667323SCathy.Zhou@Sun.COM
1678827SSean.Ye@Sun.COM if (thr_create(NULL, 0, datalink_notify_thread, NULL, 0,
1688827SSean.Ye@Sun.COM &dl_notify_tid) != 0) {
1698827SSean.Ye@Sun.COM (void) rcm_free_handle(rcm_hdl);
1708827SSean.Ye@Sun.COM return (NULL);
1718827SSean.Ye@Sun.COM }
1728827SSean.Ye@Sun.COM
1738827SSean.Ye@Sun.COM (void) mutex_init(&dl_mx, USYNC_THREAD, NULL);
1748827SSean.Ye@Sun.COM (void) cond_init(&dl_cv, USYNC_THREAD, NULL);
1758827SSean.Ye@Sun.COM
1767323SCathy.Zhou@Sun.COM return (&datalink_mod_ops);
1777323SCathy.Zhou@Sun.COM }
1787323SCathy.Zhou@Sun.COM
1797323SCathy.Zhou@Sun.COM void
slm_fini()1807323SCathy.Zhou@Sun.COM slm_fini()
1817323SCathy.Zhou@Sun.COM {
1828827SSean.Ye@Sun.COM (void) mutex_lock(&dl_mx);
1838827SSean.Ye@Sun.COM dl_exiting = B_TRUE;
1848827SSean.Ye@Sun.COM (void) cond_signal(&dl_cv);
1858827SSean.Ye@Sun.COM (void) mutex_unlock(&dl_mx);
1868827SSean.Ye@Sun.COM (void) thr_join(dl_notify_tid, NULL, NULL);
1878827SSean.Ye@Sun.COM
1888827SSean.Ye@Sun.COM (void) mutex_destroy(&dl_mx);
1898827SSean.Ye@Sun.COM (void) cond_destroy(&dl_cv);
1907323SCathy.Zhou@Sun.COM (void) rcm_free_handle(rcm_hdl);
1917323SCathy.Zhou@Sun.COM rcm_hdl = NULL;
1927323SCathy.Zhou@Sun.COM }
193