/** * fpga_region_get - get an exclusive reference to an fpga region * @region: FPGA Region struct * * Caller should call fpga_region_put() when done with region. * * Return: * * fpga_region struct if successful. * * -EBUSY if someone already has a reference to the region. * * -ENODEV if can't take parent driver module refcount.
*/ staticstruct fpga_region *fpga_region_get(struct fpga_region *region)
{ struct device *dev = ®ion->dev;
if (!mutex_trylock(®ion->mutex)) {
dev_dbg(dev, "%s: FPGA Region already in use\n", __func__); return ERR_PTR(-EBUSY);
}
get_device(dev); if (!try_module_get(region->ops_owner)) {
put_device(dev);
mutex_unlock(®ion->mutex); return ERR_PTR(-ENODEV);
}
dev_dbg(dev, "get\n");
return region;
}
/** * fpga_region_put - release a reference to a region * * @region: FPGA region
*/ staticvoid fpga_region_put(struct fpga_region *region)
{ struct device *dev = ®ion->dev;
/** * fpga_region_program_fpga - program FPGA * * @region: FPGA region * * Program an FPGA using fpga image info (region->info). * If the region has a get_bridges function, the exclusive reference for the * bridges will be held if programming succeeds. This is intended to prevent * reprogramming the region until the caller considers it safe to do so. * The caller will need to call fpga_bridges_put() before attempting to * reprogram the region. * * Return: 0 for success or negative error code.
*/ int fpga_region_program_fpga(struct fpga_region *region)
{ struct device *dev = ®ion->dev; struct fpga_image_info *info = region->info; int ret;
region = fpga_region_get(region); if (IS_ERR(region)) {
dev_err(dev, "failed to get FPGA region\n"); return PTR_ERR(region);
}
ret = fpga_mgr_lock(region->mgr); if (ret) {
dev_err(dev, "FPGA manager is busy\n"); goto err_put_region;
}
/* * In some cases, we already have a list of bridges in the * fpga region struct. Or we don't have any bridges.
*/ if (region->get_bridges) {
ret = region->get_bridges(region); if (ret) {
dev_err(dev, "failed to get fpga region bridges\n"); goto err_unlock_mgr;
}
}
ret = fpga_bridges_disable(®ion->bridge_list); if (ret) {
dev_err(dev, "failed to disable bridges\n"); goto err_put_br;
}
ret = fpga_mgr_load(region->mgr, info); if (ret) {
dev_err(dev, "failed to load FPGA image\n"); goto err_put_br;
}
ret = fpga_bridges_enable(®ion->bridge_list); if (ret) {
dev_err(dev, "failed to enable region bridges\n"); goto err_put_br;
}
/** * __fpga_region_register - create and register an FPGA Region device * @parent: device parent * @mgr: manager that programs this region * @get_bridges: optional function to get bridges to a list * @owner: module containing the get_bridges function * * This simple version of the register function should be sufficient for most users. * The fpga_region_register_full() function is available for users that need to * pass additional, optional parameters. * * Return: struct fpga_region or ERR_PTR()
*/ struct fpga_region *
__fpga_region_register(struct device *parent, struct fpga_manager *mgr, int (*get_bridges)(struct fpga_region *), struct module *owner)
{ struct fpga_region_info info = { 0 };
/** * fpga_region_unregister - unregister an FPGA region * @region: FPGA region * * This function is intended for use in an FPGA region driver's remove function.
*/ void fpga_region_unregister(struct fpga_region *region)
{
device_unregister(®ion->dev);
}
EXPORT_SYMBOL_GPL(fpga_region_unregister);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.