diff options
author | Peter Colberg <peter.colberg@intel.com> | 2024-11-19 20:10:30 -0500 |
---|---|---|
committer | Xu Yilun <yilun.xu@linux.intel.com> | 2024-12-18 22:28:48 +0800 |
commit | 59c265babab697aaa80814fe808cbb8942a14b9d (patch) | |
tree | 1a11cb56fd4013b3dfcfbda9559ac138f5ef3222 /drivers/fpga/dfl.c | |
parent | 3ddcf99119603b102e19e5f44338c1524cc549b7 (diff) |
fpga: dfl: store platform device id in feature device data
Delay the feature device id allocation from build_info_create_dev() to
binfo_create_feature_dev_data() and store the id in the feature device
data before copying it to the device. This will allow reusing the same
id in a subsequent commit which completely destroys and recreates the
feature device when releasing and reassigning the corresponding port.
Instead of manually freeing the id when no longer needed, use a
device-managed resource with a custom action to automatically free
the id right before the feature device data is freed. The id registry
is guaranteed to be allocated when dfl_id_free_action() is invoked,
since the DFL PCIe device and its device-managed resources will be
destroyed before dfl_ids_destroy() is called in dfl_fpga_exit().
Signed-off-by: Peter Colberg <peter.colberg@intel.com>
Reviewed-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
Reviewed-by: Basheer Ahmed Muddebihal <basheer.ahmed.muddebihal@linux.intel.com>
Acked-by: Xu Yilun <yilun.xu@intel.com>
Link: https://lore.kernel.org/r/20241120011035.230574-15-peter.colberg@intel.com
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Diffstat (limited to 'drivers/fpga/dfl.c')
-rw-r--r-- | drivers/fpga/dfl.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index bd6ca3e0beb16..c6e2dbd9395bd 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -740,6 +740,13 @@ static void dfl_fpga_cdev_add_port_data(struct dfl_fpga_cdev *cdev, mutex_unlock(&cdev->lock); } +static void dfl_id_free_action(void *arg) +{ + struct dfl_feature_dev_data *fdata = arg; + + dfl_id_free(fdata->type, fdata->pdev_id); +} + static struct dfl_feature_dev_data * binfo_create_feature_dev_data(struct build_feature_devs_info *binfo) { @@ -747,7 +754,7 @@ binfo_create_feature_dev_data(struct build_feature_devs_info *binfo) enum dfl_id_type type = binfo->type; struct dfl_feature_info *finfo, *p; struct dfl_feature_dev_data *fdata; - int index = 0, res_idx = 0; + int ret, index = 0, res_idx = 0; if (WARN_ON_ONCE(type >= DFL_ID_MAX)) return ERR_PTR(-EINVAL); @@ -768,6 +775,17 @@ binfo_create_feature_dev_data(struct build_feature_devs_info *binfo) fdata->dev = fdev; fdata->type = type; + + fdata->pdev_id = dfl_id_alloc(type, binfo->dev); + if (fdata->pdev_id < 0) + return ERR_PTR(fdata->pdev_id); + + ret = devm_add_action_or_reset(binfo->dev, dfl_id_free_action, fdata); + if (ret) + return ERR_PTR(ret); + + fdev->id = fdata->pdev_id; + fdata->pdev_name = dfl_devs[type].name; fdata->num = binfo->feature_num; fdata->dfl_cdev = binfo->cdev; @@ -866,10 +884,6 @@ build_info_create_dev(struct build_feature_devs_info *binfo) INIT_LIST_HEAD(&binfo->sub_features); - fdev->id = dfl_id_alloc(type, &fdev->dev); - if (fdev->id < 0) - return fdev->id; - return 0; } @@ -946,17 +960,9 @@ static void build_info_free(struct build_feature_devs_info *binfo) { struct dfl_feature_info *finfo, *p; - /* - * it is a valid id, free it. See comments in - * build_info_create_dev() - */ - if (binfo->feature_dev && binfo->feature_dev->id >= 0) { - dfl_id_free(binfo->type, binfo->feature_dev->id); - - list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { - list_del(&finfo->node); - kfree(finfo); - } + list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) { + list_del(&finfo->node); + kfree(finfo); } platform_device_put(binfo->feature_dev); @@ -1547,13 +1553,9 @@ EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_irq); static int remove_feature_dev(struct device *dev, void *data) { struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev); - struct platform_device *pdev = to_platform_device(dev); - int id = pdev->id; feature_dev_unregister(fdata); - dfl_id_free(fdata->type, id); - return 0; } @@ -1656,10 +1658,8 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev) struct platform_device *port_dev = fdata->dev; /* remove released ports */ - if (!device_is_registered(&port_dev->dev)) { - dfl_id_free(fdata->type, port_dev->id); + if (!device_is_registered(&port_dev->dev)) platform_device_put(port_dev); - } list_del(&fdata->node); put_device(&port_dev->dev); |