static int hisi_lpc_acpi_set_io_res()

in hisi_lpc.c [393:466]


static int hisi_lpc_acpi_set_io_res(struct device *child,
				    struct device *hostdev,
				    const struct resource **res, int *num_res)
{
	struct acpi_device *adev;
	struct acpi_device *host;
	struct resource_entry *rentry;
	LIST_HEAD(resource_list);
	struct resource *resources;
	int count;
	int i;

	if (!child || !hostdev)
		return -EINVAL;

	host = to_acpi_device(hostdev);
	adev = to_acpi_device(child);

	if (!adev->status.present) {
		dev_dbg(child, "device is not present\n");
		return -EIO;
	}

	if (acpi_device_enumerated(adev)) {
		dev_dbg(child, "has been enumerated\n");
		return -EIO;
	}

	/*
	 * The following code segment to retrieve the resources is common to
	 * acpi_create_platform_device(), so consider a common helper function
	 * in future.
	 */
	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
	if (count <= 0) {
		dev_dbg(child, "failed to get resources\n");
		return count ? count : -EIO;
	}

	resources = devm_kcalloc(hostdev, count, sizeof(*resources),
				 GFP_KERNEL);
	if (!resources) {
		dev_warn(hostdev, "could not allocate memory for %d resources\n",
			 count);
		acpi_dev_free_resource_list(&resource_list);
		return -ENOMEM;
	}
	count = 0;
	list_for_each_entry(rentry, &resource_list, node) {
		resources[count] = *rentry->res;
		hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
		count++;
	}

	acpi_dev_free_resource_list(&resource_list);

	/* translate the I/O resources */
	for (i = 0; i < count; i++) {
		int ret;

		if (!(resources[i].flags & IORESOURCE_IO))
			continue;
		ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]);
		if (ret) {
			dev_err(child, "translate IO range %pR failed (%d)\n",
				&resources[i], ret);
			return ret;
		}
	}
	*res = resources;
	*num_res = count;

	return 0;
}