int __must_check fsl_mc_portal_allocate()

in fsl-mc/mc-io.c [165:233]


int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
					u16 mc_io_flags,
					struct fsl_mc_io **new_mc_io)
{
	struct fsl_mc_device *mc_bus_dev;
	struct fsl_mc_bus *mc_bus;
	phys_addr_t mc_portal_phys_addr;
	size_t mc_portal_size;
	struct fsl_mc_device *dpmcp_dev;
	int error = -EINVAL;
	struct fsl_mc_resource *resource = NULL;
	struct fsl_mc_io *mc_io = NULL;

	if (mc_dev->flags & FSL_MC_IS_DPRC) {
		mc_bus_dev = mc_dev;
	} else {
		if (!dev_is_fsl_mc(mc_dev->dev.parent))
			return error;

		mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
	}

	mc_bus = to_fsl_mc_bus(mc_bus_dev);
	*new_mc_io = NULL;
	error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
	if (error < 0)
		return error;

	error = -EINVAL;
	dpmcp_dev = resource->data;

	if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
	    (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
	     dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
		dev_err(&dpmcp_dev->dev,
			"ERROR: Version %d.%d of DPMCP not supported.\n",
			dpmcp_dev->obj_desc.ver_major,
			dpmcp_dev->obj_desc.ver_minor);
		error = -ENOTSUPP;
		goto error_cleanup_resource;
	}

	mc_portal_phys_addr = dpmcp_dev->regions[0].start;
	mc_portal_size = resource_size(dpmcp_dev->regions);

	error = fsl_create_mc_io(&mc_bus_dev->dev,
				 mc_portal_phys_addr,
				 mc_portal_size, dpmcp_dev,
				 mc_io_flags, &mc_io);
	if (error < 0)
		goto error_cleanup_resource;

	dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
						   &dpmcp_dev->dev,
						   DL_FLAG_AUTOREMOVE_CONSUMER);
	if (!dpmcp_dev->consumer_link) {
		error = -EINVAL;
		goto error_cleanup_mc_io;
	}

	*new_mc_io = mc_io;
	return 0;

error_cleanup_mc_io:
	fsl_destroy_mc_io(mc_io);
error_cleanup_resource:
	fsl_mc_resource_free(resource);
	return error;
}