if (copy_from_user(&port_pr, argp, minsz)) return -EFAULT;
if (port_pr.argsz < minsz || port_pr.flags) return -EINVAL;
/* get fme header region */
fme_hdr = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);
/* check port id */
v = readq(fme_hdr + FME_HDR_CAP); if (port_pr.port_id >= FIELD_GET(FME_CAP_NUM_PORTS, v)) {
dev_dbg(&pdev->dev, "port number more than maximum\n"); return -EINVAL;
}
/* * align PR buffer per PR bandwidth, as HW ignores the extra padding * data automatically.
*/
length = ALIGN(port_pr.buffer_size, 4);
buf = vmalloc(length); if (!buf) return -ENOMEM;
if (copy_from_user(buf,
(void __user *)(unsignedlong)port_pr.buffer_address,
port_pr.buffer_size)) {
ret = -EFAULT; goto free_exit;
}
/* prepare fpga_image_info for PR */
info = fpga_image_info_alloc(&pdev->dev); if (!info) {
ret = -ENOMEM; goto free_exit;
}
info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
mutex_lock(&fdata->lock);
fme = dfl_fpga_fdata_get_private(fdata); /* fme device has been unregistered. */ if (!fme) {
ret = -EINVAL; goto unlock_exit;
}
region = dfl_fme_region_find(fme, port_pr.port_id); if (!region) {
ret = -EINVAL; goto unlock_exit;
}
/* * it allows userspace to reset the PR region's logic by disabling and * reenabling the bridge to clear things out between acceleration runs. * so no need to hold the bridges after partial reconfiguration.
*/ if (region->get_bridges)
fpga_bridges_put(®ion->bridge_list);
/** * dfl_fme_create_mgr - create fpga mgr platform device as child device * @fdata: fme feature dev data * @feature: sub feature info * * Return: mgr platform device if successful, and error code otherwise.
*/ staticstruct platform_device *
dfl_fme_create_mgr(struct dfl_feature_dev_data *fdata, struct dfl_feature *feature)
{ struct platform_device *mgr, *fme = fdata->dev; struct dfl_fme_mgr_pdata mgr_pdata; int ret = -ENOMEM;
if (!feature->ioaddr) return ERR_PTR(-ENODEV);
mgr_pdata.ioaddr = feature->ioaddr;
/* * Each FME has only one fpga-mgr, so allocate platform device using * the same FME platform device id.
*/
mgr = platform_device_alloc(DFL_FPGA_FME_MGR, fme->id); if (!mgr) return ERR_PTR(ret);
mgr->dev.parent = &fme->dev;
ret = platform_device_add_data(mgr, &mgr_pdata, sizeof(mgr_pdata)); if (ret) goto create_mgr_err;
ret = platform_device_add(mgr); if (ret) goto create_mgr_err;
/** * dfl_fme_create_bridge - create fme fpga bridge platform device as child * * @fdata: fme feature dev data * @port_id: port id for the bridge to be created. * * Return: bridge platform device if successful, and error code otherwise.
*/ staticstruct dfl_fme_bridge *
dfl_fme_create_bridge(struct dfl_feature_dev_data *fdata, int port_id)
{ struct device *dev = &fdata->dev->dev; struct dfl_fme_br_pdata br_pdata; struct dfl_fme_bridge *fme_br; int ret = -ENOMEM;
fme_br = devm_kzalloc(dev, sizeof(*fme_br), GFP_KERNEL); if (!fme_br) return ERR_PTR(ret);
/** * dfl_fme_create_region - create fpga region platform device as child * * @fdata: fme feature dev data * @mgr: mgr platform device needed for region * @br: br platform device needed for region * @port_id: port id * * Return: fme region if successful, and error code otherwise.
*/ staticstruct dfl_fme_region *
dfl_fme_create_region(struct dfl_feature_dev_data *fdata, struct platform_device *mgr, struct platform_device *br, int port_id)
{ struct dfl_fme_region_pdata region_pdata; struct device *dev = &fdata->dev->dev; struct dfl_fme_region *fme_region; int ret = -ENOMEM;
fme_region = devm_kzalloc(dev, sizeof(*fme_region), GFP_KERNEL); if (!fme_region) return ERR_PTR(ret);
region_pdata.mgr = mgr;
region_pdata.br = br;
/* * Each FPGA device may have more than one port, so allocate platform * device using the same port platform device id.
*/
fme_region->region = platform_device_alloc(DFL_FPGA_FME_REGION, br->id); if (!fme_region->region) return ERR_PTR(ret);
fme_region->region->dev.parent = dev;
ret = platform_device_add_data(fme_region->region, ®ion_pdata, sizeof(region_pdata)); if (ret) goto create_region_err;
ret = platform_device_add(fme_region->region); if (ret) goto create_region_err;
/* 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(fdata, 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(fdata, mgr,
fme_br->br, i); if (IS_ERR(fme_region)) {
ret = PTR_ERR(fme_region); goto destroy_region;
}
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.