arch/powerpc/platforms/pseries/mobility.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/pseries/mobility.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/pseries/mobility.c
Extension
.c
Size
19242 bytes
Lines
833
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

device_initcall(register_nmi_wd_lpm_factor_sysctl);
#endif /* CONFIG_SYSCTL */
#endif /* CONFIG_PPC_WATCHDOG */

static int mobility_rtas_call(int token, char *buf, s32 scope)
{
	int rc;

	spin_lock(&rtas_data_buf_lock);

	memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
	rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
	memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);

	spin_unlock(&rtas_data_buf_lock);
	return rc;
}

static int delete_dt_node(struct device_node *dn)
{
	struct device_node *pdn;
	bool is_platfac;

	pdn = of_get_parent(dn);
	is_platfac = of_node_is_type(dn, "ibm,platform-facilities") ||
		     of_node_is_type(pdn, "ibm,platform-facilities");
	of_node_put(pdn);

	/*
	 * The drivers that bind to nodes in the platform-facilities
	 * hierarchy don't support node removal, and the removal directive
	 * from firmware is always followed by an add of an equivalent
	 * node. The capability (e.g. RNG, encryption, compression)
	 * represented by the node is never interrupted by the migration.
	 * So ignore changes to this part of the tree.
	 */
	if (is_platfac) {
		pr_notice("ignoring remove operation for %pOFfp\n", dn);
		return 0;
	}

	pr_debug("removing node %pOFfp\n", dn);
	dlpar_detach_node(dn);
	return 0;
}

static int update_dt_property(struct device_node *dn, struct property **prop,
			      const char *name, u32 vd, char *value)
{
	struct property *new_prop = *prop;
	int more = 0;

	/* A negative 'vd' value indicates that only part of the new property
	 * value is contained in the buffer and we need to call
	 * ibm,update-properties again to get the rest of the value.
	 *
	 * A negative value is also the two's compliment of the actual value.
	 */
	if (vd & 0x80000000) {
		vd = ~vd + 1;
		more = 1;
	}

	if (new_prop) {
		/* partial property fixup */
		char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
		if (!new_data)
			return -ENOMEM;

		memcpy(new_data, new_prop->value, new_prop->length);
		memcpy(new_data + new_prop->length, value, vd);

		kfree(new_prop->value);
		new_prop->value = new_data;
		new_prop->length += vd;
	} else {
		new_prop = kzalloc_obj(*new_prop);
		if (!new_prop)
			return -ENOMEM;

		new_prop->name = kstrdup(name, GFP_KERNEL);
		if (!new_prop->name) {
			kfree(new_prop);
			return -ENOMEM;
		}

		new_prop->length = vd;
		new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
		if (!new_prop->value) {
			kfree(new_prop->name);

Annotation

Implementation Notes