in fsl-mc/dprc-driver.c [614:720]
int dprc_setup(struct fsl_mc_device *mc_dev)
{
struct device *parent_dev = mc_dev->dev.parent;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
struct irq_domain *mc_msi_domain;
bool mc_io_created = false;
bool msi_domain_set = false;
bool uapi_created = false;
u16 major_ver, minor_ver;
size_t region_size;
int error;
if (!is_fsl_mc_bus_dprc(mc_dev))
return -EINVAL;
if (dev_get_msi_domain(&mc_dev->dev))
return -EINVAL;
if (!mc_dev->mc_io) {
/*
* This is a child DPRC:
*/
if (!dev_is_fsl_mc(parent_dev))
return -EINVAL;
if (mc_dev->obj_desc.region_count == 0)
return -EINVAL;
region_size = resource_size(mc_dev->regions);
error = fsl_create_mc_io(&mc_dev->dev,
mc_dev->regions[0].start,
region_size,
NULL,
FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
&mc_dev->mc_io);
if (error < 0)
return error;
mc_io_created = true;
} else {
error = fsl_mc_uapi_create_device_file(mc_bus);
if (error < 0)
return -EPROBE_DEFER;
uapi_created = true;
}
mc_msi_domain = fsl_mc_find_msi_domain(&mc_dev->dev);
if (!mc_msi_domain) {
dev_warn(&mc_dev->dev,
"WARNING: MC bus without interrupt support\n");
} else {
dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
msi_domain_set = true;
}
error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
&mc_dev->mc_handle);
if (error < 0) {
dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
goto error_cleanup_msi_domain;
}
error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
&mc_bus->dprc_attr);
if (error < 0) {
dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
error);
goto error_cleanup_open;
}
error = dprc_get_api_version(mc_dev->mc_io, 0,
&major_ver,
&minor_ver);
if (error < 0) {
dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
error);
goto error_cleanup_open;
}
if (major_ver < DPRC_MIN_VER_MAJOR) {
dev_err(&mc_dev->dev,
"ERROR: DPRC version %d.%d not supported\n",
major_ver, minor_ver);
error = -ENOTSUPP;
goto error_cleanup_open;
}
return 0;
error_cleanup_open:
(void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
error_cleanup_msi_domain:
if (msi_domain_set)
dev_set_msi_domain(&mc_dev->dev, NULL);
if (mc_io_created) {
fsl_destroy_mc_io(mc_dev->mc_io);
mc_dev->mc_io = NULL;
}
if (uapi_created)
fsl_mc_uapi_remove_device_file(mc_bus);
return error;
}