int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i) { int error = 0; struct dprc_obj_desc obj_desc; memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc)); error = dprc_get_obj(dflt_mc_io, MC_CMD_NO_FLAGS, dprc_handle, i, &obj_desc); if (error < 0) { printf("dprc_get_obj(i=%d) failed: %d\n", i, error); return error; } if (!strcmp(obj_desc.type, obj_type)) { debug("Discovered object: type %s, id %d, req %s\n", obj_desc.type, obj_desc.id, obj_type); error = dprc_init_container_obj(obj_desc, dprc_handle); if (error < 0) { printf("dprc_init_container_obj(i=%d) failed: %d\n", i, error); return error; } } return error; }
/** * dprc_scan_objects - Discover objects in a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @total_irq_count: total number of IRQs needed by objects in the DPRC. * * Detects objects added and removed from a DPRC and synchronizes the * state of the Linux bus driver, MC by adding and removing * devices accordingly. * Two types of devices can be found in a DPRC: allocatable objects (e.g., * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). * All allocatable devices needed to be probed before all non-allocatable * devices, to ensure that device drivers for non-allocatable * devices can allocate any type of allocatable devices. * That is, we need to ensure that the corresponding resource pools are * populated before they can get allocation requests from probe callbacks * of the device drivers for the non-allocatable devices. */ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, unsigned int *total_irq_count) { int num_child_objects; int dprc_get_obj_failures; int error; unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; struct dprc_obj_desc *child_obj_desc_array = NULL; error = dprc_get_obj_count(mc_bus_dev->mc_io, 0, mc_bus_dev->mc_handle, &num_child_objects); if (error < 0) { dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", error); return error; } if (num_child_objects != 0) { int i; child_obj_desc_array = devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, sizeof(*child_obj_desc_array), GFP_KERNEL); if (!child_obj_desc_array) return -ENOMEM; /* * Discover objects currently present in the physical DPRC: */ dprc_get_obj_failures = 0; for (i = 0; i < num_child_objects; i++) { struct dprc_obj_desc *obj_desc = &child_obj_desc_array[i]; error = dprc_get_obj(mc_bus_dev->mc_io, 0, mc_bus_dev->mc_handle, i, obj_desc); if (error < 0) { dev_err(&mc_bus_dev->dev, "dprc_get_obj(i=%d) failed: %d\n", i, error); /* * Mark the obj entry as "invalid", by using the * empty string as obj type: */ obj_desc->type[0] = '\0'; obj_desc->id = error; dprc_get_obj_failures++; continue; } /* * add a quirk for all versions of dpsec < 4.0...none * are coherent regardless of what the MC reports. */ if ((strcmp(obj_desc->type, "dpseci") == 0) && (obj_desc->ver_major < 4)) obj_desc->flags |= DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY; irq_count += obj_desc->irq_count; dev_dbg(&mc_bus_dev->dev, "Discovered object: type %s, id %d\n", obj_desc->type, obj_desc->id); } if (dprc_get_obj_failures != 0) { dev_err(&mc_bus_dev->dev, "%d out of %d devices could not be retrieved\n", dprc_get_obj_failures, num_child_objects); } } *total_irq_count = irq_count; dprc_remove_devices(mc_bus_dev, child_obj_desc_array, num_child_objects); dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, num_child_objects); if (child_obj_desc_array) devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); return 0; }