/* * Given the root node of the device tree. * compare it to the picl tree and add to it cpus * that are new. */ static void add_cpus(di_node_t di_node) { int err; di_node_t cnode; picl_nodehdl_t plath; cpu_lookup_t cpu_arg; char *nodename; err = ptree_get_node_by_path(PLATFORM_PATH, &plath); if (err != PICL_SUCCESS) return; for (cnode = di_child_node(di_node); cnode != DI_NODE_NIL; cnode = di_sibling_node(cnode)) { nodename = di_node_name(cnode); if (nodename == NULL) continue; if (strcmp(nodename, OBP_CPU) == 0) { cpu_arg.di_node = cnode; if (ptree_walk_tree_by_class(plath, PICL_CLASS_CPU, &cpu_arg, cpu_exists) != PICL_SUCCESS) return; if (cpu_arg.result == 0) /* * Didn't find a matching cpu, add it. */ (void) construct_cpu_node(plath, cnode); } } }
/* * Given the start node of the device tree. * find all cpus in the picl tree that don't have * device tree counterparts and remove them. */ static void remove_cpus(di_node_t di_start) { int err; picl_nodehdl_t plath; cpu_lookup_t cpu_arg; err = ptree_get_node_by_path(PLATFORM_PATH, &plath); if (err != PICL_SUCCESS) return; do { cpu_arg.di_node = di_start; cpu_arg.nodeh = 0; cpu_arg.result = 0; if (ptree_walk_tree_by_class(plath, PICL_CLASS_CPU, &cpu_arg, remove_cpu_candidate) != PICL_SUCCESS) return; if (cpu_arg.result == 1) { err = ptree_delete_node(cpu_arg.nodeh); if (err == PICL_SUCCESS) ptree_destroy_node(cpu_arg.nodeh); } } while (cpu_arg.result); }
void mdescplugin_init(void) { int status; status = ptree_get_root(&root_node); if (status != PICL_SUCCESS) { return; } mdp = mdesc_devinit(); if (mdp == NULL) return; /* * update the cpu configuration in case the snapshot cache used by the * devtree plugin is out of date. */ (void) update_devices(OBP_CPU, DEV_ADD); (void) update_devices(OBP_CPU, DEV_REMOVE); rootnode = md_root_node(mdp); /* * This is the start of the CPU property augmentation code. * add_cpu_prop and the rest of the CPU code lives in cpu_prop_update.c */ status = ptree_walk_tree_by_class(root_node, "cpu", NULL, add_cpu_prop); if (status != PICL_SUCCESS) { return; } signal_devtree(); (void) disk_discovery(); /* * register dsc_handler for both "sysevent-device-added" and * and for "sysevent-device-removed" PICL events */ (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, dsc_handler, NULL); (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, dsc_handler, NULL); (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE, dr_handler, NULL); mdesc_devfini(mdp); }
/* * Discovery event handler * respond to the picl events: * PICLEVENT_SYSEVENT_DEVICE_ADDED * PICLEVENT_SYSEVENT_DEVICE_REMOVED */ static void dsc_handler(const char *ename, const void *earg, size_t size, void *cookie) { nvlist_t *nvlp = NULL; char *path; disk_lookup_t lookup; int status; /* * retrieve the device's physical path from the event arg * and determine which disk (if any) we are working with */ if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) return; if (nvlist_lookup_string(nvlp, "devfs-path", &path)) return; lookup.path = strdup(path); lookup.disk = NULL; lookup.result = DISK_NOT_FOUND; status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup, find_disk); if (status != PICL_SUCCESS) { return; } if (lookup.result == DISK_FOUND) { if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) ptree_update_propval_by_name(lookup.disk, "State", (void *)strdup(CONFIGURED), PICL_PROPNAMELEN_MAX); else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) ptree_update_propval_by_name(lookup.disk, "State", (void *)strdup(UNCONFIGURED), PICL_PROPNAMELEN_MAX); } nvlist_free(nvlp); }
/* * Ontario SBL event handler, subscribed to: * PICLEVENT_SYSEVENT_DEVICE_ADDED * PICLEVENT_SYSEVENT_DEVICE_REMOVED */ static void piclsbl_handler(const char *ename, const void *earg, size_t size, void *cookie) { char *devfs_path; char hdd_location[PICL_PROPNAMELEN_MAX]; nvlist_t *nvlp = NULL; pcp_msg_t send_msg; pcp_msg_t recv_msg; pcp_sbl_req_t *req_ptr = NULL; pcp_sbl_resp_t *resp_ptr = NULL; int status = -1; int target; disk_lookup_t lookup; int channel_fd; /* * setup the request data to attach to the libpcp msg */ if ((req_ptr = (pcp_sbl_req_t *)umem_zalloc(sizeof (pcp_sbl_req_t), UMEM_DEFAULT)) == NULL) goto sbl_return; /* * This plugin serves to enable or disable the blue RAS * 'ok-to-remove' LED that is on each of the 4 disks on the * Ontario. We catch the event via the picl handler, and * if the event is DEVICE_ADDED for one of our onboard disks, * then we'll be turning off the LED. Otherwise, if the event * is DEVICE_REMOVED, then we turn it on. */ if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) req_ptr->sbl_action = PCP_SBL_DISABLE; else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) req_ptr->sbl_action = PCP_SBL_ENABLE; else goto sbl_return; /* * retrieve the device's physical path from the event payload */ if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) goto sbl_return; if (nvlist_lookup_string(nvlp, "devfs-path", &devfs_path)) goto sbl_return; /* * look for this disk in the picl tree, and if it's * location indicates that it's one of our internal * disks, then set sbl_id to incdicate which one. * otherwise, return as it is not one of our disks. */ lookup.path = strdup(devfs_path); lookup.disk = NULL; lookup.result = DISK_NOT_FOUND; /* first, find the disk */ status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup, cb_find_disk); if (status != PICL_SUCCESS) goto sbl_return; if (lookup.result == DISK_FOUND) { /* now, lookup it's location in the node */ status = ptree_get_propval_by_name(lookup.disk, "Location", (void *)&hdd_location, PICL_PROPNAMELEN_MAX); if (status != PICL_SUCCESS) { syslog(LOG_ERR, "piclsbl: failed hdd discovery"); goto sbl_return; } } if (strcmp(hdd_location, HDD0) == 0) { req_ptr->sbl_id = PCP_SBL_HDD0; target = 0; } else if (strcmp(hdd_location, HDD1) == 0) { req_ptr->sbl_id = PCP_SBL_HDD1; target = 1; } else if (strcmp(hdd_location, HDD2) == 0) { req_ptr->sbl_id = PCP_SBL_HDD2; target = 2; } else if (strcmp(hdd_location, HDD3) == 0) { req_ptr->sbl_id = PCP_SBL_HDD3; target = 3; } else { /* this is not one of the onboard disks */ goto sbl_return; } /* * check the onboard RAID configuration for this disk. if it is * a member of a RAID and is not the RAID itself, ignore the event */ if (check_raid(target)) goto sbl_return; /* * we have the information we need, init the platform channel. * the platform channel driver will only allow one connection * at a time on this socket. on the offchance that more than * one event comes in, we'll retry to initialize this connection * up to 3 times */ if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) < 0) { /* failed to init; wait and retry up to 3 times */ int s = PCPINIT_TIMEOUT; int retries = 0; while (++retries) { (void) sleep(s); if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) >= 0) break; else if (retries == 3) { syslog(LOG_ERR, "piclsbl: ", "SC channel initialization failed"); goto sbl_return; } /* continue */ } } /* * populate the message for libpcp */ send_msg.msg_type = PCP_SBL_CONTROL; send_msg.sub_type = NULL; send_msg.msg_len = sizeof (pcp_sbl_req_t); send_msg.msg_data = (uint8_t *)req_ptr; /* * send the request, receive the response */ if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg, PCPCOMM_TIMEOUT) < 0) { /* we either timed out or erred; either way try again */ int s = PCPCOMM_TIMEOUT; (void) sleep(s); if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg, PCPCOMM_TIMEOUT) < 0) { syslog(LOG_ERR, "piclsbl: communication failure"); goto sbl_return; } } /* * validate that this data was meant for us */ if (recv_msg.msg_type != PCP_SBL_CONTROL_R) { syslog(LOG_ERR, "piclsbl: unbound packet received"); goto sbl_return; } /* * verify that the LED action has taken place */ resp_ptr = (pcp_sbl_resp_t *)recv_msg.msg_data; if (resp_ptr->status == PCP_SBL_ERROR) { syslog(LOG_ERR, "piclsbl: OK2RM LED action error"); goto sbl_return; } /* * ensure the LED action taken is the one requested */ if ((req_ptr->sbl_action == PCP_SBL_DISABLE) && (resp_ptr->sbl_state != SBL_STATE_OFF)) syslog(LOG_ERR, "piclsbl: OK2RM LED not OFF after disk " "configuration"); else if ((req_ptr->sbl_action == PCP_SBL_ENABLE) && (resp_ptr->sbl_state != SBL_STATE_ON)) syslog(LOG_ERR, "piclsbl: OK2RM LED not ON after disk " "unconfiguration"); else if (resp_ptr->sbl_state == SBL_STATE_UNKNOWN) syslog(LOG_ERR, "piclsbl: OK2RM LED set to unknown state"); sbl_return: (*pcp_close_ptr)(channel_fd); if (req_ptr != NULL) umem_free(req_ptr, sizeof (pcp_sbl_req_t)); if (resp_ptr != NULL) free(resp_ptr); if (nvlp != NULL) nvlist_free(nvlp); }