// SPDX-License-Identifier: GPL-2.0-only /* * Support for dynamic reconfiguration for PCI, Memory, and CPU * Hotplug and Dynamic Logical Partitioning on RPA platforms. * * Copyright (C) 2009 Nathan Fontenot * Copyright (C) 2009 IBM Corporation
*/
case NEXT_PROPERTY:
property = dlpar_parse_cc_property(ccwa); if (!property) goto cc_error;
if (!last_dn->properties)
last_dn->properties = property; else
last_property->next = property;
last_property = property; break;
case PREV_PARENT:
last_dn = last_dn->parent; break;
case MORE_MEMORY: case ERR_CFG_USE: default:
printk(KERN_ERR "Unexpected Error (%d) " "returned from configure-connector\n", rc); goto cc_error;
}
} while (rc);
cc_error:
rtas_work_area_free(work_area);
if (rc) { if (first_dn)
dlpar_free_cc_nodes(first_dn);
return NULL;
}
return first_dn;
}
int dlpar_attach_node(struct device_node *dn, struct device_node *parent)
{ int rc;
dn->parent = parent;
rc = of_attach_node(dn); if (rc) {
printk(KERN_ERR "Failed to add device node %pOF\n", dn); return rc;
}
return 0;
}
int dlpar_detach_node(struct device_node *dn)
{ struct device_node *child; int rc;
for_each_node_with_property(np, "ibm,drc-info") {
info = of_find_property(np, "ibm,drc-info", NULL); if (info == NULL) { /* XXX can this happen? */
of_node_put(np); return NULL;
}
value = of_prop_next_u32(info, NULL, &count); if (value == NULL) continue;
value++; for (i = 0; i < count; i++) { if (of_read_drc_info_cell(&info, &value, &drc)) break; if (index > drc.last_drc_index) continue;
node_index = drc.drc_index_start; for (j = 0; j < drc.num_sequential_elems; j++) { if (index == node_index) return np;
node_index += drc.sequential_inc;
}
}
}
return NULL;
}
staticstruct device_node *
get_device_node_with_drc_indexes(u32 drc_index)
{ struct device_node *np = NULL;
u32 nr_indexes, index; int i, rc;
for_each_node_with_property(np, "ibm,drc-indexes") { /* * First element in the array is the total number of * DRC indexes returned.
*/
rc = of_property_read_u32_index(np, "ibm,drc-indexes",
0, &nr_indexes); if (rc) goto out_put_np;
/* * Retrieve DRC index from the list and return the * device node if matched with the specified index.
*/ for (i = 0; i < nr_indexes; i++) {
rc = of_property_read_u32_index(np, "ibm,drc-indexes",
i+1, &index); if (rc) goto out_put_np;
/* * Do not add device node(s) if already exists in the * device tree.
*/
np = get_device_node_with_drc_index(index); if (np) {
pr_err("%s: Adding device node for index (%d), but " "already exists in the device tree\n",
__func__, index);
rc = -EINVAL; goto out;
}
/* * Recent FW provides ibm,drc-info property. So search * for the user specified DRC index from ibm,drc-info * property. If this property is not available, search * in the indexes array from ibm,drc-indexes property.
*/
np = get_device_node_with_drc_info(index);
if (!np) {
np = get_device_node_with_drc_indexes(index); if (!np) return -EIO;
}
/* Next, configure the connector. */
nodes = dlpar_configure_connector(cpu_to_be32(index), np); if (!nodes) {
rc = -EIO; goto out;
}
/* * Add the new nodes from dlpar_configure_connector() onto * the device-tree.
*/
of_changeset_init(&ocs);
rc = dlpar_changeset_attach_cc_nodes(&ocs, nodes);
if (!rc)
rc = of_changeset_apply(&ocs); else
dlpar_free_cc_nodes(nodes);
args = argbuf = kstrdup(buf, GFP_KERNEL); if (!argbuf) return -ENOMEM;
/* * Parse out the request from the user, this will be in the form: * <resource> <action> <id_type> <id>
*/
rc = dlpar_parse_resource(&args, &hp_elog); if (rc) goto dlpar_store_out;
rc = dlpar_parse_action(&args, &hp_elog); if (rc) goto dlpar_store_out;
rc = dlpar_parse_id_type(&args, &hp_elog); if (rc) goto dlpar_store_out;
rc = handle_dlpar_errorlog(&hp_elog);
dlpar_store_out:
kfree(argbuf);
if (rc)
pr_err("Could not handle DLPAR request \"%s\"\n", buf);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.