10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51991Sheppo * Common Development and Distribution License (the "License").
61991Sheppo * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211991Sheppo
220Sstevel@tonic-gate /*
23*9764SMichael.Bergknoff@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * The MDESC picl plugin serves 2 different functionalities.
290Sstevel@tonic-gate * --The first is to look up certain CPU properties in the MDESC an to add
300Sstevel@tonic-gate * these properties in the already created CPU PICL nodes in the /platform
310Sstevel@tonic-gate * section of the tree.
320Sstevel@tonic-gate * --The second functionality is to create a /disk_discovery section of the
330Sstevel@tonic-gate * PICL tree which will have a disk node created for each disk node in the
340Sstevel@tonic-gate * machine description.
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include "mdescplugin.h"
385028Sfw157321 #include <libnvpair.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate #pragma init(mdescplugin_register) /* place in .init section */
410Sstevel@tonic-gate
420Sstevel@tonic-gate picl_nodehdl_t root_node;
430Sstevel@tonic-gate md_t *mdp;
440Sstevel@tonic-gate mde_cookie_t rootnode;
450Sstevel@tonic-gate
460Sstevel@tonic-gate void mdescplugin_init(void);
470Sstevel@tonic-gate void mdescplugin_fini(void);
48*9764SMichael.Bergknoff@Sun.COM static void signal_devtree(void);
490Sstevel@tonic-gate
500Sstevel@tonic-gate extern int add_cpu_prop(picl_nodehdl_t node, void *args);
510Sstevel@tonic-gate extern int disk_discovery(void);
520Sstevel@tonic-gate extern md_t *mdesc_devinit(void);
531991Sheppo extern void mdesc_devfini(md_t *mdp);
541991Sheppo extern int update_devices(char *dev, int op);
550Sstevel@tonic-gate
560Sstevel@tonic-gate picld_plugin_reg_t mdescplugin_reg = {
570Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1,
580Sstevel@tonic-gate PICLD_PLUGIN_CRITICAL,
590Sstevel@tonic-gate "mdesc_plugin",
600Sstevel@tonic-gate mdescplugin_init,
610Sstevel@tonic-gate mdescplugin_fini
620Sstevel@tonic-gate };
630Sstevel@tonic-gate
640Sstevel@tonic-gate #define DISK_FOUND 0x00
650Sstevel@tonic-gate #define DISK_NOT_FOUND 0x01
660Sstevel@tonic-gate
670Sstevel@tonic-gate typedef struct disk_lookup {
680Sstevel@tonic-gate char *path;
690Sstevel@tonic-gate picl_nodehdl_t disk;
700Sstevel@tonic-gate int result;
710Sstevel@tonic-gate } disk_lookup_t;
720Sstevel@tonic-gate
730Sstevel@tonic-gate int
find_disk(picl_nodehdl_t node,void * args)740Sstevel@tonic-gate find_disk(picl_nodehdl_t node, void *args)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate disk_lookup_t *lookup = (disk_lookup_t *)args;
770Sstevel@tonic-gate int status;
780Sstevel@tonic-gate char path[PICL_PROPNAMELEN_MAX];
790Sstevel@tonic-gate
800Sstevel@tonic-gate status = ptree_get_propval_by_name(node, "Path", (void *)&path,
810Sstevel@tonic-gate PICL_PROPNAMELEN_MAX);
820Sstevel@tonic-gate if (status != PICL_SUCCESS) {
830Sstevel@tonic-gate return (PICL_WALK_CONTINUE);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate
860Sstevel@tonic-gate if (strcmp(path, lookup->path) == 0) {
870Sstevel@tonic-gate lookup->disk = node;
880Sstevel@tonic-gate lookup->result = DISK_FOUND;
890Sstevel@tonic-gate return (PICL_WALK_TERMINATE);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate return (PICL_WALK_CONTINUE);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
961991Sheppo * DR event handler
971991Sheppo * respond to the picl events:
981991Sheppo * PICLEVENT_DR_AP_STATE_CHANGE
991991Sheppo */
1001991Sheppo static void
dr_handler(const char * ename,const void * earg,size_t size,void * cookie)1011991Sheppo dr_handler(const char *ename, const void *earg, size_t size, void *cookie)
1021991Sheppo {
1031991Sheppo nvlist_t *nvlp = NULL;
1041991Sheppo char *dtype;
1051991Sheppo char *ap_id;
1061991Sheppo char *hint;
1071991Sheppo
1081991Sheppo
1091991Sheppo if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) != 0) {
1101991Sheppo return;
1111991Sheppo }
1121991Sheppo
1131991Sheppo if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) {
1141991Sheppo return;
1151991Sheppo }
1161991Sheppo
1171991Sheppo if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
1181991Sheppo nvlist_free(nvlp);
1191991Sheppo return;
1201991Sheppo }
1211991Sheppo
1221991Sheppo if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
1231991Sheppo nvlist_free(nvlp);
1241991Sheppo return;
1251991Sheppo }
1261991Sheppo
1271991Sheppo if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id)) {
1281991Sheppo nvlist_free(nvlp);
1291991Sheppo return;
1301991Sheppo }
1311991Sheppo
1321991Sheppo if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint)) {
1331991Sheppo nvlist_free(nvlp);
1341991Sheppo return;
1351991Sheppo }
1361991Sheppo
1371991Sheppo mdp = mdesc_devinit();
1381991Sheppo if (mdp == NULL) {
1391991Sheppo nvlist_free(nvlp);
1401991Sheppo return;
1411991Sheppo }
1421991Sheppo
1431991Sheppo rootnode = md_root_node(mdp);
1441991Sheppo
1451991Sheppo if (strcmp(hint, DR_HINT_INSERT) == 0)
1461991Sheppo (void) update_devices(ap_id, DEV_ADD);
1471991Sheppo else if (strcmp(hint, DR_HINT_REMOVE) == 0)
1481991Sheppo (void) update_devices(ap_id, DEV_REMOVE);
1491991Sheppo
1501991Sheppo mdesc_devfini(mdp);
1511991Sheppo nvlist_free(nvlp);
152*9764SMichael.Bergknoff@Sun.COM
153*9764SMichael.Bergknoff@Sun.COM /*
154*9764SMichael.Bergknoff@Sun.COM * Signal the devtree plugin to add more cpu properties.
155*9764SMichael.Bergknoff@Sun.COM */
156*9764SMichael.Bergknoff@Sun.COM signal_devtree();
1571991Sheppo }
1581991Sheppo
1591991Sheppo /*
1600Sstevel@tonic-gate * Discovery event handler
1610Sstevel@tonic-gate * respond to the picl events:
1620Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_ADDED
1630Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_REMOVED
1640Sstevel@tonic-gate */
1650Sstevel@tonic-gate static void
dsc_handler(const char * ename,const void * earg,size_t size,void * cookie)1660Sstevel@tonic-gate dsc_handler(const char *ename, const void *earg, size_t size, void *cookie)
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate nvlist_t *nvlp = NULL;
1690Sstevel@tonic-gate char *path;
1700Sstevel@tonic-gate disk_lookup_t lookup;
1710Sstevel@tonic-gate int status;
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate * retrieve the device's physical path from the event arg
1750Sstevel@tonic-gate * and determine which disk (if any) we are working with
1760Sstevel@tonic-gate */
1770Sstevel@tonic-gate if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
1780Sstevel@tonic-gate return;
1790Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, "devfs-path", &path))
1800Sstevel@tonic-gate return;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate lookup.path = strdup(path);
1830Sstevel@tonic-gate lookup.disk = NULL;
1840Sstevel@tonic-gate lookup.result = DISK_NOT_FOUND;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
1870Sstevel@tonic-gate find_disk);
1880Sstevel@tonic-gate if (status != PICL_SUCCESS) {
1890Sstevel@tonic-gate return;
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate if (lookup.result == DISK_FOUND) {
1930Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
1940Sstevel@tonic-gate ptree_update_propval_by_name(lookup.disk, "State",
1950Sstevel@tonic-gate (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX);
1960Sstevel@tonic-gate else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
1970Sstevel@tonic-gate ptree_update_propval_by_name(lookup.disk, "State",
1980Sstevel@tonic-gate (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate nvlist_free(nvlp);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2045028Sfw157321 /*ARGSUSED*/
2055028Sfw157321 static void
mdesc_ev_completion_handler(char * ename,void * earg,size_t size)2065028Sfw157321 mdesc_ev_completion_handler(char *ename, void *earg, size_t size)
2075028Sfw157321 {
2085028Sfw157321 free(earg);
2095028Sfw157321 }
2105028Sfw157321
2115028Sfw157321 static void
signal_devtree(void)2125028Sfw157321 signal_devtree(void)
2135028Sfw157321 {
2145028Sfw157321 nvlist_t *nvl;
2155028Sfw157321 char *packed_nvl;
2165028Sfw157321 size_t nvl_size;
2175028Sfw157321 int status;
2185028Sfw157321
2195028Sfw157321 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL) != 0)
2205028Sfw157321 return;
2215028Sfw157321
2225028Sfw157321 /*
2235028Sfw157321 * Right now (Aug. 2007) snowbird is the only other platform
2245028Sfw157321 * which uses this event. Since that's a sun4u platform and
2255028Sfw157321 * this is sun4v we do not have to worry about possible confusion
2265028Sfw157321 * or interference between the two by grabbing this event for
2275028Sfw157321 * our own use here. This event is consumed by the devtree
2285028Sfw157321 * plug-in. The event signals the plug-in to re-run its
2295028Sfw157321 * cpu initialization function, which will cause it to add
2305028Sfw157321 * additional information to the cpu devtree nodes (particularly,
2315028Sfw157321 * the administrative state of the cpus.)
2325028Sfw157321 */
2335028Sfw157321 if (nvlist_add_string(nvl, PICLEVENTARG_EVENT_NAME,
2345028Sfw157321 PICLEVENT_CPU_STATE_CHANGE) != 0) {
2355028Sfw157321 free(nvl);
2365028Sfw157321 return;
2375028Sfw157321 }
2385028Sfw157321
2395028Sfw157321 /*
2405028Sfw157321 * The devtree plug-in needs to see a devfs path argument for
2415028Sfw157321 * any event it considers. We supply one here which is essentially
2425028Sfw157321 * a dummy since it is not processed by the devtree plug-in for
2435028Sfw157321 * this event.
2445028Sfw157321 */
2455028Sfw157321 if (nvlist_add_string(nvl, PICLEVENTARG_DEVFS_PATH, "/cpu") != 0) {
2465028Sfw157321 free(nvl);
2475028Sfw157321 return;
2485028Sfw157321 }
2495095Sfw157321 packed_nvl = NULL;
2505028Sfw157321 if (nvlist_pack(nvl, &packed_nvl, &nvl_size, NV_ENCODE_NATIVE,
2515095Sfw157321 0) != 0) {
2525028Sfw157321 free(nvl);
2535028Sfw157321 return;
2545028Sfw157321 }
2555028Sfw157321 if ((status = ptree_post_event(PICLEVENT_CPU_STATE_CHANGE,
2565028Sfw157321 packed_nvl, nvl_size, mdesc_ev_completion_handler)) !=
2575028Sfw157321 PICL_SUCCESS) {
2585028Sfw157321 free(nvl);
2595028Sfw157321 syslog(LOG_WARNING,
2605028Sfw157321 "signal_devtree: can't post cpu event: %d\n", status);
2615028Sfw157321 }
2625028Sfw157321 }
2635028Sfw157321
2640Sstevel@tonic-gate void
mdescplugin_init(void)2650Sstevel@tonic-gate mdescplugin_init(void)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate int status;
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate status = ptree_get_root(&root_node);
2700Sstevel@tonic-gate if (status != PICL_SUCCESS) {
2710Sstevel@tonic-gate return;
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate mdp = mdesc_devinit();
2750Sstevel@tonic-gate if (mdp == NULL)
2760Sstevel@tonic-gate return;
2770Sstevel@tonic-gate
2786902Smb158278 /*
2796902Smb158278 * update the cpu configuration in case the snapshot cache used by the
2806902Smb158278 * devtree plugin is out of date.
2816902Smb158278 */
2826902Smb158278 (void) update_devices(OBP_CPU, DEV_ADD);
2836902Smb158278 (void) update_devices(OBP_CPU, DEV_REMOVE);
2846902Smb158278
2850Sstevel@tonic-gate rootnode = md_root_node(mdp);
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate /*
2880Sstevel@tonic-gate * This is the start of the CPU property augmentation code.
2890Sstevel@tonic-gate * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c
2900Sstevel@tonic-gate */
2910Sstevel@tonic-gate status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop);
2920Sstevel@tonic-gate if (status != PICL_SUCCESS) {
2930Sstevel@tonic-gate return;
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2965028Sfw157321 signal_devtree();
2975028Sfw157321
2980Sstevel@tonic-gate (void) disk_discovery();
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * register dsc_handler for both "sysevent-device-added" and
3020Sstevel@tonic-gate * and for "sysevent-device-removed" PICL events
3030Sstevel@tonic-gate */
3040Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3050Sstevel@tonic-gate dsc_handler, NULL);
3060Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3070Sstevel@tonic-gate dsc_handler, NULL);
3081991Sheppo (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3091991Sheppo dr_handler, NULL);
3100Sstevel@tonic-gate
3111991Sheppo mdesc_devfini(mdp);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate void
mdescplugin_fini(void)3150Sstevel@tonic-gate mdescplugin_fini(void)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate /* unregister the event handler */
3180Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3190Sstevel@tonic-gate dsc_handler, NULL);
3200Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3210Sstevel@tonic-gate dsc_handler, NULL);
3221991Sheppo (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3231991Sheppo dr_handler, NULL);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate void
mdescplugin_register(void)3270Sstevel@tonic-gate mdescplugin_register(void)
3280Sstevel@tonic-gate {
3290Sstevel@tonic-gate picld_plugin_register(&mdescplugin_reg);
3300Sstevel@tonic-gate }
331