int dlpar_memory(struct pseries_hp_errorlog *hp_elog) { struct device_node *dn; struct property *prop; u32 count, drc_index; int rc; count = hp_elog->_drc_u.drc_count; drc_index = hp_elog->_drc_u.drc_index; lock_device_hotplug(); dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); if (!dn) { rc = -EINVAL; goto dlpar_memory_out; } prop = dlpar_clone_drconf_property(dn); if (!prop) { rc = -EINVAL; goto dlpar_memory_out; } switch (hp_elog->action) { case PSERIES_HP_ELOG_ACTION_ADD: if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) rc = dlpar_memory_add_by_count(count, prop); else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) rc = dlpar_memory_add_by_index(drc_index, prop); else rc = -EINVAL; break; case PSERIES_HP_ELOG_ACTION_REMOVE: if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) rc = dlpar_memory_remove_by_count(count, prop); else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) rc = dlpar_memory_remove_by_index(drc_index, prop); else rc = -EINVAL; break; default: pr_err("Invalid action (%d) specified\n", hp_elog->action); rc = -EINVAL; break; } dlpar_free_property(prop); dlpar_memory_out: of_node_put(dn); unlock_device_hotplug(); return rc; }
static struct property *dlpar_clone_property(struct property *prop, u32 prop_size) { struct property *new_prop; new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); if (!new_prop) return NULL; new_prop->name = kstrdup(prop->name, GFP_KERNEL); new_prop->value = kzalloc(prop_size, GFP_KERNEL); if (!new_prop->name || !new_prop->value) { dlpar_free_property(new_prop); return NULL; } memcpy(new_prop->value, prop->value, prop->length); new_prop->length = prop_size; of_property_set_flag(new_prop, OF_DYNAMIC); return new_prop; }