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;
}