in dfl-fme-pr.c [369:437]
static int pr_mgmt_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fme_region *fme_region;
struct dfl_fme_bridge *fme_br;
struct platform_device *mgr;
struct dfl_fme *priv;
void __iomem *fme_hdr;
int ret = -ENODEV, i = 0;
u64 fme_cap, port_offset;
fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev,
FME_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
priv = dfl_fpga_pdata_get_private(pdata);
/* Initialize the region and bridge sub device list */
INIT_LIST_HEAD(&priv->region_list);
INIT_LIST_HEAD(&priv->bridge_list);
/* Create fpga mgr platform device */
mgr = dfl_fme_create_mgr(pdata, feature);
if (IS_ERR(mgr)) {
dev_err(&pdev->dev, "fail to create fpga mgr pdev\n");
goto unlock;
}
priv->mgr = mgr;
/* Read capability register to check number of regions and bridges */
fme_cap = readq(fme_hdr + FME_HDR_CAP);
for (; i < FIELD_GET(FME_CAP_NUM_PORTS, fme_cap); i++) {
port_offset = readq(fme_hdr + FME_HDR_PORT_OFST(i));
if (!(port_offset & FME_PORT_OFST_IMP))
continue;
/* Create bridge for each port */
fme_br = dfl_fme_create_bridge(pdata, i);
if (IS_ERR(fme_br)) {
ret = PTR_ERR(fme_br);
goto destroy_region;
}
list_add(&fme_br->node, &priv->bridge_list);
/* Create region for each port */
fme_region = dfl_fme_create_region(pdata, mgr,
fme_br->br, i);
if (IS_ERR(fme_region)) {
ret = PTR_ERR(fme_region);
goto destroy_region;
}
list_add(&fme_region->node, &priv->region_list);
}
mutex_unlock(&pdata->lock);
return 0;
destroy_region:
dfl_fme_destroy_regions(pdata);
dfl_fme_destroy_bridges(pdata);
dfl_fme_destroy_mgr(pdata);
unlock:
mutex_unlock(&pdata->lock);
return ret;
}