Beispiel #1
0
/**
 * device_property_read_string_array - return a string array property of device
 * @dev: Device to get the property of
 * @propname: Name of the property
 * @val: The values are stored here
 * @nval: Size of the @val array
 *
 * Function reads an array of string properties with @propname from the device
 * firmware description and stores them to @val if found.
 *
 * Return: %0 if the property was found (success),
 *	   %-EINVAL if given arguments are not valid,
 *	   %-ENODATA if the property does not have a value,
 *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
 *	   %-EOVERFLOW if the size of the property is not as expected.
 */
int device_property_read_string_array(struct device *dev, const char *propname,
				      const char **val, size_t nval)
{
	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
		of_property_read_string_array(dev->of_node, propname, val, nval) :
		acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
				   DEV_PROP_STRING, val, nval);
}
Beispiel #2
0
/**
 * fwnode_property_read_string_array - return string array property of a node
 * @fwnode: Firmware node to get the property of
 * @propname: Name of the property
 * @val: The values are stored here
 * @nval: Size of the @val array
 *
 * Read an string list property @propname from the given firmware node and store
 * them to @val if found.
 *
 * Return: %0 if the property was found (success),
 *	   %-EINVAL if given arguments are not valid,
 *	   %-ENODATA if the property does not have a value,
 *	   %-EPROTO if the property is not an array of strings,
 *	   %-EOVERFLOW if the size of the property is not as expected,
 *	   %-ENXIO if no suitable firmware interface is present.
 */
int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
				      const char *propname, const char **val,
				      size_t nval)
{
	if (is_of_node(fwnode))
		return of_property_read_string_array(of_node(fwnode), propname,
						     val, nval);
	else if (is_acpi_node(fwnode))
		return acpi_dev_prop_read(acpi_node(fwnode), propname,
					  DEV_PROP_STRING, val, nval);

	return -ENXIO;
}
Beispiel #3
0
/**
 * fwnode_property_read_string_array - return string array property of a node
 * @fwnode: Firmware node to get the property of
 * @propname: Name of the property
 * @val: The values are stored here or %NULL to return the number of values
 * @nval: Size of the @val array
 *
 * Read an string list property @propname from the given firmware node and store
 * them to @val if found.
 *
 * Return: number of values if @val was %NULL,
 *         %0 if the property was found (success),
 *	   %-EINVAL if given arguments are not valid,
 *	   %-ENODATA if the property does not have a value,
 *	   %-EPROTO if the property is not an array of strings,
 *	   %-EOVERFLOW if the size of the property is not as expected,
 *	   %-ENXIO if no suitable firmware interface is present.
 */
int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
                                      const char *propname, const char **val,
                                      size_t nval)
{
    if (is_of_node(fwnode))
        return val ?
               of_property_read_string_array(to_of_node(fwnode),
                                             propname, val, nval) :
               of_property_count_strings(to_of_node(fwnode), propname);
    else if (is_acpi_node(fwnode))
        return acpi_dev_prop_read(to_acpi_node(fwnode), propname,
                                  DEV_PROP_STRING, val, nval);

    return pset_prop_read_array(to_pset(fwnode), propname,
                                DEV_PROP_STRING, val, nval);
}
Beispiel #4
0
static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
					       const char *propname,
					       const char **val, size_t nval)
{
	if (is_of_node(fwnode))
		return val ?
			of_property_read_string_array(to_of_node(fwnode),
						      propname, val, nval) :
			of_property_count_strings(to_of_node(fwnode), propname);
	else if (is_acpi_node(fwnode))
		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
					   val, nval);
	else if (is_pset_node(fwnode))
		return val ?
			pset_prop_read_string_array(to_pset_node(fwnode),
						    propname, val, nval) :
			pset_prop_count_elems_of_size(to_pset_node(fwnode),
						      propname,
						      sizeof(const char *));
	return -ENXIO;
}
static void __init of_selftest_property_string(void)
{
	const char *strings[4];
	struct device_node *np;
	int rc;

	pr_info("start\n");
	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
	if (!np) {
		pr_err("No testcase data in device tree\n");
		return;
	}

	rc = of_property_match_string(np, "phandle-list-names", "first");
	selftest(rc == 0, "first expected:0 got:%i\n", rc);
	rc = of_property_match_string(np, "phandle-list-names", "second");
	selftest(rc == 1, "second expected:0 got:%i\n", rc);
	rc = of_property_match_string(np, "phandle-list-names", "third");
	selftest(rc == 2, "third expected:0 got:%i\n", rc);
	rc = of_property_match_string(np, "phandle-list-names", "fourth");
	selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc);
	rc = of_property_match_string(np, "missing-property", "blah");
	selftest(rc == -EINVAL, "missing property; rc=%i\n", rc);
	rc = of_property_match_string(np, "empty-property", "blah");
	selftest(rc == -ENODATA, "empty property; rc=%i\n", rc);
	rc = of_property_match_string(np, "unterminated-string", "blah");
	selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);

	/* of_property_count_strings() tests */
	rc = of_property_count_strings(np, "string-property");
	selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
	rc = of_property_count_strings(np, "phandle-list-names");
	selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
	rc = of_property_count_strings(np, "unterminated-string");
	selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
	rc = of_property_count_strings(np, "unterminated-string-list");
	selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);

	/* of_property_read_string_index() tests */
	rc = of_property_read_string_index(np, "string-property", 0, strings);
	selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc);
	strings[0] = NULL;
	rc = of_property_read_string_index(np, "string-property", 1, strings);
	selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
	rc = of_property_read_string_index(np, "phandle-list-names", 0, strings);
	selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
	rc = of_property_read_string_index(np, "phandle-list-names", 1, strings);
	selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc);
	rc = of_property_read_string_index(np, "phandle-list-names", 2, strings);
	selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc);
	strings[0] = NULL;
	rc = of_property_read_string_index(np, "phandle-list-names", 3, strings);
	selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
	strings[0] = NULL;
	rc = of_property_read_string_index(np, "unterminated-string", 0, strings);
	selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
	rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings);
	selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
	strings[0] = NULL;
	rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */
	selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
	strings[1] = NULL;

	/* of_property_read_string_array() tests */
	rc = of_property_read_string_array(np, "string-property", strings, 4);
	selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
	rc = of_property_read_string_array(np, "phandle-list-names", strings, 4);
	selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
	rc = of_property_read_string_array(np, "unterminated-string", strings, 4);
	selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
	/* -- An incorrectly formed string should cause a failure */
	rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4);
	selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
	/* -- parsing the correctly formed strings should still work: */
	strings[2] = NULL;
	rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2);
	selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc);
	strings[1] = NULL;
	rc = of_property_read_string_array(np, "phandle-list-names", strings, 1);
	selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]);
}
Beispiel #6
0
int __init opal_event_init(void)
{
	struct device_node *dn, *opal_node;
	const char **names;
	u32 *irqs;
	int i, rc;

	opal_node = of_find_node_by_path("/ibm,opal");
	if (!opal_node) {
		pr_warn("opal: Node not found\n");
		return -ENODEV;
	}

	/* If dn is NULL it means the domain won't be linked to a DT
	 * node so therefore irq_of_parse_and_map(...) wont work. But
	 * that shouldn't be problem because if we're running a
	 * version of skiboot that doesn't have the dn then the
	 * devices won't have the correct properties and will have to
	 * fall back to the legacy method (opal_event_request(...))
	 * anyway. */
	dn = of_find_compatible_node(NULL, NULL, "ibm,opal-event");
	opal_event_irqchip.domain = irq_domain_add_linear(dn, MAX_NUM_EVENTS,
				&opal_event_domain_ops, &opal_event_irqchip);
	of_node_put(dn);
	if (!opal_event_irqchip.domain) {
		pr_warn("opal: Unable to create irq domain\n");
		rc = -ENOMEM;
		goto out;
	}

	/* Get opal-interrupts property and names if present */
	rc = of_property_count_u32_elems(opal_node, "opal-interrupts");
	if (rc < 0)
		goto out;

	opal_irq_count = rc;
	pr_debug("Found %d interrupts reserved for OPAL\n", opal_irq_count);

	irqs = kcalloc(opal_irq_count, sizeof(*irqs), GFP_KERNEL);
	names = kcalloc(opal_irq_count, sizeof(*names), GFP_KERNEL);
	opal_irqs = kcalloc(opal_irq_count, sizeof(*opal_irqs), GFP_KERNEL);

	if (WARN_ON(!irqs || !names || !opal_irqs))
		goto out_free;

	rc = of_property_read_u32_array(opal_node, "opal-interrupts",
					irqs, opal_irq_count);
	if (rc < 0) {
		pr_err("Error %d reading opal-interrupts array\n", rc);
		goto out_free;
	}

	/* It's not an error for the names to be missing */
	of_property_read_string_array(opal_node, "opal-interrupts-names",
				      names, opal_irq_count);

	/* Install interrupt handlers */
	for (i = 0; i < opal_irq_count; i++) {
		unsigned int virq;
		char *name;

		/* Get hardware and virtual IRQ */
		virq = irq_create_mapping(NULL, irqs[i]);
		if (!virq) {
			pr_warn("Failed to map irq 0x%x\n", irqs[i]);
			continue;
		}

		if (names[i] && strlen(names[i]))
			name = kasprintf(GFP_KERNEL, "opal-%s", names[i]);
		else
			name = kasprintf(GFP_KERNEL, "opal");

		/* Install interrupt handler */
		rc = request_irq(virq, opal_interrupt, IRQF_TRIGGER_LOW,
				 name, NULL);
		if (rc) {
			irq_dispose_mapping(virq);
			pr_warn("Error %d requesting irq %d (0x%x)\n",
				 rc, virq, irqs[i]);
			continue;
		}

		/* Cache IRQ */
		opal_irqs[i] = virq;
	}

out_free:
	kfree(irqs);
	kfree(names);
out:
	of_node_put(opal_node);
	return rc;
}