static int dprc_exit(void) { int err; err = dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle); if (err < 0) { printf("dprc_close(): Child failed: %d\n", err); goto err; } err = dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle, child_dprc_id); if (err < 0) { printf("dprc_destroy_container() failed: %d\n", err); goto err; } err = dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle); if (err < 0) { printf("dprc_close(): Root failed: %d\n", err); goto err; } if (dflt_mc_io) free(dflt_mc_io); if (root_mc_io) free(root_mc_io); return 0; err: return err; }
static int get_dprc_icid(struct fsl_mc_io *mc_io, int container_id, u16 *icid) { u16 dprc_handle; struct dprc_attributes attr; int error; error = dprc_open(mc_io, 0, container_id, &dprc_handle); if (error < 0) { dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); return error; } memset(&attr, 0, sizeof(attr)); error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr); if (error < 0) { dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", error); goto common_cleanup; } *icid = attr.icid; error = 0; common_cleanup: (void)dprc_close(mc_io, 0, dprc_handle); return error; }
int fsl_mc_ldpaa_init(bd_t *bis) { int i, error = 0; int dprc_opened = 0, container_id; int num_child_objects = 0; error = mc_init(); if (error < 0) goto error; error = dprc_get_container_id(dflt_mc_io, MC_CMD_NO_FLAGS, &container_id); if (error < 0) { printf("dprc_get_container_id() failed: %d\n", error); goto error; } debug("fsl-mc: Container id=0x%x\n", container_id); error = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, container_id, &dflt_dprc_handle); if (error < 0) { printf("dprc_open() failed: %d\n", error); goto error; } dprc_opened = true; error = dprc_get_obj_count(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle, &num_child_objects); if (error < 0) { printf("dprc_get_obj_count() failed: %d\n", error); goto error; } debug("Total child in container %d = %d\n", container_id, num_child_objects); if (num_child_objects != 0) { /* * Discover objects currently in the DPRC container in the MC: */ for (i = 0; i < num_child_objects; i++) error = dprc_scan_container_obj(dflt_dprc_handle, "dpbp", i); for (i = 0; i < num_child_objects; i++) error = dprc_scan_container_obj(dflt_dprc_handle, "dpio", i); for (i = 0; i < num_child_objects; i++) error = dprc_scan_container_obj(dflt_dprc_handle, "dpni", i); } error: if (dprc_opened) dprc_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dprc_handle); return error; }
/** * dprc_remove - callback invoked when a DPRC is being unbound from this driver * * @mc_dev: Pointer to fsl-mc device representing the DPRC * * It removes the DPRC's child objects from Linux (not from the MC) and * closes the DPRC device in the MC. * It tears down the interrupts that were configured for the DPRC device. * It destroys the interrupt pool associated with this MC bus. */ static int dprc_remove(struct fsl_mc_device *mc_dev) { int error; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; if (WARN_ON(!mc_dev->mc_io)) return -EINVAL; if (WARN_ON(!mc_bus->irq_resources)) return -EINVAL; if (dev_get_msi_domain(&mc_dev->dev)) dprc_teardown_irq(mc_dev); device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); if (dev_get_msi_domain(&mc_dev->dev)) { fsl_mc_cleanup_irq_pool(mc_bus); dev_set_msi_domain(&mc_dev->dev, NULL); } fsl_mc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); if (error < 0) dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { fsl_destroy_mc_io(mc_dev->mc_io); mc_dev->mc_io = NULL; } dev_info(&mc_dev->dev, "DPRC device unbound from driver"); return 0; }
static int dprc_init(void) { int err, child_portal_id, container_id; struct dprc_cfg cfg; uint64_t mc_portal_offset; /* Open root container */ err = dprc_get_container_id(root_mc_io, MC_CMD_NO_FLAGS, &container_id); if (err < 0) { printf("dprc_get_container_id(): Root failed: %d\n", err); goto err_root_container_id; } #ifdef DEBUG printf("Root container id = %d\n", container_id); #endif err = dprc_open(root_mc_io, MC_CMD_NO_FLAGS, container_id, &root_dprc_handle); if (err < 0) { printf("dprc_open(): Root Container failed: %d\n", err); goto err_root_open; } if (!root_dprc_handle) { printf("dprc_open(): Root Container Handle is not valid\n"); goto err_root_open; } cfg.options = DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED | DPRC_CFG_OPT_OBJ_CREATE_ALLOWED | DPRC_CFG_OPT_ALLOC_ALLOWED; cfg.icid = DPRC_GET_ICID_FROM_POOL; cfg.portal_id = 250; err = dprc_create_container(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle, &cfg, &child_dprc_id, &mc_portal_offset); if (err < 0) { printf("dprc_create_container() failed: %d\n", err); goto err_create; } dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); if (!dflt_mc_io) { err = -ENOMEM; printf(" No memory: malloc() failed\n"); goto err_malloc; } child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset); dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id); #ifdef DEBUG printf("MC portal of child DPRC container: %d, physical addr %p)\n", child_dprc_id, dflt_mc_io->mmio_regs); #endif err = dprc_open(dflt_mc_io, MC_CMD_NO_FLAGS, child_dprc_id, &dflt_dprc_handle); if (err < 0) { printf("dprc_open(): Child container failed: %d\n", err); goto err_child_open; } if (!dflt_dprc_handle) { printf("dprc_open(): Child container Handle is not valid\n"); goto err_child_open; } return 0; err_child_open: free(dflt_mc_io); err_malloc: dprc_destroy_container(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle, child_dprc_id); err_create: dprc_close(root_mc_io, MC_CMD_NO_FLAGS, root_dprc_handle); err_root_open: err_root_container_id: return err; }
/** * dprc_probe - callback invoked when a DPRC is being bound to this driver * * @mc_dev: Pointer to fsl-mc device representing a DPRC * * It opens the physical DPRC in the MC. * It scans the DPRC to discover the MC objects contained in it. * It creates the interrupt pool for the MC bus associated with the DPRC. * It configures the interrupts for the DPRC device itself. */ static int dprc_probe(struct fsl_mc_device *mc_dev) { int error; size_t region_size; struct device *parent_dev = mc_dev->dev.parent; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); bool mc_io_created = false; bool msi_domain_set = false; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) return -EINVAL; if (!mc_dev->mc_io) { /* * This is a child DPRC: */ if (WARN_ON(!dev_is_fsl_mc(parent_dev))) return -EINVAL; if (WARN_ON(mc_dev->obj_desc.region_count == 0)) return -EINVAL; region_size = mc_dev->regions[0].end - mc_dev->regions[0].start + 1; 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; /* * Inherit parent MSI domain: */ dev_set_msi_domain(&mc_dev->dev, dev_get_msi_domain(parent_dev)); msi_domain_set = true; } else { /* * This is a root DPRC */ struct irq_domain *mc_msi_domain; if (WARN_ON(dev_is_fsl_mc(parent_dev))) return -EINVAL; error = fsl_mc_find_msi_domain(parent_dev, &mc_msi_domain); if (error < 0) { 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; } if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { dev_err(&mc_dev->dev, "ERROR: DPRC version %d.%d not supported\n", mc_bus->dprc_attr.version.major, mc_bus->dprc_attr.version.minor); error = -ENOTSUPP; goto error_cleanup_open; } mutex_init(&mc_bus->scan_mutex); /* * Discover MC objects in DPRC object: */ error = dprc_scan_container(mc_dev); if (error < 0) goto error_cleanup_open; /* * Configure interrupt for the DPRC object associated with this MC bus: */ error = dprc_setup_irq(mc_dev); if (error < 0) goto error_cleanup_open; dev_info(&mc_dev->dev, "DPRC device bound to driver"); 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; } return error; }