11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo 221ae08745Sheppo /* 23*535c87f8Smb158278 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 241ae08745Sheppo * Use is subject to license terms. 251ae08745Sheppo */ 261ae08745Sheppo 271ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 281ae08745Sheppo 291ae08745Sheppo #include "mdescplugin.h" 301ae08745Sheppo 311ae08745Sheppo static di_prom_handle_t ph = DI_PROM_HANDLE_NIL; 321ae08745Sheppo 331ae08745Sheppo typedef struct cpu_lookup { 341ae08745Sheppo di_node_t di_node; 351ae08745Sheppo picl_nodehdl_t nodeh; 361ae08745Sheppo int result; 371ae08745Sheppo } cpu_lookup_t; 381ae08745Sheppo 391ae08745Sheppo extern int add_cpu_prop(picl_nodehdl_t node, void *args); 401ae08745Sheppo extern md_t *mdesc_devinit(void); 411ae08745Sheppo 421ae08745Sheppo /* 431ae08745Sheppo * This function is identical to the one in the picldevtree plugin. 441ae08745Sheppo * Unfortunately we can't just reuse that code. 451ae08745Sheppo */ 46*535c87f8Smb158278 int 471ae08745Sheppo add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist, 481ae08745Sheppo unsigned int nrows) 491ae08745Sheppo { 501ae08745Sheppo ptree_propinfo_t propinfo; 511ae08745Sheppo picl_prophdl_t proph; 521ae08745Sheppo picl_prophdl_t tblh; 531ae08745Sheppo int err; 541ae08745Sheppo unsigned int i; 551ae08745Sheppo unsigned int j; 561ae08745Sheppo picl_prophdl_t *proprow; 571ae08745Sheppo int len; 581ae08745Sheppo 591ae08745Sheppo #define NCOLS_IN_STRING_TABLE 1 601ae08745Sheppo 611ae08745Sheppo err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 621ae08745Sheppo PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name, 631ae08745Sheppo NULL, NULL); 641ae08745Sheppo if (err != PICL_SUCCESS) 651ae08745Sheppo return (err); 661ae08745Sheppo 671ae08745Sheppo err = ptree_create_table(&tblh); 681ae08745Sheppo if (err != PICL_SUCCESS) 691ae08745Sheppo return (err); 701ae08745Sheppo 711ae08745Sheppo err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph); 721ae08745Sheppo if (err != PICL_SUCCESS) 731ae08745Sheppo return (err); 741ae08745Sheppo 751ae08745Sheppo proprow = alloca(sizeof (picl_prophdl_t) * nrows); 761ae08745Sheppo if (proprow == NULL) { 771ae08745Sheppo (void) ptree_destroy_prop(proph); 781ae08745Sheppo return (PICL_FAILURE); 791ae08745Sheppo } 801ae08745Sheppo 811ae08745Sheppo for (j = 0; j < nrows; ++j) { 821ae08745Sheppo len = strlen(strlist) + 1; 831ae08745Sheppo err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 841ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, len, name, 851ae08745Sheppo NULL, NULL); 861ae08745Sheppo if (err != PICL_SUCCESS) 871ae08745Sheppo break; 881ae08745Sheppo err = ptree_create_prop(&propinfo, strlist, &proprow[j]); 891ae08745Sheppo if (err != PICL_SUCCESS) 901ae08745Sheppo break; 911ae08745Sheppo strlist += len; 921ae08745Sheppo err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE, 931ae08745Sheppo &proprow[j]); 941ae08745Sheppo if (err != PICL_SUCCESS) 951ae08745Sheppo break; 961ae08745Sheppo } 971ae08745Sheppo 981ae08745Sheppo if (err != PICL_SUCCESS) { 991ae08745Sheppo for (i = 0; i < j; ++i) 1001ae08745Sheppo (void) ptree_destroy_prop(proprow[i]); 1011ae08745Sheppo (void) ptree_delete_prop(proph); 1021ae08745Sheppo (void) ptree_destroy_prop(proph); 1031ae08745Sheppo return (err); 1041ae08745Sheppo } 1051ae08745Sheppo 1061ae08745Sheppo return (PICL_SUCCESS); 1071ae08745Sheppo } 1081ae08745Sheppo 1091ae08745Sheppo /* 1101ae08745Sheppo * This function is identical to the one in the picldevtree plugin. 1111ae08745Sheppo * Unfortunately we can't just reuse that code. 1121ae08745Sheppo */ 1131ae08745Sheppo static void 1141ae08745Sheppo add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) 1151ae08745Sheppo { 1161ae08745Sheppo int instance; 1171ae08745Sheppo char *di_val; 1181ae08745Sheppo di_prop_t di_prop; 1191ae08745Sheppo int di_ptype; 1201ae08745Sheppo ptree_propinfo_t propinfo; 1211ae08745Sheppo 1221ae08745Sheppo instance = di_instance(di_node); 1231ae08745Sheppo (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1241ae08745Sheppo PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, 1251ae08745Sheppo NULL, NULL); 1261ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); 1271ae08745Sheppo 1281ae08745Sheppo di_val = di_bus_addr(di_node); 1291ae08745Sheppo if (di_val) { 1301ae08745Sheppo (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1311ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 1321ae08745Sheppo PICL_PROP_BUS_ADDR, NULL, NULL); 1331ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 1341ae08745Sheppo NULL); 1351ae08745Sheppo } 1361ae08745Sheppo 1371ae08745Sheppo di_val = di_binding_name(di_node); 1381ae08745Sheppo if (di_val) { 1391ae08745Sheppo (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1401ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 1411ae08745Sheppo PICL_PROP_BINDING_NAME, NULL, NULL); 1421ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 1431ae08745Sheppo NULL); 1441ae08745Sheppo } 1451ae08745Sheppo 1461ae08745Sheppo di_val = di_driver_name(di_node); 1471ae08745Sheppo if (di_val) { 1481ae08745Sheppo (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1491ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 1501ae08745Sheppo PICL_PROP_DRIVER_NAME, NULL, NULL); 1511ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 1521ae08745Sheppo NULL); 1531ae08745Sheppo } 1541ae08745Sheppo 1551ae08745Sheppo di_val = di_devfs_path(di_node); 1561ae08745Sheppo if (di_val) { 1571ae08745Sheppo (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1581ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 1591ae08745Sheppo PICL_PROP_DEVFS_PATH, NULL, NULL); 1601ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 1611ae08745Sheppo NULL); 1621ae08745Sheppo di_devfs_path_free(di_val); 1631ae08745Sheppo } 1641ae08745Sheppo 1651ae08745Sheppo for (di_prop = di_prop_next(di_node, DI_PROP_NIL); 1661ae08745Sheppo di_prop != DI_PROP_NIL; 1671ae08745Sheppo di_prop = di_prop_next(di_node, di_prop)) { 1681ae08745Sheppo 1691ae08745Sheppo di_val = di_prop_name(di_prop); 1701ae08745Sheppo di_ptype = di_prop_type(di_prop); 1711ae08745Sheppo switch (di_ptype) { 1721ae08745Sheppo case DI_PROP_TYPE_BOOLEAN: 1731ae08745Sheppo (void) ptree_init_propinfo(&propinfo, 1741ae08745Sheppo PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, 1751ae08745Sheppo PICL_READ, (size_t)0, di_val, NULL, NULL); 1761ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, 1771ae08745Sheppo NULL, NULL); 1781ae08745Sheppo break; 1791ae08745Sheppo case DI_PROP_TYPE_INT: { 1801ae08745Sheppo int *idata; 1811ae08745Sheppo int len; 1821ae08745Sheppo 1831ae08745Sheppo len = di_prop_ints(di_prop, &idata); 1841ae08745Sheppo if (len < 0) 1851ae08745Sheppo /* Recieved error, so ignore prop */ 1861ae08745Sheppo break; 1871ae08745Sheppo 1881ae08745Sheppo if (len == 1) 1891ae08745Sheppo (void) ptree_init_propinfo(&propinfo, 1901ae08745Sheppo PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, 1911ae08745Sheppo PICL_READ, len * sizeof (int), di_val, 1921ae08745Sheppo NULL, NULL); 1931ae08745Sheppo else 1941ae08745Sheppo (void) ptree_init_propinfo(&propinfo, 1951ae08745Sheppo PTREE_PROPINFO_VERSION, 1961ae08745Sheppo PICL_PTYPE_BYTEARRAY, PICL_READ, 1971ae08745Sheppo len * sizeof (int), di_val, 1981ae08745Sheppo NULL, NULL); 1991ae08745Sheppo 2001ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, 2011ae08745Sheppo idata, NULL); 2021ae08745Sheppo } 2031ae08745Sheppo break; 2041ae08745Sheppo case DI_PROP_TYPE_STRING: { 2051ae08745Sheppo char *sdata; 2061ae08745Sheppo int len; 2071ae08745Sheppo 2081ae08745Sheppo len = di_prop_strings(di_prop, &sdata); 2091ae08745Sheppo if (len < 0) 2101ae08745Sheppo break; 2111ae08745Sheppo 2121ae08745Sheppo if (len == 1) { 2131ae08745Sheppo (void) ptree_init_propinfo(&propinfo, 2141ae08745Sheppo PTREE_PROPINFO_VERSION, 2151ae08745Sheppo PICL_PTYPE_CHARSTRING, PICL_READ, 2161ae08745Sheppo strlen(sdata) + 1, di_val, 2171ae08745Sheppo NULL, NULL); 2181ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, 2191ae08745Sheppo &propinfo, sdata, NULL); 2201ae08745Sheppo } else { 2211ae08745Sheppo (void) add_string_list_prop(nodeh, di_val, 2221ae08745Sheppo sdata, len); 2231ae08745Sheppo } 2241ae08745Sheppo } 2251ae08745Sheppo break; 2261ae08745Sheppo case DI_PROP_TYPE_BYTE: { 2271ae08745Sheppo int len; 2281ae08745Sheppo unsigned char *bdata; 2291ae08745Sheppo 2301ae08745Sheppo len = di_prop_bytes(di_prop, &bdata); 2311ae08745Sheppo if (len < 0) 2321ae08745Sheppo break; 2331ae08745Sheppo (void) ptree_init_propinfo(&propinfo, 2341ae08745Sheppo PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, 2351ae08745Sheppo PICL_READ, len, di_val, NULL, NULL); 2361ae08745Sheppo (void) ptree_create_and_add_prop(nodeh, &propinfo, 2371ae08745Sheppo bdata, NULL); 2381ae08745Sheppo } 2391ae08745Sheppo break; 2401ae08745Sheppo case DI_PROP_TYPE_UNKNOWN: 2411ae08745Sheppo break; 2421ae08745Sheppo case DI_PROP_TYPE_UNDEF_IT: 2431ae08745Sheppo break; 2441ae08745Sheppo default: 2451ae08745Sheppo break; 2461ae08745Sheppo } 2471ae08745Sheppo } 2481ae08745Sheppo } 2491ae08745Sheppo 2501ae08745Sheppo /* 251*535c87f8Smb158278 * add OBP_REG property to picl cpu node if it's not already there. 252*535c87f8Smb158278 */ 253*535c87f8Smb158278 static void 254*535c87f8Smb158278 add_reg_prop(picl_nodehdl_t pn, di_node_t dn) 255*535c87f8Smb158278 { 256*535c87f8Smb158278 int reg_prop[SUN4V_CPU_REGSIZE]; 257*535c87f8Smb158278 int status; 258*535c87f8Smb158278 int dlen; 259*535c87f8Smb158278 int *pdata; 260*535c87f8Smb158278 ptree_propinfo_t propinfo; 261*535c87f8Smb158278 262*535c87f8Smb158278 status = ptree_get_propval_by_name(pn, OBP_REG, reg_prop, 263*535c87f8Smb158278 sizeof (reg_prop)); 264*535c87f8Smb158278 if (status == PICL_SUCCESS) { 265*535c87f8Smb158278 return; 266*535c87f8Smb158278 } 267*535c87f8Smb158278 dlen = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata); 268*535c87f8Smb158278 if (dlen < 0) { 269*535c87f8Smb158278 return; 270*535c87f8Smb158278 } 271*535c87f8Smb158278 status = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 272*535c87f8Smb158278 PICL_PTYPE_BYTEARRAY, PICL_READ, dlen * sizeof (int), OBP_REG, 273*535c87f8Smb158278 NULL, NULL); 274*535c87f8Smb158278 if (status != PICL_SUCCESS) { 275*535c87f8Smb158278 return; 276*535c87f8Smb158278 } 277*535c87f8Smb158278 (void) ptree_create_and_add_prop(pn, &propinfo, pdata, NULL); 278*535c87f8Smb158278 } 279*535c87f8Smb158278 280*535c87f8Smb158278 /* 2811ae08745Sheppo * Create a picl node of type cpu and fill it. 2821ae08745Sheppo * properties are filled from both the device tree and the 2831ae08745Sheppo * Machine description. 2841ae08745Sheppo */ 2851ae08745Sheppo static int 2861ae08745Sheppo construct_cpu_node(picl_nodehdl_t plath, di_node_t dn) 2871ae08745Sheppo { 2881ae08745Sheppo int err; 2891ae08745Sheppo char *nodename; 2901ae08745Sheppo picl_nodehdl_t anodeh; 2911ae08745Sheppo 2921ae08745Sheppo nodename = di_node_name(dn); /* PICL_PROP_NAME */ 2931ae08745Sheppo 2941ae08745Sheppo err = ptree_create_and_add_node(plath, nodename, PICL_CLASS_CPU, 2951ae08745Sheppo &anodeh); 2961ae08745Sheppo if (err != PICL_SUCCESS) 2971ae08745Sheppo return (err); 2981ae08745Sheppo 2991ae08745Sheppo add_devinfo_props(anodeh, dn); 300*535c87f8Smb158278 add_reg_prop(anodeh, dn); 3011ae08745Sheppo (void) add_cpu_prop(anodeh, NULL); 3021ae08745Sheppo 3031ae08745Sheppo return (err); 3041ae08745Sheppo } 3051ae08745Sheppo 3061ae08745Sheppo /* 3071ae08745Sheppo * Given a devinfo node find its reg property. 3081ae08745Sheppo */ 3091ae08745Sheppo static int 3101ae08745Sheppo get_reg_prop(di_node_t dn, int **pdata) 3111ae08745Sheppo { 3121ae08745Sheppo int dret = 0; 3131ae08745Sheppo 3141ae08745Sheppo dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, pdata); 3151ae08745Sheppo if (dret > 0) 3161ae08745Sheppo return (dret); 3171ae08745Sheppo 3181ae08745Sheppo if (!ph) 3191ae08745Sheppo return (0); 3201ae08745Sheppo dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, pdata); 3211ae08745Sheppo return (dret < 0? 0 : dret); 3221ae08745Sheppo } 3231ae08745Sheppo 3241ae08745Sheppo /* 3251ae08745Sheppo * Given a devinfo cpu node find its cpuid property. 3261ae08745Sheppo */ 3271ae08745Sheppo int 3281ae08745Sheppo get_cpuid(di_node_t di_node) 3291ae08745Sheppo { 3301ae08745Sheppo int len; 3311ae08745Sheppo int *idata; 3321ae08745Sheppo int dcpuid = -1; 3331ae08745Sheppo 3341ae08745Sheppo len = get_reg_prop(di_node, &idata); 3351ae08745Sheppo 3361ae08745Sheppo if (len != SUN4V_CPU_REGSIZE) 3371ae08745Sheppo return (dcpuid); 3381ae08745Sheppo if (len == SUN4V_CPU_REGSIZE) 3391ae08745Sheppo dcpuid = CFGHDL_TO_CPUID(idata[0]); 3401ae08745Sheppo 3411ae08745Sheppo return (dcpuid); 3421ae08745Sheppo } 3431ae08745Sheppo 3441ae08745Sheppo int 3451ae08745Sheppo find_cpu(di_node_t node, int cpuid) 3461ae08745Sheppo { 3471ae08745Sheppo int dcpuid; 3481ae08745Sheppo di_node_t cnode; 3491ae08745Sheppo char *nodename; 3501ae08745Sheppo 3511ae08745Sheppo for (cnode = di_child_node(node); cnode != DI_NODE_NIL; 3521ae08745Sheppo cnode = di_sibling_node(cnode)) { 3531ae08745Sheppo nodename = di_node_name(cnode); 3541ae08745Sheppo if (nodename == NULL) 3551ae08745Sheppo continue; 3561ae08745Sheppo if (strcmp(nodename, OBP_CPU) == 0) { 3571ae08745Sheppo dcpuid = get_cpuid(cnode); 3581ae08745Sheppo if (dcpuid == cpuid) { 3591ae08745Sheppo return (1); 3601ae08745Sheppo } 3611ae08745Sheppo } 3621ae08745Sheppo } 3631ae08745Sheppo return (0); 3641ae08745Sheppo } 3651ae08745Sheppo 3661ae08745Sheppo /* 3671ae08745Sheppo * Callback to the ptree walk function during remove_cpus. 3681ae08745Sheppo * As a part of the args receives a picl nodeh, searches 3691ae08745Sheppo * the device tree for a cpu whose cpuid matches the picl cpu node. 3701ae08745Sheppo * Sets arg struct's result to 1 if it failed to match and terminates 3711ae08745Sheppo * the walk. 3721ae08745Sheppo */ 3731ae08745Sheppo static int 3741ae08745Sheppo remove_cpu_candidate(picl_nodehdl_t nodeh, void *c_args) 3751ae08745Sheppo { 3761ae08745Sheppo di_node_t di_node; 3771ae08745Sheppo cpu_lookup_t *cpu_arg; 3781ae08745Sheppo int err; 3791ae08745Sheppo int pcpuid; 3801ae08745Sheppo int reg_prop[SUN4V_CPU_REGSIZE]; 3811ae08745Sheppo 3821ae08745Sheppo if (c_args == NULL) 3831ae08745Sheppo return (PICL_INVALIDARG); 3841ae08745Sheppo 3851ae08745Sheppo cpu_arg = c_args; 3861ae08745Sheppo di_node = cpu_arg->di_node; 3871ae08745Sheppo 3881ae08745Sheppo err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop, 3891ae08745Sheppo sizeof (reg_prop)); 3901ae08745Sheppo 3911ae08745Sheppo if (err != PICL_SUCCESS) { 3921ae08745Sheppo return (PICL_WALK_CONTINUE); 3931ae08745Sheppo } 3941ae08745Sheppo 3951ae08745Sheppo pcpuid = CFGHDL_TO_CPUID(reg_prop[0]); 3961ae08745Sheppo 3971ae08745Sheppo if (!find_cpu(di_node, pcpuid)) { 3981ae08745Sheppo cpu_arg->result = 1; 3991ae08745Sheppo cpu_arg->nodeh = nodeh; 4001ae08745Sheppo return (PICL_WALK_TERMINATE); 4011ae08745Sheppo } 4021ae08745Sheppo 4031ae08745Sheppo cpu_arg->result = 0; 4041ae08745Sheppo return (PICL_WALK_CONTINUE); 4051ae08745Sheppo } 4061ae08745Sheppo 4071ae08745Sheppo /* 4081ae08745Sheppo * Given the start node of the device tree. 4091ae08745Sheppo * find all cpus in the picl tree that don't have 4101ae08745Sheppo * device tree counterparts and remove them. 4111ae08745Sheppo */ 4121ae08745Sheppo static void 4131ae08745Sheppo remove_cpus(di_node_t di_start) 4141ae08745Sheppo { 4151ae08745Sheppo int err; 4161ae08745Sheppo picl_nodehdl_t plath; 4171ae08745Sheppo cpu_lookup_t cpu_arg; 4181ae08745Sheppo 4191ae08745Sheppo err = ptree_get_node_by_path(PLATFORM_PATH, &plath); 4201ae08745Sheppo if (err != PICL_SUCCESS) 4211ae08745Sheppo return; 4221ae08745Sheppo 4231ae08745Sheppo do { 4241ae08745Sheppo cpu_arg.di_node = di_start; 4251ae08745Sheppo cpu_arg.nodeh = 0; 4261ae08745Sheppo cpu_arg.result = 0; 4271ae08745Sheppo 4281ae08745Sheppo if (ptree_walk_tree_by_class(plath, 4291ae08745Sheppo PICL_CLASS_CPU, &cpu_arg, remove_cpu_candidate) 4301ae08745Sheppo != PICL_SUCCESS) 4311ae08745Sheppo return; 4321ae08745Sheppo 4331ae08745Sheppo if (cpu_arg.result == 1) { 4341ae08745Sheppo err = ptree_delete_node(cpu_arg.nodeh); 4351ae08745Sheppo if (err == PICL_SUCCESS) 4361ae08745Sheppo ptree_destroy_node(cpu_arg.nodeh); 4371ae08745Sheppo } 4381ae08745Sheppo } while (cpu_arg.result); 4391ae08745Sheppo } 4401ae08745Sheppo 4411ae08745Sheppo /* 4421ae08745Sheppo * Callback to the ptree walk function during add_cpus. 4431ae08745Sheppo * As a part of the args receives a cpu di_node, compares 4441ae08745Sheppo * each picl cpu node's cpuid to the device tree node's cpuid. 4451ae08745Sheppo * Sets arg struct's result to 1 on a match. 4461ae08745Sheppo */ 4471ae08745Sheppo static int 4481ae08745Sheppo cpu_exists(picl_nodehdl_t nodeh, void *c_args) 4491ae08745Sheppo { 4501ae08745Sheppo di_node_t di_node; 4511ae08745Sheppo cpu_lookup_t *cpu_arg; 4521ae08745Sheppo int err; 4531ae08745Sheppo int dcpuid, pcpuid; 4541ae08745Sheppo int reg_prop[4]; 4551ae08745Sheppo 4561ae08745Sheppo if (c_args == NULL) 4571ae08745Sheppo return (PICL_INVALIDARG); 4581ae08745Sheppo 4591ae08745Sheppo cpu_arg = c_args; 4601ae08745Sheppo di_node = cpu_arg->di_node; 4611ae08745Sheppo dcpuid = get_cpuid(di_node); 4621ae08745Sheppo 4631ae08745Sheppo err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop, 4641ae08745Sheppo sizeof (reg_prop)); 4651ae08745Sheppo 4661ae08745Sheppo if (err != PICL_SUCCESS) 4671ae08745Sheppo return (PICL_WALK_CONTINUE); 4681ae08745Sheppo 4691ae08745Sheppo pcpuid = CFGHDL_TO_CPUID(reg_prop[0]); 4701ae08745Sheppo 4711ae08745Sheppo if (dcpuid == pcpuid) { 4721ae08745Sheppo cpu_arg->result = 1; 4731ae08745Sheppo return (PICL_WALK_TERMINATE); 4741ae08745Sheppo } 4751ae08745Sheppo 4761ae08745Sheppo cpu_arg->result = 0; 4771ae08745Sheppo return (PICL_WALK_CONTINUE); 4781ae08745Sheppo } 4791ae08745Sheppo 4801ae08745Sheppo /* 4811ae08745Sheppo * Given the root node of the device tree. 4821ae08745Sheppo * compare it to the picl tree and add to it cpus 4831ae08745Sheppo * that are new. 4841ae08745Sheppo */ 4851ae08745Sheppo static void 4861ae08745Sheppo add_cpus(di_node_t di_node) 4871ae08745Sheppo { 4881ae08745Sheppo int err; 4891ae08745Sheppo di_node_t cnode; 4901ae08745Sheppo picl_nodehdl_t plath; 4911ae08745Sheppo cpu_lookup_t cpu_arg; 4921ae08745Sheppo char *nodename; 4931ae08745Sheppo 4941ae08745Sheppo err = ptree_get_node_by_path(PLATFORM_PATH, &plath); 4951ae08745Sheppo if (err != PICL_SUCCESS) 4961ae08745Sheppo return; 4971ae08745Sheppo 4981ae08745Sheppo for (cnode = di_child_node(di_node); cnode != DI_NODE_NIL; 4991ae08745Sheppo cnode = di_sibling_node(cnode)) { 5001ae08745Sheppo nodename = di_node_name(cnode); 5011ae08745Sheppo if (nodename == NULL) 5021ae08745Sheppo continue; 5031ae08745Sheppo if (strcmp(nodename, OBP_CPU) == 0) { 5041ae08745Sheppo cpu_arg.di_node = cnode; 5051ae08745Sheppo 5061ae08745Sheppo if (ptree_walk_tree_by_class(plath, 5071ae08745Sheppo PICL_CLASS_CPU, &cpu_arg, cpu_exists) 5081ae08745Sheppo != PICL_SUCCESS) 5091ae08745Sheppo return; 5101ae08745Sheppo 5111ae08745Sheppo if (cpu_arg.result == 0) 5121ae08745Sheppo /* 5131ae08745Sheppo * Didn't find a matching cpu, add it. 5141ae08745Sheppo */ 5151ae08745Sheppo (void) construct_cpu_node(plath, 5161ae08745Sheppo cnode); 5171ae08745Sheppo } 5181ae08745Sheppo } 5191ae08745Sheppo } 5201ae08745Sheppo 5211ae08745Sheppo /* 5221ae08745Sheppo * Handle DR events. Only supports cpu add and remove. 5231ae08745Sheppo */ 5241ae08745Sheppo int 5251ae08745Sheppo update_devices(char *dev, int op) 5261ae08745Sheppo { 5271ae08745Sheppo di_node_t di_root; 5281ae08745Sheppo 5291ae08745Sheppo if ((di_root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) 5301ae08745Sheppo return (PICL_FAILURE); 5311ae08745Sheppo 5321ae08745Sheppo if ((ph = di_prom_init()) == NULL) 5331ae08745Sheppo return (PICL_FAILURE); 5341ae08745Sheppo 5351ae08745Sheppo if (op == DEV_ADD) { 5361ae08745Sheppo if (strcmp(dev, OBP_CPU) == 0) 5371ae08745Sheppo add_cpus(di_root); 5381ae08745Sheppo } 5391ae08745Sheppo 5401ae08745Sheppo if (op == DEV_REMOVE) { 5411ae08745Sheppo if (strcmp(dev, OBP_CPU) == 0) 5421ae08745Sheppo remove_cpus(di_root); 5431ae08745Sheppo } 5441ae08745Sheppo 5451ae08745Sheppo di_fini(di_root); 5461ae08745Sheppo di_prom_fini(ph); 5471ae08745Sheppo return (PICL_SUCCESS); 5481ae08745Sheppo } 549