2024-04-09 23:41:50

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 0/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

DFL ports are registered as platform devices in PF mode. The port device
should be removed from the host when the user wants to configure the
port as a VF and pass through to a virtual machine. The FME device
ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.

In the previous implementation, the port platform device is not completely
destroyed on port release: it is removed from the system by
platform_device_del(), but the platform device instance is retained.
When the port assign ioctl is called, the platform device is added back by
platform_device_add(), which conflicts with this comment of device_add():
"Do not call this routine more than once for any device structure", and
will cause a kernel warning at runtime.

This patch tries to completely unregister the port platform device on
release and registers a new one on assign. But the main work is to remove
the dependency on struct dfl_feature_platform_data for many internal DFL
APIs. This structure holds many DFL enumeration infos for feature devices.
Many DFL APIs are expected to work with these info even when the port
platform device is unregistered. But with the change the platform_data will
be freed in this case. So this patch introduces a new structure
dfl_feature_dev_data for these APIs, which acts similarly to the previous
dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
pointer to dfl_feature_dev_data to make the feature device driver work.

The single monolithic v1 patch is split into multiple, smaller patches
at the request of the maintainer. The first patch adds temporary macros
that alias dfl_feature_dev_data ("fdata") to dfl_feature_platform_data
("pdata") and associated functions from the "fdata" to the corresponding
"pdata" variants. Subsequent patches separate out most of the symbol
name changes required by this patch series, one patch per file. The last
patch of the series removes the macros and applies the actual change.

Link: https://lore.kernel.org/all/DM6PR11MB3819F9CCD0A6126B55BCB47685FB9@DM6PR11MB3819.namprd11.prod.outlook.com/T/#t

This series applies after the following non-RFC patches:
- fpga: dfl: remove unused function is_dfl_feature_present
- [v2] fpga: dfl: remove unused member pdata from struct dfl_{afu,fme}

Changes since v1:
- Split monolithic patch into series at request of maintainer.
- Substitute binfo->type for removed function feature_dev_id_type() in
parse_feature_irqs().
- Return ERR_PTR(-ENOMEM) on !feature->params in
binfo_create_feature_dev_data().
- Reorder cdev as first member of struct dfl_feature_platform_data
such that container_of() to obtain pdata evaluates to a no-op.
- Change afu_ioctl_*() to receive dfl_feature_dev_data instead of
dfl_feature_platform_data.
- Change fme_hdr_ioctl_*() to receive dfl_feature_dev_data instead of
dfl_feature_platform_data.
- Replace local variable pdata with fdata in afu_mmap().
- Remove unused local variable pdata in afu_dev_{init,destroy}().
- Remove unused local variable pdata in fme_dev_{init,destroy}().
- Reorder local variables in afu_dma_unpin_pages() to reverse Christmas
tree order.
- Align kernel-doc function name for __dfl_fpga_cdev_find_port_data().
- Substitute @fdata for @pdata in kernel-doc comments for
dfl_fme_create_mgr() and dfl_fme_destroy_mgr().

Peter Colberg (8):
fpga: dfl: alias dfl_feature_dev_data to dfl_feature_platform_data
fpga: dfl: migrate AFU DMA region management driver to
dfl_feature_dev_data
fpga: dfl: migrate AFU MMIO region management driver to
dfl_feature_dev_data
fpga: dfl: migrate FPGA Management Engine driver to
dfl_feature_dev_data
fpga: dfl: migrate FME partial reconfiguration driver to
dfl_feature_dev_data
fpga: dfl: migrate Accelerated Function Unit driver to
dfl_feature_dev_data
fpga: dfl: migrate DFL support header to dfl_feature_dev_data
fpga: dfl: migrate dfl_get_feature_by_id() to dfl_feature_dev_data

Xu Yilun (1):
fpga: dfl: fix kernel warning on port release/assign for SRIOV

drivers/fpga/dfl-afu-dma-region.c | 119 ++++----
drivers/fpga/dfl-afu-error.c | 59 ++--
drivers/fpga/dfl-afu-main.c | 281 +++++++++----------
drivers/fpga/dfl-afu-region.c | 51 ++--
drivers/fpga/dfl-afu.h | 26 +-
drivers/fpga/dfl-fme-br.c | 24 +-
drivers/fpga/dfl-fme-error.c | 98 +++----
drivers/fpga/dfl-fme-main.c | 86 +++---
drivers/fpga/dfl-fme-pr.c | 88 +++---
drivers/fpga/dfl.c | 433 +++++++++++++++---------------
drivers/fpga/dfl.h | 139 ++++++----
11 files changed, 722 insertions(+), 682 deletions(-)

--
2.44.0



2024-04-09 23:42:28

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 2/9] fpga: dfl: migrate AFU DMA region management driver to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl-afu-dma-region.c. This is done
to split a single monolithic change into multiple, smaller patches at the
request of the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
- Reorder local variables in afu_dma_unpin_pages() to reverse Christmas
tree order.
---
drivers/fpga/dfl-afu-dma-region.c | 119 +++++++++++++++---------------
1 file changed, 61 insertions(+), 58 deletions(-)

diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
index 02b60fde0430..fb45e51b12af 100644
--- a/drivers/fpga/dfl-afu-dma-region.c
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -16,26 +16,26 @@

#include "dfl-afu.h"

-void afu_dma_region_init(struct dfl_feature_platform_data *pdata)
+void afu_dma_region_init(struct dfl_feature_dev_data *fdata)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);

afu->dma_regions = RB_ROOT;
}

/**
* afu_dma_pin_pages - pin pages of given dma memory region
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @region: dma memory region to be pinned
*
* Pin all the pages of given dfl_afu_dma_region.
* Return 0 for success or negative error code.
*/
-static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
+static int afu_dma_pin_pages(struct dfl_feature_dev_data *fdata,
struct dfl_afu_dma_region *region)
{
int npages = region->length >> PAGE_SHIFT;
- struct device *dev = &pdata->dev->dev;
+ struct device *dev = &fdata->dev->dev;
int ret, pinned;

ret = account_locked_vm(current->mm, npages, true);
@@ -73,17 +73,17 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,

/**
* afu_dma_unpin_pages - unpin pages of given dma memory region
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @region: dma memory region to be unpinned
*
* Unpin all the pages of given dfl_afu_dma_region.
* Return 0 for success or negative error code.
*/
-static void afu_dma_unpin_pages(struct dfl_feature_platform_data *pdata,
+static void afu_dma_unpin_pages(struct dfl_feature_dev_data *fdata,
struct dfl_afu_dma_region *region)
{
long npages = region->length >> PAGE_SHIFT;
- struct device *dev = &pdata->dev->dev;
+ struct device *dev = &fdata->dev->dev;

unpin_user_pages(region->pages, npages);
kfree(region->pages);
@@ -133,20 +133,21 @@ static bool dma_region_check_iova(struct dfl_afu_dma_region *region,

/**
* afu_dma_region_add - add given dma region to rbtree
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @region: dma region to be added
*
* Return 0 for success, -EEXIST if dma region has already been added.
*
- * Needs to be called with pdata->lock heold.
+ * Needs to be called with fdata->lock held.
*/
-static int afu_dma_region_add(struct dfl_feature_platform_data *pdata,
+static int afu_dma_region_add(struct dfl_feature_dev_data *fdata,
struct dfl_afu_dma_region *region)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
+ struct device *dev = &fdata->dev->dev;
struct rb_node **new, *parent = NULL;

- dev_dbg(&pdata->dev->dev, "add region (iova = %llx)\n",
+ dev_dbg(dev, "add region (iova = %llx)\n",
(unsigned long long)region->iova);

new = &afu->dma_regions.rb_node;
@@ -177,50 +178,51 @@ static int afu_dma_region_add(struct dfl_feature_platform_data *pdata,

/**
* afu_dma_region_remove - remove given dma region from rbtree
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @region: dma region to be removed
*
- * Needs to be called with pdata->lock heold.
+ * Needs to be called with fdata->lock held.
*/
-static void afu_dma_region_remove(struct dfl_feature_platform_data *pdata,
+static void afu_dma_region_remove(struct dfl_feature_dev_data *fdata,
struct dfl_afu_dma_region *region)
{
+ struct device *dev = &fdata->dev->dev;
struct dfl_afu *afu;

- dev_dbg(&pdata->dev->dev, "del region (iova = %llx)\n",
+ dev_dbg(dev, "del region (iova = %llx)\n",
(unsigned long long)region->iova);

- afu = dfl_fpga_pdata_get_private(pdata);
+ afu = dfl_fpga_fdata_get_private(fdata);
rb_erase(&region->node, &afu->dma_regions);
}

/**
* afu_dma_region_destroy - destroy all regions in rbtree
- * @pdata: feature device platform data
+ * @fdata: feature dev data
*
- * Needs to be called with pdata->lock heold.
+ * Needs to be called with fdata->lock held.
*/
-void afu_dma_region_destroy(struct dfl_feature_platform_data *pdata)
+void afu_dma_region_destroy(struct dfl_feature_dev_data *fdata)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
struct rb_node *node = rb_first(&afu->dma_regions);
struct dfl_afu_dma_region *region;

while (node) {
region = container_of(node, struct dfl_afu_dma_region, node);

- dev_dbg(&pdata->dev->dev, "del region (iova = %llx)\n",
+ dev_dbg(&fdata->dev->dev, "del region (iova = %llx)\n",
(unsigned long long)region->iova);

rb_erase(node, &afu->dma_regions);

if (region->iova)
- dma_unmap_page(dfl_fpga_pdata_to_parent(pdata),
+ dma_unmap_page(dfl_fpga_fdata_to_parent(fdata),
region->iova, region->length,
DMA_BIDIRECTIONAL);

if (region->pages)
- afu_dma_unpin_pages(pdata, region);
+ afu_dma_unpin_pages(fdata, region);

node = rb_next(node);
kfree(region);
@@ -229,7 +231,7 @@ void afu_dma_region_destroy(struct dfl_feature_platform_data *pdata)

/**
* afu_dma_region_find - find the dma region from rbtree based on iova and size
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @iova: address of the dma memory area
* @size: size of the dma memory area
*
@@ -239,14 +241,14 @@ void afu_dma_region_destroy(struct dfl_feature_platform_data *pdata)
* [@iova, @iova+size)
* If nothing is matched returns NULL.
*
- * Needs to be called with pdata->lock held.
+ * Needs to be called with fdata->lock held.
*/
struct dfl_afu_dma_region *
-afu_dma_region_find(struct dfl_feature_platform_data *pdata, u64 iova, u64 size)
+afu_dma_region_find(struct dfl_feature_dev_data *fdata, u64 iova, u64 size)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
struct rb_node *node = afu->dma_regions.rb_node;
- struct device *dev = &pdata->dev->dev;
+ struct device *dev = &fdata->dev->dev;

while (node) {
struct dfl_afu_dma_region *region;
@@ -276,20 +278,20 @@ afu_dma_region_find(struct dfl_feature_platform_data *pdata, u64 iova, u64 size)

/**
* afu_dma_region_find_iova - find the dma region from rbtree by iova
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @iova: address of the dma region
*
- * Needs to be called with pdata->lock held.
+ * Needs to be called with fdata->lock held.
*/
static struct dfl_afu_dma_region *
-afu_dma_region_find_iova(struct dfl_feature_platform_data *pdata, u64 iova)
+afu_dma_region_find_iova(struct dfl_feature_dev_data *fdata, u64 iova)
{
- return afu_dma_region_find(pdata, iova, 0);
+ return afu_dma_region_find(fdata, iova, 0);
}

/**
* afu_dma_map_region - map memory region for dma
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @user_addr: address of the memory region
* @length: size of the memory region
* @iova: pointer of iova address
@@ -298,9 +300,10 @@ afu_dma_region_find_iova(struct dfl_feature_platform_data *pdata, u64 iova)
* of the memory region via @iova.
* Return 0 for success, otherwise error code.
*/
-int afu_dma_map_region(struct dfl_feature_platform_data *pdata,
+int afu_dma_map_region(struct dfl_feature_dev_data *fdata,
u64 user_addr, u64 length, u64 *iova)
{
+ struct device *dev = &fdata->dev->dev;
struct dfl_afu_dma_region *region;
int ret;

@@ -323,47 +326,47 @@ int afu_dma_map_region(struct dfl_feature_platform_data *pdata,
region->length = length;

/* Pin the user memory region */
- ret = afu_dma_pin_pages(pdata, region);
+ ret = afu_dma_pin_pages(fdata, region);
if (ret) {
- dev_err(&pdata->dev->dev, "failed to pin memory region\n");
+ dev_err(dev, "failed to pin memory region\n");
goto free_region;
}

/* Only accept continuous pages, return error else */
if (!afu_dma_check_continuous_pages(region)) {
- dev_err(&pdata->dev->dev, "pages are not continuous\n");
+ dev_err(dev, "pages are not continuous\n");
ret = -EINVAL;
goto unpin_pages;
}

/* As pages are continuous then start to do DMA mapping */
- region->iova = dma_map_page(dfl_fpga_pdata_to_parent(pdata),
+ region->iova = dma_map_page(dfl_fpga_fdata_to_parent(fdata),
region->pages[0], 0,
region->length,
DMA_BIDIRECTIONAL);
- if (dma_mapping_error(dfl_fpga_pdata_to_parent(pdata), region->iova)) {
- dev_err(&pdata->dev->dev, "failed to map for dma\n");
+ if (dma_mapping_error(dfl_fpga_fdata_to_parent(fdata), region->iova)) {
+ dev_err(dev, "failed to map for dma\n");
ret = -EFAULT;
goto unpin_pages;
}

*iova = region->iova;

- mutex_lock(&pdata->lock);
- ret = afu_dma_region_add(pdata, region);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ ret = afu_dma_region_add(fdata, region);
+ mutex_unlock(&fdata->lock);
if (ret) {
- dev_err(&pdata->dev->dev, "failed to add dma region\n");
+ dev_err(dev, "failed to add dma region\n");
goto unmap_dma;
}

return 0;

unmap_dma:
- dma_unmap_page(dfl_fpga_pdata_to_parent(pdata),
+ dma_unmap_page(dfl_fpga_fdata_to_parent(fdata),
region->iova, region->length, DMA_BIDIRECTIONAL);
unpin_pages:
- afu_dma_unpin_pages(pdata, region);
+ afu_dma_unpin_pages(fdata, region);
free_region:
kfree(region);
return ret;
@@ -371,34 +374,34 @@ int afu_dma_map_region(struct dfl_feature_platform_data *pdata,

/**
* afu_dma_unmap_region - unmap dma memory region
- * @pdata: feature device platform data
+ * @fdata: feature dev data
* @iova: dma address of the region
*
* Unmap dma memory region based on @iova.
* Return 0 for success, otherwise error code.
*/
-int afu_dma_unmap_region(struct dfl_feature_platform_data *pdata, u64 iova)
+int afu_dma_unmap_region(struct dfl_feature_dev_data *fdata, u64 iova)
{
struct dfl_afu_dma_region *region;

- mutex_lock(&pdata->lock);
- region = afu_dma_region_find_iova(pdata, iova);
+ mutex_lock(&fdata->lock);
+ region = afu_dma_region_find_iova(fdata, iova);
if (!region) {
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return -EINVAL;
}

if (region->in_use) {
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return -EBUSY;
}

- afu_dma_region_remove(pdata, region);
- mutex_unlock(&pdata->lock);
+ afu_dma_region_remove(fdata, region);
+ mutex_unlock(&fdata->lock);

- dma_unmap_page(dfl_fpga_pdata_to_parent(pdata),
+ dma_unmap_page(dfl_fpga_fdata_to_parent(fdata),
region->iova, region->length, DMA_BIDIRECTIONAL);
- afu_dma_unpin_pages(pdata, region);
+ afu_dma_unpin_pages(fdata, region);
kfree(region);

return 0;
--
2.44.0


2024-04-09 23:42:31

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 1/9] fpga: dfl: alias dfl_feature_dev_data to dfl_feature_platform_data

Add temporary macros that alias dfl_feature_dev_data ("fdata") to
dfl_feature_platform_data ("pdata") and associated functions from the
"fdata" to the corresponding "pdata" variants. This is done to split a
single monolithic change into multiple, smaller patches at the request of
the maintainer. The macros will be removed in the last patch of the series.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
---
drivers/fpga/dfl.h | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index 5063d73b0d82..d724614796cb 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -206,6 +206,8 @@
#define PORT_UINT_CAP_INT_NUM GENMASK_ULL(11, 0) /* Interrupts num */
#define PORT_UINT_CAP_FST_VECT GENMASK_ULL(23, 12) /* First Vector */

+#define dfl_feature_dev_data dfl_feature_platform_data
+
/**
* struct dfl_fpga_port_ops - port ops
*
@@ -365,6 +367,8 @@ int dfl_feature_dev_use_count(struct dfl_feature_platform_data *pdata)
return pdata->open_count;
}

+#define dfl_fpga_fdata_set_private dfl_fpga_pdata_set_private
+
static inline
void dfl_fpga_pdata_set_private(struct dfl_feature_platform_data *pdata,
void *private)
@@ -372,6 +376,8 @@ void dfl_fpga_pdata_set_private(struct dfl_feature_platform_data *pdata,
pdata->private = private;
}

+#define dfl_fpga_fdata_get_private dfl_fpga_pdata_get_private
+
static inline
void *dfl_fpga_pdata_get_private(struct dfl_feature_platform_data *pdata)
{
@@ -437,6 +443,10 @@ void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u16 id)
return NULL;
}

+#define to_dfl_feature_dev_data dev_get_platdata
+
+#define dfl_fpga_fdata_to_parent dfl_fpga_pdata_to_parent
+
static inline
struct device *dfl_fpga_pdata_to_parent(struct dfl_feature_platform_data *pdata)
{
--
2.44.0


2024-04-09 23:42:34

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 3/9] fpga: dfl: migrate AFU MMIO region management driver to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl-afu-region.c. This is done to
split a single monolithic change into multiple, smaller patches at the
request of the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
---
drivers/fpga/dfl-afu-region.c | 51 ++++++++++++++++++-----------------
1 file changed, 26 insertions(+), 25 deletions(-)

diff --git a/drivers/fpga/dfl-afu-region.c b/drivers/fpga/dfl-afu-region.c
index 2e7b41629406..b11a5b21e666 100644
--- a/drivers/fpga/dfl-afu-region.c
+++ b/drivers/fpga/dfl-afu-region.c
@@ -12,11 +12,11 @@

/**
* afu_mmio_region_init - init function for afu mmio region support
- * @pdata: afu platform device's pdata.
+ * @fdata: afu feature dev data
*/
-void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
+void afu_mmio_region_init(struct dfl_feature_dev_data *fdata)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);

INIT_LIST_HEAD(&afu->regions);
}
@@ -39,7 +39,7 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
/**
* afu_mmio_region_add - add a mmio region to given feature dev.
*
- * @pdata: afu platform device's pdata.
+ * @fdata: afu feature dev data
* @region_index: region index.
* @region_size: region size.
* @phys: region's physical address of this region.
@@ -47,14 +47,15 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
*
* Return: 0 on success, negative error code otherwise.
*/
-int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
+int afu_mmio_region_add(struct dfl_feature_dev_data *fdata,
u32 region_index, u64 region_size, u64 phys, u32 flags)
{
+ struct device *dev = &fdata->dev->dev;
struct dfl_afu_mmio_region *region;
struct dfl_afu *afu;
int ret = 0;

- region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
+ region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
if (!region)
return -ENOMEM;

@@ -63,13 +64,13 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
region->phys = phys;
region->flags = flags;

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);

- afu = dfl_fpga_pdata_get_private(pdata);
+ afu = dfl_fpga_fdata_get_private(fdata);

/* check if @index already exists */
if (get_region_by_index(afu, region_index)) {
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
ret = -EEXIST;
goto exit;
}
@@ -80,37 +81,37 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,

afu->region_cur_offset += region_size;
afu->num_regions++;
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return 0;

exit:
- devm_kfree(&pdata->dev->dev, region);
+ devm_kfree(dev, region);
return ret;
}

/**
* afu_mmio_region_destroy - destroy all mmio regions under given feature dev.
- * @pdata: afu platform device's pdata.
+ * @fdata: afu feature dev data
*/
-void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
+void afu_mmio_region_destroy(struct dfl_feature_dev_data *fdata)
{
- struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
struct dfl_afu_mmio_region *tmp, *region;

list_for_each_entry_safe(region, tmp, &afu->regions, node)
- devm_kfree(&pdata->dev->dev, region);
+ devm_kfree(&fdata->dev->dev, region);
}

/**
* afu_mmio_region_get_by_index - find an afu region by index.
- * @pdata: afu platform device's pdata.
+ * @fdata: afu feature dev data
* @region_index: region index.
* @pregion: ptr to region for result.
*
* Return: 0 on success, negative error code otherwise.
*/
-int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
+int afu_mmio_region_get_by_index(struct dfl_feature_dev_data *fdata,
u32 region_index,
struct dfl_afu_mmio_region *pregion)
{
@@ -118,8 +119,8 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
struct dfl_afu *afu;
int ret = 0;

- mutex_lock(&pdata->lock);
- afu = dfl_fpga_pdata_get_private(pdata);
+ mutex_lock(&fdata->lock);
+ afu = dfl_fpga_fdata_get_private(fdata);
region = get_region_by_index(afu, region_index);
if (!region) {
ret = -EINVAL;
@@ -127,14 +128,14 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
}
*pregion = *region;
exit:
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret;
}

/**
* afu_mmio_region_get_by_offset - find an afu mmio region by offset and size
*
- * @pdata: afu platform device's pdata.
+ * @fdata: afu feature dev data
* @offset: region offset from start of the device fd.
* @size: region size.
* @pregion: ptr to region for result.
@@ -144,7 +145,7 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
*
* Return: 0 on success, negative error code otherwise.
*/
-int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
+int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata,
u64 offset, u64 size,
struct dfl_afu_mmio_region *pregion)
{
@@ -152,8 +153,8 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
struct dfl_afu *afu;
int ret = 0;

- mutex_lock(&pdata->lock);
- afu = dfl_fpga_pdata_get_private(pdata);
+ mutex_lock(&fdata->lock);
+ afu = dfl_fpga_fdata_get_private(fdata);
for_each_region(region, afu)
if (region->offset <= offset &&
region->offset + region->size >= offset + size) {
@@ -162,6 +163,6 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
}
ret = -EINVAL;
exit:
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret;
}
--
2.44.0


2024-04-09 23:42:41

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 4/9] fpga: dfl: migrate FPGA Management Engine driver to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl-fme-main.c. This is done to
split a single monolithic change into multiple, smaller patches at the
request of the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
- Change fme_hdr_ioctl_*() to receive dfl_feature_dev_data instead of
dfl_feature_platform_data.
- Remove unused local variable pdata in fme_dev_{init,destroy}().
---
drivers/fpga/dfl-fme-main.c | 68 ++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 864924f68f5e..7f119b09b54e 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -135,10 +135,10 @@ static const struct attribute_group fme_hdr_group = {
.attrs = fme_hdr_attrs,
};

-static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
+static long fme_hdr_ioctl_release_port(struct dfl_feature_dev_data *fdata,
unsigned long arg)
{
- struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
+ struct dfl_fpga_cdev *cdev = fdata->dfl_cdev;
int port_id;

if (get_user(port_id, (int __user *)arg))
@@ -147,10 +147,10 @@ static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
return dfl_fpga_cdev_release_port(cdev, port_id);
}

-static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
+static long fme_hdr_ioctl_assign_port(struct dfl_feature_dev_data *fdata,
unsigned long arg)
{
- struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
+ struct dfl_fpga_cdev *cdev = fdata->dfl_cdev;
int port_id;

if (get_user(port_id, (int __user *)arg))
@@ -163,13 +163,13 @@ static long fme_hdr_ioctl(struct platform_device *pdev,
struct dfl_feature *feature,
unsigned int cmd, unsigned long arg)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);

switch (cmd) {
case DFL_FPGA_FME_PORT_RELEASE:
- return fme_hdr_ioctl_release_port(pdata, arg);
+ return fme_hdr_ioctl_release_port(fdata, arg);
case DFL_FPGA_FME_PORT_ASSIGN:
- return fme_hdr_ioctl_assign_port(pdata, arg);
+ return fme_hdr_ioctl_assign_port(fdata, arg);
}

return -ENODEV;
@@ -411,14 +411,14 @@ static int power_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev->parent);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
struct dfl_feature *feature = dev_get_drvdata(dev);
int ret = 0;
u64 v;

val = clamp_val(val / MICRO, 0, PWR_THRESHOLD_MAX);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);

switch (attr) {
case hwmon_power_max:
@@ -438,7 +438,7 @@ static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
break;
}

- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return ret;
}
@@ -589,7 +589,7 @@ static struct dfl_feature_driver fme_feature_drvs[] = {
},
};

-static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
+static long fme_ioctl_check_extension(struct dfl_feature_dev_data *fdata,
unsigned long arg)
{
/* No extension support for now */
@@ -600,19 +600,21 @@ static int fme_open(struct inode *inode, struct file *filp)
{
struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
+ struct dfl_feature_dev_data *fdata;
int ret;

if (WARN_ON(!pdata))
return -ENODEV;

- mutex_lock(&pdata->lock);
- ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
+ fdata = pdata;
+ mutex_lock(&fdata->lock);
+ ret = dfl_feature_dev_use_begin(fdata, filp->f_flags & O_EXCL);
if (!ret) {
dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
- dfl_feature_dev_use_count(pdata));
+ dfl_feature_dev_use_count(fdata));
filp->private_data = pdata;
}
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return ret;
}
@@ -620,19 +622,20 @@ static int fme_open(struct inode *inode, struct file *filp)
static int fme_release(struct inode *inode, struct file *filp)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
- struct platform_device *pdev = pdata->dev;
+ struct dfl_feature_dev_data *fdata = pdata;
+ struct platform_device *pdev = fdata->dev;
struct dfl_feature *feature;

dev_dbg(&pdev->dev, "Device File Release\n");

- mutex_lock(&pdata->lock);
- dfl_feature_dev_use_end(pdata);
+ mutex_lock(&fdata->lock);
+ dfl_feature_dev_use_end(fdata);

- if (!dfl_feature_dev_use_count(pdata))
- dfl_fpga_dev_for_each_feature(pdata, feature)
+ if (!dfl_feature_dev_use_count(fdata))
+ dfl_fpga_dev_for_each_feature(fdata, feature)
dfl_fpga_set_irq_triggers(feature, 0,
feature->nr_irqs, NULL);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return 0;
}
@@ -640,7 +643,8 @@ static int fme_release(struct inode *inode, struct file *filp)
static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
- struct platform_device *pdev = pdata->dev;
+ struct dfl_feature_dev_data *fdata = pdata;
+ struct platform_device *pdev = fdata->dev;
struct dfl_feature *f;
long ret;

@@ -650,7 +654,7 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case DFL_FPGA_GET_API_VERSION:
return DFL_FPGA_API_VERSION;
case DFL_FPGA_CHECK_EXTENSION:
- return fme_ioctl_check_extension(pdata, arg);
+ return fme_ioctl_check_extension(fdata, arg);
default:
/*
* Let sub-feature's ioctl function to handle the cmd.
@@ -658,7 +662,7 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
* handled in this sub feature, and returns 0 or other
* error code if cmd is handled.
*/
- dfl_fpga_dev_for_each_feature(pdata, f) {
+ dfl_fpga_dev_for_each_feature(fdata, f) {
if (f->ops && f->ops->ioctl) {
ret = f->ops->ioctl(pdev, f, cmd, arg);
if (ret != -ENODEV)
@@ -672,27 +676,27 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

static int fme_dev_init(struct platform_device *pdev)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
struct dfl_fme *fme;

fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
if (!fme)
return -ENOMEM;

- mutex_lock(&pdata->lock);
- dfl_fpga_pdata_set_private(pdata, fme);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ dfl_fpga_fdata_set_private(fdata, fme);
+ mutex_unlock(&fdata->lock);

return 0;
}

static void fme_dev_destroy(struct platform_device *pdev)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);

- mutex_lock(&pdata->lock);
- dfl_fpga_pdata_set_private(pdata, NULL);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ dfl_fpga_fdata_set_private(fdata, NULL);
+ mutex_unlock(&fdata->lock);
}

static const struct file_operations fme_fops = {
--
2.44.0


2024-04-09 23:43:02

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 5/9] fpga: dfl: migrate FME partial reconfiguration driver to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl-fme-pr.c. This is done to split
a single monolithic change into multiple, smaller patches at the request of
the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
- Substitute @fdata for @pdata in kernel-doc comments for
dfl_fme_create_mgr() and dfl_fme_destroy_mgr().
---
drivers/fpga/dfl-fme-pr.c | 82 ++++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 40 deletions(-)

diff --git a/drivers/fpga/dfl-fme-pr.c b/drivers/fpga/dfl-fme-pr.c
index cdcf6dea4cc9..f4c95c4b88d9 100644
--- a/drivers/fpga/dfl-fme-pr.c
+++ b/drivers/fpga/dfl-fme-pr.c
@@ -65,7 +65,7 @@ static struct fpga_region *dfl_fme_region_find(struct dfl_fme *fme, int port_id)

static int fme_pr(struct platform_device *pdev, unsigned long arg)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
void __user *argp = (void __user *)arg;
struct dfl_fpga_fme_port_pr port_pr;
struct fpga_image_info *info;
@@ -123,8 +123,8 @@ static int fme_pr(struct platform_device *pdev, unsigned long arg)

info->flags |= FPGA_MGR_PARTIAL_RECONFIG;

- mutex_lock(&pdata->lock);
- fme = dfl_fpga_pdata_get_private(pdata);
+ mutex_lock(&fdata->lock);
+ fme = dfl_fpga_fdata_get_private(fdata);
/* fme device has been unregistered. */
if (!fme) {
ret = -EINVAL;
@@ -156,7 +156,7 @@ static int fme_pr(struct platform_device *pdev, unsigned long arg)

put_device(&region->dev);
unlock_exit:
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
free_exit:
vfree(buf);
return ret;
@@ -164,16 +164,16 @@ static int fme_pr(struct platform_device *pdev, unsigned long arg)

/**
* dfl_fme_create_mgr - create fpga mgr platform device as child device
+ * @fdata: fme feature dev data
* @feature: sub feature info
- * @pdata: fme platform_device's pdata
*
* Return: mgr platform device if successful, and error code otherwise.
*/
static struct platform_device *
-dfl_fme_create_mgr(struct dfl_feature_platform_data *pdata,
+dfl_fme_create_mgr(struct dfl_feature_dev_data *fdata,
struct dfl_feature *feature)
{
- struct platform_device *mgr, *fme = pdata->dev;
+ struct platform_device *mgr, *fme = fdata->dev;
struct dfl_fme_mgr_pdata mgr_pdata;
int ret = -ENOMEM;

@@ -209,11 +209,11 @@ dfl_fme_create_mgr(struct dfl_feature_platform_data *pdata,

/**
* dfl_fme_destroy_mgr - destroy fpga mgr platform device
- * @pdata: fme platform device's pdata
+ * @fdata: fme feature dev data
*/
-static void dfl_fme_destroy_mgr(struct dfl_feature_platform_data *pdata)
+static void dfl_fme_destroy_mgr(struct dfl_feature_dev_data *fdata)
{
- struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_fme *priv = dfl_fpga_fdata_get_private(fdata);

platform_device_unregister(priv->mgr);
}
@@ -221,15 +221,15 @@ static void dfl_fme_destroy_mgr(struct dfl_feature_platform_data *pdata)
/**
* dfl_fme_create_bridge - create fme fpga bridge platform device as child
*
- * @pdata: fme platform device's pdata
+ * @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.
*/
static struct dfl_fme_bridge *
-dfl_fme_create_bridge(struct dfl_feature_platform_data *pdata, int port_id)
+dfl_fme_create_bridge(struct dfl_feature_dev_data *fdata, int port_id)
{
- struct device *dev = &pdata->dev->dev;
+ struct device *dev = &fdata->dev->dev;
struct dfl_fme_br_pdata br_pdata;
struct dfl_fme_bridge *fme_br;
int ret = -ENOMEM;
@@ -238,7 +238,7 @@ dfl_fme_create_bridge(struct dfl_feature_platform_data *pdata, int port_id)
if (!fme_br)
return ERR_PTR(ret);

- br_pdata.cdev = pdata->dfl_cdev;
+ br_pdata.cdev = fdata->dfl_cdev;
br_pdata.port_id = port_id;

fme_br->br = platform_device_alloc(DFL_FPGA_FME_BRIDGE,
@@ -274,11 +274,11 @@ static void dfl_fme_destroy_bridge(struct dfl_fme_bridge *fme_br)

/**
* dfl_fme_destroy_bridges - destroy all fpga bridge platform device
- * @pdata: fme platform device's pdata
+ * @fdata: fme feature dev data
*/
-static void dfl_fme_destroy_bridges(struct dfl_feature_platform_data *pdata)
+static void dfl_fme_destroy_bridges(struct dfl_feature_dev_data *fdata)
{
- struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_fme *priv = dfl_fpga_fdata_get_private(fdata);
struct dfl_fme_bridge *fbridge, *tmp;

list_for_each_entry_safe(fbridge, tmp, &priv->bridge_list, node) {
@@ -290,7 +290,7 @@ static void dfl_fme_destroy_bridges(struct dfl_feature_platform_data *pdata)
/**
* dfl_fme_create_region - create fpga region platform device as child
*
- * @pdata: fme platform device's pdata
+ * @fdata: fme feature dev data
* @mgr: mgr platform device needed for region
* @br: br platform device needed for region
* @port_id: port id
@@ -298,12 +298,12 @@ static void dfl_fme_destroy_bridges(struct dfl_feature_platform_data *pdata)
* Return: fme region if successful, and error code otherwise.
*/
static struct dfl_fme_region *
-dfl_fme_create_region(struct dfl_feature_platform_data *pdata,
+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 = &pdata->dev->dev;
+ struct device *dev = &fdata->dev->dev;
struct dfl_fme_region *fme_region;
int ret = -ENOMEM;

@@ -353,11 +353,11 @@ static void dfl_fme_destroy_region(struct dfl_fme_region *fme_region)

/**
* dfl_fme_destroy_regions - destroy all fme regions
- * @pdata: fme platform device's pdata
+ * @fdata: fme feature dev data
*/
-static void dfl_fme_destroy_regions(struct dfl_feature_platform_data *pdata)
+static void dfl_fme_destroy_regions(struct dfl_feature_dev_data *fdata)
{
- struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
+ struct dfl_fme *priv = dfl_fpga_fdata_get_private(fdata);
struct dfl_fme_region *fme_region, *tmp;

list_for_each_entry_safe(fme_region, tmp, &priv->region_list, node) {
@@ -369,7 +369,8 @@ static void dfl_fme_destroy_regions(struct dfl_feature_platform_data *pdata)
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_feature_dev_data *fdata =
+ to_dfl_feature_dev_data(&pdev->dev);
struct dfl_fme_region *fme_region;
struct dfl_fme_bridge *fme_br;
struct platform_device *mgr;
@@ -381,15 +382,15 @@ static int pr_mgmt_init(struct platform_device *pdev,
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);
+ mutex_lock(&fdata->lock);
+ priv = dfl_fpga_fdata_get_private(fdata);

/* 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);
+ mgr = dfl_fme_create_mgr(fdata, feature);
if (IS_ERR(mgr)) {
dev_err(&pdev->dev, "fail to create fpga mgr pdev\n");
goto unlock;
@@ -405,7 +406,7 @@ static int pr_mgmt_init(struct platform_device *pdev,
continue;

/* Create bridge for each port */
- fme_br = dfl_fme_create_bridge(pdata, i);
+ fme_br = dfl_fme_create_bridge(fdata, i);
if (IS_ERR(fme_br)) {
ret = PTR_ERR(fme_br);
goto destroy_region;
@@ -414,7 +415,7 @@ static int pr_mgmt_init(struct platform_device *pdev,
list_add(&fme_br->node, &priv->bridge_list);

/* Create region for each port */
- fme_region = dfl_fme_create_region(pdata, mgr,
+ fme_region = dfl_fme_create_region(fdata, mgr,
fme_br->br, i);
if (IS_ERR(fme_region)) {
ret = PTR_ERR(fme_region);
@@ -423,30 +424,31 @@ static int pr_mgmt_init(struct platform_device *pdev,

list_add(&fme_region->node, &priv->region_list);
}
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return 0;

destroy_region:
- dfl_fme_destroy_regions(pdata);
- dfl_fme_destroy_bridges(pdata);
- dfl_fme_destroy_mgr(pdata);
+ dfl_fme_destroy_regions(fdata);
+ dfl_fme_destroy_bridges(fdata);
+ dfl_fme_destroy_mgr(fdata);
unlock:
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret;
}

static void pr_mgmt_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata =
+ to_dfl_feature_dev_data(&pdev->dev);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);

- dfl_fme_destroy_regions(pdata);
- dfl_fme_destroy_bridges(pdata);
- dfl_fme_destroy_mgr(pdata);
- mutex_unlock(&pdata->lock);
+ dfl_fme_destroy_regions(fdata);
+ dfl_fme_destroy_bridges(fdata);
+ dfl_fme_destroy_mgr(fdata);
+ mutex_unlock(&fdata->lock);
}

static long fme_pr_ioctl(struct platform_device *pdev,
--
2.44.0


2024-04-09 23:43:23

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 6/9] fpga: dfl: migrate Accelerated Function Unit driver to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl-afu-main.c. This is done to
split a single monolithic change into multiple, smaller patches at the
request of the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
- Change afu_ioctl_*() to receive dfl_feature_dev_data instead of
dfl_feature_platform_data.
- Replace local variable pdata with fdata in afu_mmap().
- Remove unused local variable pdata in afu_dev_{init,destroy}().
---
drivers/fpga/dfl-afu-main.c | 110 ++++++++++++++++++------------------
1 file changed, 56 insertions(+), 54 deletions(-)

diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 6b97c073849e..61868cdd5b0b 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -504,9 +504,11 @@ static const struct attribute_group port_afu_group = {
static int port_afu_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
+ struct dfl_feature_dev_data *fdata =
+ to_dfl_feature_dev_data(&pdev->dev);
struct resource *res = &pdev->resource[feature->resource_index];

- return afu_mmio_region_add(dev_get_platdata(&pdev->dev),
+ return afu_mmio_region_add(fdata,
DFL_PORT_REGION_INDEX_AFU,
resource_size(res), res->start,
DFL_PORT_REGION_MMAP | DFL_PORT_REGION_READ |
@@ -525,9 +527,11 @@ static const struct dfl_feature_ops port_afu_ops = {
static int port_stp_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
+ struct dfl_feature_dev_data *fdata =
+ to_dfl_feature_dev_data(&pdev->dev);
struct resource *res = &pdev->resource[feature->resource_index];

- return afu_mmio_region_add(dev_get_platdata(&pdev->dev),
+ return afu_mmio_region_add(fdata,
DFL_PORT_REGION_INDEX_STP,
resource_size(res), res->start,
DFL_PORT_REGION_MMAP | DFL_PORT_REGION_READ |
@@ -596,21 +600,19 @@ static struct dfl_feature_driver port_feature_drvs[] = {
static int afu_open(struct inode *inode, struct file *filp)
{
struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
- struct dfl_feature_platform_data *pdata;
+ struct dfl_feature_dev_data *fdata;
int ret;

- pdata = dev_get_platdata(&fdev->dev);
- if (WARN_ON(!pdata))
- return -ENODEV;
+ fdata = to_dfl_feature_dev_data(&fdev->dev);

- mutex_lock(&pdata->lock);
- ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
+ mutex_lock(&fdata->lock);
+ ret = dfl_feature_dev_use_begin(fdata, filp->f_flags & O_EXCL);
if (!ret) {
dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
- dfl_feature_dev_use_count(pdata));
+ dfl_feature_dev_use_count(fdata));
filp->private_data = fdev;
}
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return ret;
}
@@ -618,29 +620,29 @@ static int afu_open(struct inode *inode, struct file *filp)
static int afu_release(struct inode *inode, struct file *filp)
{
struct platform_device *pdev = filp->private_data;
- struct dfl_feature_platform_data *pdata;
+ struct dfl_feature_dev_data *fdata;
struct dfl_feature *feature;

dev_dbg(&pdev->dev, "Device File Release\n");

- pdata = dev_get_platdata(&pdev->dev);
+ fdata = to_dfl_feature_dev_data(&pdev->dev);

- mutex_lock(&pdata->lock);
- dfl_feature_dev_use_end(pdata);
+ mutex_lock(&fdata->lock);
+ dfl_feature_dev_use_end(fdata);

- if (!dfl_feature_dev_use_count(pdata)) {
- dfl_fpga_dev_for_each_feature(pdata, feature)
+ if (!dfl_feature_dev_use_count(fdata)) {
+ dfl_fpga_dev_for_each_feature(fdata, feature)
dfl_fpga_set_irq_triggers(feature, 0,
feature->nr_irqs, NULL);
__port_reset(pdev);
- afu_dma_region_destroy(pdata);
+ afu_dma_region_destroy(fdata);
}
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return 0;
}

-static long afu_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
+static long afu_ioctl_check_extension(struct dfl_feature_dev_data *fdata,
unsigned long arg)
{
/* No extension support for now */
@@ -648,7 +650,7 @@ static long afu_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
}

static long
-afu_ioctl_get_info(struct dfl_feature_platform_data *pdata, void __user *arg)
+afu_ioctl_get_info(struct dfl_feature_dev_data *fdata, void __user *arg)
{
struct dfl_fpga_port_info info;
struct dfl_afu *afu;
@@ -662,12 +664,12 @@ afu_ioctl_get_info(struct dfl_feature_platform_data *pdata, void __user *arg)
if (info.argsz < minsz)
return -EINVAL;

- mutex_lock(&pdata->lock);
- afu = dfl_fpga_pdata_get_private(pdata);
+ mutex_lock(&fdata->lock);
+ afu = dfl_fpga_fdata_get_private(fdata);
info.flags = 0;
info.num_regions = afu->num_regions;
info.num_umsgs = afu->num_umsgs;
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
@@ -675,7 +677,7 @@ afu_ioctl_get_info(struct dfl_feature_platform_data *pdata, void __user *arg)
return 0;
}

-static long afu_ioctl_get_region_info(struct dfl_feature_platform_data *pdata,
+static long afu_ioctl_get_region_info(struct dfl_feature_dev_data *fdata,
void __user *arg)
{
struct dfl_fpga_port_region_info rinfo;
@@ -691,7 +693,7 @@ static long afu_ioctl_get_region_info(struct dfl_feature_platform_data *pdata,
if (rinfo.argsz < minsz || rinfo.padding)
return -EINVAL;

- ret = afu_mmio_region_get_by_index(pdata, rinfo.index, &region);
+ ret = afu_mmio_region_get_by_index(fdata, rinfo.index, &region);
if (ret)
return ret;

@@ -706,7 +708,7 @@ static long afu_ioctl_get_region_info(struct dfl_feature_platform_data *pdata,
}

static long
-afu_ioctl_dma_map(struct dfl_feature_platform_data *pdata, void __user *arg)
+afu_ioctl_dma_map(struct dfl_feature_dev_data *fdata, void __user *arg)
{
struct dfl_fpga_port_dma_map map;
unsigned long minsz;
@@ -720,16 +722,16 @@ afu_ioctl_dma_map(struct dfl_feature_platform_data *pdata, void __user *arg)
if (map.argsz < minsz || map.flags)
return -EINVAL;

- ret = afu_dma_map_region(pdata, map.user_addr, map.length, &map.iova);
+ ret = afu_dma_map_region(fdata, map.user_addr, map.length, &map.iova);
if (ret)
return ret;

if (copy_to_user(arg, &map, sizeof(map))) {
- afu_dma_unmap_region(pdata, map.iova);
+ afu_dma_unmap_region(fdata, map.iova);
return -EFAULT;
}

- dev_dbg(&pdata->dev->dev, "dma map: ua=%llx, len=%llx, iova=%llx\n",
+ dev_dbg(&fdata->dev->dev, "dma map: ua=%llx, len=%llx, iova=%llx\n",
(unsigned long long)map.user_addr,
(unsigned long long)map.length,
(unsigned long long)map.iova);
@@ -738,7 +740,7 @@ afu_ioctl_dma_map(struct dfl_feature_platform_data *pdata, void __user *arg)
}

static long
-afu_ioctl_dma_unmap(struct dfl_feature_platform_data *pdata, void __user *arg)
+afu_ioctl_dma_unmap(struct dfl_feature_dev_data *fdata, void __user *arg)
{
struct dfl_fpga_port_dma_unmap unmap;
unsigned long minsz;
@@ -751,33 +753,33 @@ afu_ioctl_dma_unmap(struct dfl_feature_platform_data *pdata, void __user *arg)
if (unmap.argsz < minsz || unmap.flags)
return -EINVAL;

- return afu_dma_unmap_region(pdata, unmap.iova);
+ return afu_dma_unmap_region(fdata, unmap.iova);
}

static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct platform_device *pdev = filp->private_data;
- struct dfl_feature_platform_data *pdata;
+ struct dfl_feature_dev_data *fdata;
struct dfl_feature *f;
long ret;

dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);

- pdata = dev_get_platdata(&pdev->dev);
+ fdata = to_dfl_feature_dev_data(&pdev->dev);

switch (cmd) {
case DFL_FPGA_GET_API_VERSION:
return DFL_FPGA_API_VERSION;
case DFL_FPGA_CHECK_EXTENSION:
- return afu_ioctl_check_extension(pdata, arg);
+ return afu_ioctl_check_extension(fdata, arg);
case DFL_FPGA_PORT_GET_INFO:
- return afu_ioctl_get_info(pdata, (void __user *)arg);
+ return afu_ioctl_get_info(fdata, (void __user *)arg);
case DFL_FPGA_PORT_GET_REGION_INFO:
- return afu_ioctl_get_region_info(pdata, (void __user *)arg);
+ return afu_ioctl_get_region_info(fdata, (void __user *)arg);
case DFL_FPGA_PORT_DMA_MAP:
- return afu_ioctl_dma_map(pdata, (void __user *)arg);
+ return afu_ioctl_dma_map(fdata, (void __user *)arg);
case DFL_FPGA_PORT_DMA_UNMAP:
- return afu_ioctl_dma_unmap(pdata, (void __user *)arg);
+ return afu_ioctl_dma_unmap(fdata, (void __user *)arg);
default:
/*
* Let sub-feature's ioctl function to handle the cmd
@@ -785,7 +787,7 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
* handled in this sub feature, and returns 0 and other
* error code if cmd is handled.
*/
- dfl_fpga_dev_for_each_feature(pdata, f)
+ dfl_fpga_dev_for_each_feature(fdata, f)
if (f->ops && f->ops->ioctl) {
ret = f->ops->ioctl(pdev, f, cmd, arg);
if (ret != -ENODEV)
@@ -805,8 +807,8 @@ static const struct vm_operations_struct afu_vma_ops = {
static int afu_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct platform_device *pdev = filp->private_data;
- struct dfl_feature_platform_data *pdata;
u64 size = vma->vm_end - vma->vm_start;
+ struct dfl_feature_dev_data *fdata;
struct dfl_afu_mmio_region region;
u64 offset;
int ret;
@@ -814,10 +816,10 @@ static int afu_mmap(struct file *filp, struct vm_area_struct *vma)
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;

- pdata = dev_get_platdata(&pdev->dev);
+ fdata = to_dfl_feature_dev_data(&pdev->dev);

offset = vma->vm_pgoff << PAGE_SHIFT;
- ret = afu_mmio_region_get_by_offset(pdata, offset, size, &region);
+ ret = afu_mmio_region_get_by_offset(fdata, offset, size, &region);
if (ret)
return ret;

@@ -851,31 +853,31 @@ static const struct file_operations afu_fops = {

static int afu_dev_init(struct platform_device *pdev)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
struct dfl_afu *afu;

afu = devm_kzalloc(&pdev->dev, sizeof(*afu), GFP_KERNEL);
if (!afu)
return -ENOMEM;

- mutex_lock(&pdata->lock);
- dfl_fpga_pdata_set_private(pdata, afu);
- afu_mmio_region_init(pdata);
- afu_dma_region_init(pdata);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ dfl_fpga_fdata_set_private(fdata, afu);
+ afu_mmio_region_init(fdata);
+ afu_dma_region_init(fdata);
+ mutex_unlock(&fdata->lock);

return 0;
}

static int afu_dev_destroy(struct platform_device *pdev)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);

- mutex_lock(&pdata->lock);
- afu_mmio_region_destroy(pdata);
- afu_dma_region_destroy(pdata);
- dfl_fpga_pdata_set_private(pdata, NULL);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ afu_mmio_region_destroy(fdata);
+ afu_dma_region_destroy(fdata);
+ dfl_fpga_fdata_set_private(fdata, NULL);
+ mutex_unlock(&fdata->lock);

return 0;
}
--
2.44.0


2024-04-09 23:43:41

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 7/9] fpga: dfl: migrate DFL support header to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the file: drivers/fpga/dfl.h. This is done to split a
single monolithic change into multiple, smaller patches at the request of
the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
---
drivers/fpga/dfl.h | 46 ++++++++++++++++++++--------------------------
1 file changed, 20 insertions(+), 26 deletions(-)

diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index d724614796cb..b700f5bb7be7 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -333,55 +333,51 @@ struct dfl_feature_platform_data {
};

static inline
-int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata,
+int dfl_feature_dev_use_begin(struct dfl_feature_dev_data *fdata,
bool excl)
{
- if (pdata->excl_open)
+ if (fdata->excl_open)
return -EBUSY;

if (excl) {
- if (pdata->open_count)
+ if (fdata->open_count)
return -EBUSY;

- pdata->excl_open = true;
+ fdata->excl_open = true;
}
- pdata->open_count++;
+ fdata->open_count++;

return 0;
}

static inline
-void dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata)
+void dfl_feature_dev_use_end(struct dfl_feature_dev_data *fdata)
{
- pdata->excl_open = false;
+ fdata->excl_open = false;

- if (WARN_ON(pdata->open_count <= 0))
+ if (WARN_ON(fdata->open_count <= 0))
return;

- pdata->open_count--;
+ fdata->open_count--;
}

static inline
-int dfl_feature_dev_use_count(struct dfl_feature_platform_data *pdata)
+int dfl_feature_dev_use_count(struct dfl_feature_dev_data *fdata)
{
- return pdata->open_count;
+ return fdata->open_count;
}

-#define dfl_fpga_fdata_set_private dfl_fpga_pdata_set_private
-
static inline
-void dfl_fpga_pdata_set_private(struct dfl_feature_platform_data *pdata,
+void dfl_fpga_fdata_set_private(struct dfl_feature_dev_data *fdata,
void *private)
{
- pdata->private = private;
+ fdata->private = private;
}

-#define dfl_fpga_fdata_get_private dfl_fpga_pdata_get_private
-
static inline
-void *dfl_fpga_pdata_get_private(struct dfl_feature_platform_data *pdata)
+void *dfl_fpga_fdata_get_private(struct dfl_feature_dev_data *fdata)
{
- return pdata->private;
+ return fdata->private;
}

struct dfl_feature_ops {
@@ -414,9 +410,9 @@ struct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)
return pdata->dev;
}

-#define dfl_fpga_dev_for_each_feature(pdata, feature) \
- for ((feature) = (pdata)->features; \
- (feature) < (pdata)->features + (pdata)->num; (feature)++)
+#define dfl_fpga_dev_for_each_feature(fdata, feature) \
+ for ((feature) = (fdata)->features; \
+ (feature) < (fdata)->features + (fdata)->num; (feature)++)

static inline
struct dfl_feature *dfl_get_feature_by_id(struct device *dev, u16 id)
@@ -445,12 +441,10 @@ void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u16 id)

#define to_dfl_feature_dev_data dev_get_platdata

-#define dfl_fpga_fdata_to_parent dfl_fpga_pdata_to_parent
-
static inline
-struct device *dfl_fpga_pdata_to_parent(struct dfl_feature_platform_data *pdata)
+struct device *dfl_fpga_fdata_to_parent(struct dfl_feature_dev_data *fdata)
{
- return pdata->dev->dev.parent->parent;
+ return fdata->dev->dev.parent->parent;
}

static inline bool dfl_feature_is_fme(void __iomem *base)
--
2.44.0


2024-04-09 23:43:55

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 8/9] fpga: dfl: migrate dfl_get_feature_by_id() to dfl_feature_dev_data

This change separates out most of the symbol name changes required by this
patch series for the function: dfl_get_feature_by_id(). This is done to
split a single monolithic change into multiple, smaller patches at the
request of the maintainer.

Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
---
drivers/fpga/dfl-afu-error.c | 59 +++++++------
drivers/fpga/dfl-afu-main.c | 166 ++++++++++++++++++-----------------
drivers/fpga/dfl-afu.h | 26 +++---
drivers/fpga/dfl-fme-error.c | 98 +++++++++++----------
drivers/fpga/dfl-fme-main.c | 18 ++--
drivers/fpga/dfl-fme-pr.c | 6 +-
drivers/fpga/dfl.c | 3 +-
drivers/fpga/dfl.h | 13 ++-
8 files changed, 203 insertions(+), 186 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index ab7be6217368..0f392d1f6d45 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -28,37 +28,36 @@
#define ERROR_MASK GENMASK_ULL(63, 0)

/* mask or unmask port errors by the error mask register. */
-static void __afu_port_err_mask(struct device *dev, bool mask)
+static void __afu_port_err_mask(struct dfl_feature_dev_data *fdata, bool mask)
{
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);

writeq(mask ? ERROR_MASK : 0, base + PORT_ERROR_MASK);
}

static void afu_port_err_mask(struct device *dev, bool mask)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);

- mutex_lock(&pdata->lock);
- __afu_port_err_mask(dev, mask);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ __afu_port_err_mask(fdata, mask);
+ mutex_unlock(&fdata->lock);
}

/* clear port errors. */
static int afu_port_err_clear(struct device *dev, u64 err)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
- struct platform_device *pdev = to_platform_device(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base_err, *base_hdr;
int enable_ret = 0, ret = -EBUSY;
u64 v;

- base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
- base_hdr = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base_err = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
+ base_hdr = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);

/*
* clear Port Errors
@@ -80,12 +79,12 @@ static int afu_port_err_clear(struct device *dev, u64 err)
}

/* Halt Port by keeping Port in reset */
- ret = __afu_port_disable(pdev);
+ ret = __afu_port_disable(fdata);
if (ret)
goto done;

/* Mask all errors */
- __afu_port_err_mask(dev, true);
+ __afu_port_err_mask(fdata, true);

/* Clear errors if err input matches with current port errors.*/
v = readq(base_err + PORT_ERROR);
@@ -102,28 +101,28 @@ static int afu_port_err_clear(struct device *dev, u64 err)
}

/* Clear mask */
- __afu_port_err_mask(dev, false);
+ __afu_port_err_mask(fdata, false);

/* Enable the Port by clearing the reset */
- enable_ret = __afu_port_enable(pdev);
+ enable_ret = __afu_port_enable(fdata);

done:
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return enable_ret ? enable_ret : ret;
}

static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 error;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
error = readq(base + PORT_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)error);
}
@@ -146,15 +145,15 @@ static DEVICE_ATTR_RW(errors);
static ssize_t first_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 error;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
error = readq(base + PORT_FIRST_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)error);
}
@@ -164,16 +163,16 @@ static ssize_t first_malformed_req_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 req0, req1;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
req0 = readq(base + PORT_MALFORMED_REQ0);
req1 = readq(base + PORT_MALFORMED_REQ1);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%016llx%016llx\n",
(unsigned long long)req1, (unsigned long long)req0);
@@ -191,12 +190,14 @@ static umode_t port_err_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
+ struct dfl_feature_dev_data *fdata;

+ fdata = to_dfl_feature_dev_data(dev);
/*
* sysfs entries are visible only if related private feature is
* enumerated.
*/
- if (!dfl_get_feature_by_id(dev, PORT_FEATURE_ID_ERROR))
+ if (!dfl_get_feature_by_id(fdata, PORT_FEATURE_ID_ERROR))
return 0;

return attr->mode;
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 61868cdd5b0b..42928cc7e42b 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -26,7 +26,7 @@

/**
* __afu_port_enable - enable a port by clear reset
- * @pdev: port platform device.
+ * @fdata: port feature dev data.
*
* Enable Port by clear the port soft reset bit, which is set by default.
* The AFU is unable to respond to any MMIO access while in reset.
@@ -35,18 +35,17 @@
*
* The caller needs to hold lock for protection.
*/
-int __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct dfl_feature_dev_data *fdata)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
void __iomem *base;
u64 v;

- WARN_ON(!pdata->disable_count);
+ WARN_ON(!fdata->disable_count);

- if (--pdata->disable_count != 0)
+ if (--fdata->disable_count != 0)
return 0;

- base = dfl_get_feature_ioaddr_by_id(&pdev->dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

/* Clear port soft reset */
v = readq(base + PORT_HDR_CTRL);
@@ -60,7 +59,8 @@ int __afu_port_enable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
!(v & PORT_CTRL_SFTRST_ACK),
RST_POLL_INVL, RST_POLL_TIMEOUT)) {
- dev_err(&pdev->dev, "timeout, failure to enable device\n");
+ dev_err(fdata->dfl_cdev->parent,
+ "timeout, failure to enable device\n");
return -ETIMEDOUT;
}

@@ -69,22 +69,21 @@ int __afu_port_enable(struct platform_device *pdev)

/**
* __afu_port_disable - disable a port by hold reset
- * @pdev: port platform device.
+ * @fdata: port feature dev data.
*
* Disable Port by setting the port soft reset bit, it puts the port into reset.
*
* The caller needs to hold lock for protection.
*/
-int __afu_port_disable(struct platform_device *pdev)
+int __afu_port_disable(struct dfl_feature_dev_data *fdata)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
void __iomem *base;
u64 v;

- if (pdata->disable_count++ != 0)
+ if (fdata->disable_count++ != 0)
return 0;

- base = dfl_get_feature_ioaddr_by_id(&pdev->dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

/* Set port soft reset */
v = readq(base + PORT_HDR_CTRL);
@@ -99,7 +98,8 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
v & PORT_CTRL_SFTRST_ACK,
RST_POLL_INVL, RST_POLL_TIMEOUT)) {
- dev_err(&pdev->dev, "timeout, failure to disable device\n");
+ dev_err(fdata->dfl_cdev->parent,
+ "timeout, failure to disable device\n");
return -ETIMEDOUT;
}

@@ -118,34 +118,37 @@ int __afu_port_disable(struct platform_device *pdev)
* (disabled). Any attempts on MMIO access to AFU while in reset, will
* result errors reported via port error reporting sub feature (if present).
*/
-static int __port_reset(struct platform_device *pdev)
+static int __port_reset(struct dfl_feature_dev_data *fdata)
{
int ret;

- ret = __afu_port_disable(pdev);
+ ret = __afu_port_disable(fdata);
if (ret)
return ret;

- return __afu_port_enable(pdev);
+ return __afu_port_enable(fdata);
}

static int port_reset(struct platform_device *pdev)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata;
int ret;

- mutex_lock(&pdata->lock);
- ret = __port_reset(pdev);
- mutex_unlock(&pdata->lock);
+ fdata = to_dfl_feature_dev_data(&pdev->dev);
+
+ mutex_lock(&fdata->lock);
+ ret = __port_reset(fdata);
+ mutex_unlock(&fdata->lock);

return ret;
}

static int port_get_id(struct platform_device *pdev)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(&pdev->dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

return FIELD_GET(PORT_CAP_PORT_NUM, readq(base + PORT_HDR_CAP));
}
@@ -162,15 +165,15 @@ static DEVICE_ATTR_RO(id);
static ssize_t
ltr_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + PORT_HDR_CTRL);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v));
}
@@ -179,7 +182,7 @@ static ssize_t
ltr_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
bool ltr;
u64 v;
@@ -187,14 +190,14 @@ ltr_store(struct device *dev, struct device_attribute *attr,
if (kstrtobool(buf, &ltr))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_LATENCY;
v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0);
writeq(v, base + PORT_HDR_CTRL);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -203,15 +206,15 @@ static DEVICE_ATTR_RW(ltr);
static ssize_t
ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + PORT_HDR_STS);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v));
}
@@ -220,18 +223,18 @@ static ssize_t
ap1_event_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
bool clear;

if (kstrtobool(buf, &clear) || !clear)
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -241,15 +244,15 @@ static ssize_t
ap2_event_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + PORT_HDR_STS);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v));
}
@@ -258,18 +261,18 @@ static ssize_t
ap2_event_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
bool clear;

if (kstrtobool(buf, &clear) || !clear)
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -278,15 +281,15 @@ static DEVICE_ATTR_RW(ap2_event);
static ssize_t
power_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + PORT_HDR_STS);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v));
}
@@ -296,18 +299,18 @@ static ssize_t
userclk_freqcmd_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
u64 userclk_freq_cmd;
void __iomem *base;

if (kstrtou64(buf, 0, &userclk_freq_cmd))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(userclk_freq_cmd, base + PORT_HDR_USRCLK_CMD0);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -317,18 +320,18 @@ static ssize_t
userclk_freqcntrcmd_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
u64 userclk_freqcntr_cmd;
void __iomem *base;

if (kstrtou64(buf, 0, &userclk_freqcntr_cmd))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(userclk_freqcntr_cmd, base + PORT_HDR_USRCLK_CMD1);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -338,15 +341,15 @@ static ssize_t
userclk_freqsts_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
u64 userclk_freqsts;
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
userclk_freqsts = readq(base + PORT_HDR_USRCLK_STS0);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)userclk_freqsts);
}
@@ -356,15 +359,15 @@ static ssize_t
userclk_freqcntrsts_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
u64 userclk_freqcntrsts;
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
userclk_freqcntrsts = readq(base + PORT_HDR_USRCLK_STS1);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n",
(unsigned long long)userclk_freqcntrsts);
@@ -388,10 +391,12 @@ static umode_t port_hdr_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
+ struct dfl_feature_dev_data *fdata;
umode_t mode = attr->mode;
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
+ fdata = to_dfl_feature_dev_data(dev);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

if (dfl_feature_revision(base) > 0) {
/*
@@ -456,21 +461,21 @@ static const struct dfl_feature_ops port_hdr_ops = {
static ssize_t
afu_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 guidl, guidh;

- base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_AFU);
+ base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_AFU);

- mutex_lock(&pdata->lock);
- if (pdata->disable_count) {
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ if (fdata->disable_count) {
+ mutex_unlock(&fdata->lock);
return -EBUSY;
}

guidl = readq(base + GUID_L);
guidh = readq(base + GUID_H);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return scnprintf(buf, PAGE_SIZE, "%016llx%016llx\n", guidh, guidl);
}
@@ -485,12 +490,15 @@ static umode_t port_afu_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
+ struct dfl_feature_dev_data *fdata;
+
+ fdata = to_dfl_feature_dev_data(dev);

/*
* sysfs entries are visible only if related private feature is
* enumerated.
*/
- if (!dfl_get_feature_by_id(dev, PORT_FEATURE_ID_AFU))
+ if (!dfl_get_feature_by_id(fdata, PORT_FEATURE_ID_AFU))
return 0;

return attr->mode;
@@ -634,7 +642,7 @@ static int afu_release(struct inode *inode, struct file *filp)
dfl_fpga_dev_for_each_feature(fdata, feature)
dfl_fpga_set_irq_triggers(feature, 0,
feature->nr_irqs, NULL);
- __port_reset(pdev);
+ __port_reset(fdata);
afu_dma_region_destroy(fdata);
}
mutex_unlock(&fdata->lock);
@@ -884,15 +892,15 @@ static int afu_dev_destroy(struct platform_device *pdev)

static int port_enable_set(struct platform_device *pdev, bool enable)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
int ret;

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
if (enable)
- ret = __afu_port_enable(pdev);
+ ret = __afu_port_enable(fdata);
else
- ret = __afu_port_disable(pdev);
- mutex_unlock(&pdata->lock);
+ ret = __afu_port_disable(fdata);
+ mutex_unlock(&fdata->lock);

return ret;
}
diff --git a/drivers/fpga/dfl-afu.h b/drivers/fpga/dfl-afu.h
index 7bef3e300aa2..03be4f0969c7 100644
--- a/drivers/fpga/dfl-afu.h
+++ b/drivers/fpga/dfl-afu.h
@@ -76,27 +76,27 @@ struct dfl_afu {
struct rb_root dma_regions;
};

-/* hold pdata->lock when call __afu_port_enable/disable */
-int __afu_port_enable(struct platform_device *pdev);
-int __afu_port_disable(struct platform_device *pdev);
+/* hold fdata->lock when call __afu_port_enable/disable */
+int __afu_port_enable(struct dfl_feature_dev_data *fdata);
+int __afu_port_disable(struct dfl_feature_dev_data *fdata);

-void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);
-int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
+void afu_mmio_region_init(struct dfl_feature_dev_data *fdata);
+int afu_mmio_region_add(struct dfl_feature_dev_data *fdata,
u32 region_index, u64 region_size, u64 phys, u32 flags);
-void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata);
-int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
+void afu_mmio_region_destroy(struct dfl_feature_dev_data *fdata);
+int afu_mmio_region_get_by_index(struct dfl_feature_dev_data *fdata,
u32 region_index,
struct dfl_afu_mmio_region *pregion);
-int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
+int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata,
u64 offset, u64 size,
struct dfl_afu_mmio_region *pregion);
-void afu_dma_region_init(struct dfl_feature_platform_data *pdata);
-void afu_dma_region_destroy(struct dfl_feature_platform_data *pdata);
-int afu_dma_map_region(struct dfl_feature_platform_data *pdata,
+void afu_dma_region_init(struct dfl_feature_dev_data *fdata);
+void afu_dma_region_destroy(struct dfl_feature_dev_data *fdata);
+int afu_dma_map_region(struct dfl_feature_dev_data *fdata,
u64 user_addr, u64 length, u64 *iova);
-int afu_dma_unmap_region(struct dfl_feature_platform_data *pdata, u64 iova);
+int afu_dma_unmap_region(struct dfl_feature_dev_data *fdata, u64 iova);
struct dfl_afu_dma_region *
-afu_dma_region_find(struct dfl_feature_platform_data *pdata,
+afu_dma_region_find(struct dfl_feature_dev_data *fdata,
u64 iova, u64 size);

extern const struct dfl_feature_ops port_err_ops;
diff --git a/drivers/fpga/dfl-fme-error.c b/drivers/fpga/dfl-fme-error.c
index 51c2892ec06d..f00d949efe69 100644
--- a/drivers/fpga/dfl-fme-error.c
+++ b/drivers/fpga/dfl-fme-error.c
@@ -42,15 +42,15 @@
static ssize_t pcie0_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 value;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
value = readq(base + PCIE0_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
@@ -59,7 +59,7 @@ static ssize_t pcie0_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
int ret = 0;
u64 v, val;
@@ -67,9 +67,9 @@ static ssize_t pcie0_errors_store(struct device *dev,
if (kstrtou64(buf, 0, &val))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(GENMASK_ULL(63, 0), base + PCIE0_ERROR_MASK);

v = readq(base + PCIE0_ERROR);
@@ -79,7 +79,7 @@ static ssize_t pcie0_errors_store(struct device *dev,
ret = -EINVAL;

writeq(0ULL, base + PCIE0_ERROR_MASK);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(pcie0_errors);
@@ -87,15 +87,15 @@ static DEVICE_ATTR_RW(pcie0_errors);
static ssize_t pcie1_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 value;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
value = readq(base + PCIE1_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
@@ -104,7 +104,7 @@ static ssize_t pcie1_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
int ret = 0;
u64 v, val;
@@ -112,9 +112,9 @@ static ssize_t pcie1_errors_store(struct device *dev,
if (kstrtou64(buf, 0, &val))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(GENMASK_ULL(63, 0), base + PCIE1_ERROR_MASK);

v = readq(base + PCIE1_ERROR);
@@ -124,7 +124,7 @@ static ssize_t pcie1_errors_store(struct device *dev,
ret = -EINVAL;

writeq(0ULL, base + PCIE1_ERROR_MASK);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(pcie1_errors);
@@ -132,9 +132,10 @@ static DEVICE_ATTR_RW(pcie1_errors);
static ssize_t nonfatal_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

return sprintf(buf, "0x%llx\n",
(unsigned long long)readq(base + RAS_NONFAT_ERROR));
@@ -144,9 +145,10 @@ static DEVICE_ATTR_RO(nonfatal_errors);
static ssize_t catfatal_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

return sprintf(buf, "0x%llx\n",
(unsigned long long)readq(base + RAS_CATFAT_ERROR));
@@ -156,15 +158,15 @@ static DEVICE_ATTR_RO(catfatal_errors);
static ssize_t inject_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + RAS_ERROR_INJECT);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n",
(unsigned long long)FIELD_GET(INJECT_ERROR_MASK, v));
@@ -174,7 +176,7 @@ static ssize_t inject_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u8 inject_error;
u64 v;
@@ -185,14 +187,14 @@ static ssize_t inject_errors_store(struct device *dev,
if (inject_error & ~INJECT_ERROR_MASK)
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
v = readq(base + RAS_ERROR_INJECT);
v &= ~INJECT_ERROR_MASK;
v |= FIELD_PREP(INJECT_ERROR_MASK, inject_error);
writeq(v, base + RAS_ERROR_INJECT);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return count;
}
@@ -201,15 +203,15 @@ static DEVICE_ATTR_RW(inject_errors);
static ssize_t fme_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 value;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
value = readq(base + FME_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
@@ -218,7 +220,7 @@ static ssize_t fme_errors_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v, val;
int ret = 0;
@@ -226,9 +228,9 @@ static ssize_t fme_errors_store(struct device *dev,
if (kstrtou64(buf, 0, &val))
return -EINVAL;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
writeq(GENMASK_ULL(63, 0), base + FME_ERROR_MASK);

v = readq(base + FME_ERROR);
@@ -240,7 +242,7 @@ static ssize_t fme_errors_store(struct device *dev,
/* Workaround: disable MBP_ERROR if feature revision is 0 */
writeq(dfl_feature_revision(base) ? 0ULL : MBP_ERROR,
base + FME_ERROR_MASK);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
return ret ? ret : count;
}
static DEVICE_ATTR_RW(fme_errors);
@@ -248,15 +250,15 @@ static DEVICE_ATTR_RW(fme_errors);
static ssize_t first_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 value;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
value = readq(base + FME_FIRST_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
@@ -265,15 +267,15 @@ static DEVICE_ATTR_RO(first_error);
static ssize_t next_error_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 value;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
value = readq(base + FME_NEXT_ERROR);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

return sprintf(buf, "0x%llx\n", (unsigned long long)value);
}
@@ -295,12 +297,14 @@ static umode_t fme_global_err_attrs_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
+ struct dfl_feature_dev_data *fdata;

+ fdata = to_dfl_feature_dev_data(dev);
/*
* sysfs entries are visible only if related private feature is
* enumerated.
*/
- if (!dfl_get_feature_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR))
+ if (!dfl_get_feature_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR))
return 0;

return attr->mode;
@@ -314,12 +318,12 @@ const struct attribute_group fme_global_err_group = {

static void fme_err_mask(struct device *dev, bool mask)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_GLOBAL_ERR);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);

/* Workaround: keep MBP_ERROR always masked if revision is 0 */
if (dfl_feature_revision(base))
@@ -332,7 +336,7 @@ static void fme_err_mask(struct device *dev, bool mask)
writeq(mask ? ERROR_MASK : 0, base + RAS_NONFAT_ERROR_MASK);
writeq(mask ? ERROR_MASK : 0, base + RAS_CATFAT_ERROR_MASK);

- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);
}

static int fme_global_err_init(struct platform_device *pdev,
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 7f119b09b54e..d271d1e60efd 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -28,10 +28,11 @@
static ssize_t ports_num_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_CAP);

@@ -47,10 +48,11 @@ static DEVICE_ATTR_RO(ports_num);
static ssize_t bitstream_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_BITSTREAM_ID);

@@ -65,10 +67,11 @@ static DEVICE_ATTR_RO(bitstream_id);
static ssize_t bitstream_metadata_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_BITSTREAM_MD);

@@ -79,10 +82,11 @@ static DEVICE_ATTR_RO(bitstream_metadata);
static ssize_t cache_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_CAP);

@@ -94,10 +98,11 @@ static DEVICE_ATTR_RO(cache_size);
static ssize_t fabric_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_CAP);

@@ -109,10 +114,11 @@ static DEVICE_ATTR_RO(fabric_version);
static ssize_t socket_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_CAP);

diff --git a/drivers/fpga/dfl-fme-pr.c b/drivers/fpga/dfl-fme-pr.c
index f4c95c4b88d9..7cc591df3ebb 100644
--- a/drivers/fpga/dfl-fme-pr.c
+++ b/drivers/fpga/dfl-fme-pr.c
@@ -87,8 +87,7 @@ static int fme_pr(struct platform_device *pdev, unsigned long arg)
return -EINVAL;

/* get fme header region */
- fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev,
- FME_FEATURE_ID_HEADER);
+ fme_hdr = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

/* check port id */
v = readq(fme_hdr + FME_HDR_CAP);
@@ -379,8 +378,7 @@ static int pr_mgmt_init(struct platform_device *pdev,
int ret = -ENODEV, i = 0;
u64 fme_cap, port_offset;

- fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev,
- FME_FEATURE_ID_HEADER);
+ fme_hdr = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

mutex_lock(&fdata->lock);
priv = dfl_fpga_fdata_get_private(fdata);
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 094ee97ea26c..219d52cce924 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -1789,10 +1789,11 @@ EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port);
static void config_port_access_mode(struct device *fme_dev, int port_id,
bool is_vf)
{
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(fme_dev);
void __iomem *base;
u64 v;

- base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER);
+ base = dfl_get_feature_ioaddr_by_id(fdata, FME_FEATURE_ID_HEADER);

v = readq(base + FME_HDR_PORT_OFST(port_id));

diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index b700f5bb7be7..7ea96788a969 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -414,23 +414,22 @@ struct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)
for ((feature) = (fdata)->features; \
(feature) < (fdata)->features + (fdata)->num; (feature)++)

-static inline
-struct dfl_feature *dfl_get_feature_by_id(struct device *dev, u16 id)
+static inline struct dfl_feature *
+dfl_get_feature_by_id(struct dfl_feature_dev_data *fdata, u16 id)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct dfl_feature *feature;

- dfl_fpga_dev_for_each_feature(pdata, feature)
+ dfl_fpga_dev_for_each_feature(fdata, feature)
if (feature->id == id)
return feature;

return NULL;
}

-static inline
-void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u16 id)
+static inline void __iomem *
+dfl_get_feature_ioaddr_by_id(struct dfl_feature_dev_data *fdata, u16 id)
{
- struct dfl_feature *feature = dfl_get_feature_by_id(dev, id);
+ struct dfl_feature *feature = dfl_get_feature_by_id(fdata, id);

if (feature && feature->ioaddr)
return feature->ioaddr;
--
2.44.0


2024-04-09 23:44:10

by Colberg, Peter

[permalink] [raw]
Subject: [RFC PATCH v2 9/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

From: Xu Yilun <[email protected]>

DFL ports are registered as platform devices in PF mode. The port device
should be removed from the host when the user wants to configure the
port as a VF and pass through to a virtual machine. The FME device
ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.

In the previous implementation, the port platform device is not completely
destroyed on port release: it is removed from the system by
platform_device_del(), but the platform device instance is retained.
When the port assign ioctl is called, the platform device is added back by
platform_device_add(), which conflicts with this comment of device_add():
"Do not call this routine more than once for any device structure", and
will cause a kernel warning at runtime.

This patch tries to completely unregister the port platform device on
release and registers a new one on assign. But the main work is to remove
the dependency on struct dfl_feature_platform_data for many internal DFL
APIs. This structure holds many DFL enumeration infos for feature devices.
Many DFL APIs are expected to work with these info even when the port
platform device is unregistered. But with the change the platform_data will
be freed in this case. So this patch introduces a new structure
dfl_feature_dev_data for these APIs, which acts similarly to the previous
dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
pointer to dfl_feature_dev_data to make the feature device driver work.

Signed-off-by: Xu Yilun <[email protected]>
Signed-off-by: Russ Weight <[email protected]>
Signed-off-by: Peter Colberg <[email protected]>
---
v2:
- Split monolithic patch into series at request of maintainer
- Substitute binfo->type for removed function feature_dev_id_type() in
parse_feature_irqs().
- Return ERR_PTR(-ENOMEM) on !feature->params in
binfo_create_feature_dev_data().
- Reorder cdev as first member of struct dfl_feature_platform_data
such that container_of() to obtain pdata evaluates to a no-op.
- Align kernel-doc function name for __dfl_fpga_cdev_find_port_data().
---
drivers/fpga/dfl-afu-main.c | 9 +-
drivers/fpga/dfl-fme-br.c | 24 +-
drivers/fpga/dfl-fme-main.c | 6 +-
drivers/fpga/dfl.c | 430 +++++++++++++++++-------------------
drivers/fpga/dfl.h | 86 +++++---
5 files changed, 281 insertions(+), 274 deletions(-)

diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 42928cc7e42b..ead03b7aea70 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -143,9 +143,8 @@ static int port_reset(struct platform_device *pdev)
return ret;
}

-static int port_get_id(struct platform_device *pdev)
+static int port_get_id(struct dfl_feature_dev_data *fdata)
{
- struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
void __iomem *base;

base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);
@@ -156,7 +155,8 @@ static int port_get_id(struct platform_device *pdev)
static ssize_t
id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- int id = port_get_id(to_platform_device(dev));
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
+ int id = port_get_id(fdata);

return scnprintf(buf, PAGE_SIZE, "%d\n", id);
}
@@ -890,9 +890,8 @@ static int afu_dev_destroy(struct platform_device *pdev)
return 0;
}

-static int port_enable_set(struct platform_device *pdev, bool enable)
+static int port_enable_set(struct dfl_feature_dev_data *fdata, bool enable)
{
- struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
int ret;

mutex_lock(&fdata->lock);
diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
index 0b01b3895277..a298a041877b 100644
--- a/drivers/fpga/dfl-fme-br.c
+++ b/drivers/fpga/dfl-fme-br.c
@@ -22,34 +22,34 @@
struct fme_br_priv {
struct dfl_fme_br_pdata *pdata;
struct dfl_fpga_port_ops *port_ops;
- struct platform_device *port_pdev;
+ struct dfl_feature_dev_data *port_fdata;
};

static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
{
struct fme_br_priv *priv = bridge->priv;
- struct platform_device *port_pdev;
+ struct dfl_feature_dev_data *port_fdata;
struct dfl_fpga_port_ops *ops;

- if (!priv->port_pdev) {
- port_pdev = dfl_fpga_cdev_find_port(priv->pdata->cdev,
- &priv->pdata->port_id,
- dfl_fpga_check_port_id);
- if (!port_pdev)
+ if (!priv->port_fdata) {
+ port_fdata = dfl_fpga_cdev_find_port_data(priv->pdata->cdev,
+ &priv->pdata->port_id,
+ dfl_fpga_check_port_id);
+ if (!port_fdata)
return -ENODEV;

- priv->port_pdev = port_pdev;
+ priv->port_fdata = port_fdata;
}

- if (priv->port_pdev && !priv->port_ops) {
- ops = dfl_fpga_port_ops_get(priv->port_pdev);
+ if (priv->port_fdata && !priv->port_ops) {
+ ops = dfl_fpga_port_ops_get(priv->port_fdata);
if (!ops || !ops->enable_set)
return -ENOENT;

priv->port_ops = ops;
}

- return priv->port_ops->enable_set(priv->port_pdev, enable);
+ return priv->port_ops->enable_set(priv->port_fdata, enable);
}

static const struct fpga_bridge_ops fme_bridge_ops = {
@@ -85,8 +85,6 @@ static void fme_br_remove(struct platform_device *pdev)

fpga_bridge_unregister(br);

- if (priv->port_pdev)
- put_device(&priv->port_pdev->dev);
if (priv->port_ops)
dfl_fpga_port_ops_put(priv->port_ops);
}
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index d271d1e60efd..e0a35c701121 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -612,7 +612,7 @@ static int fme_open(struct inode *inode, struct file *filp)
if (WARN_ON(!pdata))
return -ENODEV;

- fdata = pdata;
+ fdata = pdata->fdata;
mutex_lock(&fdata->lock);
ret = dfl_feature_dev_use_begin(fdata, filp->f_flags & O_EXCL);
if (!ret) {
@@ -628,7 +628,7 @@ static int fme_open(struct inode *inode, struct file *filp)
static int fme_release(struct inode *inode, struct file *filp)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
- struct dfl_feature_dev_data *fdata = pdata;
+ struct dfl_feature_dev_data *fdata = pdata->fdata;
struct platform_device *pdev = fdata->dev;
struct dfl_feature *feature;

@@ -649,7 +649,7 @@ static int fme_release(struct inode *inode, struct file *filp)
static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
- struct dfl_feature_dev_data *fdata = pdata;
+ struct dfl_feature_dev_data *fdata = pdata->fdata;
struct platform_device *pdev = fdata->dev;
struct dfl_feature *f;
long ret;
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 219d52cce924..916db9960fa0 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -119,17 +119,6 @@ static void dfl_id_free(enum dfl_id_type type, int id)
mutex_unlock(&dfl_id_mutex);
}

-static enum dfl_id_type feature_dev_id_type(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dfl_devs); i++)
- if (!strcmp(dfl_devs[i].name, pdev->name))
- return i;
-
- return DFL_ID_MAX;
-}
-
static enum dfl_id_type dfh_id_to_type(u16 id)
{
int i;
@@ -161,7 +150,8 @@ static LIST_HEAD(dfl_port_ops_list);
*
* Please note that must dfl_fpga_port_ops_put after use the port_ops.
*/
-struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev)
+struct dfl_fpga_port_ops *
+dfl_fpga_port_ops_get(struct dfl_feature_dev_data *fdata)
{
struct dfl_fpga_port_ops *ops = NULL;

@@ -171,7 +161,7 @@ struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev)

list_for_each_entry(ops, &dfl_port_ops_list, node) {
/* match port_ops using the name of platform device */
- if (!strcmp(pdev->name, ops->name)) {
+ if (!strcmp(fdata->pdev_name, ops->name)) {
if (!try_module_get(ops->owner))
ops = NULL;
goto done;
@@ -227,22 +217,21 @@ EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
*
* Return: 1 if port device matches with given port id, otherwise 0.
*/
-int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
+int dfl_fpga_check_port_id(struct dfl_feature_dev_data *fdata, void *pport_id)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fpga_port_ops *port_ops;

- if (pdata->id != FEATURE_DEV_ID_UNUSED)
- return pdata->id == *(int *)pport_id;
+ if (fdata->id != FEATURE_DEV_ID_UNUSED)
+ return fdata->id == *(int *)pport_id;

- port_ops = dfl_fpga_port_ops_get(pdev);
+ port_ops = dfl_fpga_port_ops_get(fdata);
if (!port_ops || !port_ops->get_id)
return 0;

- pdata->id = port_ops->get_id(pdev);
+ fdata->id = port_ops->get_id(fdata);
dfl_fpga_port_ops_put(port_ops);

- return pdata->id == *(int *)pport_id;
+ return fdata->id == *(int *)pport_id;
}
EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);

@@ -351,10 +340,10 @@ static void release_dfl_dev(struct device *dev)
}

static struct dfl_device *
-dfl_dev_add(struct dfl_feature_platform_data *pdata,
+dfl_dev_add(struct dfl_feature_dev_data *fdata,
struct dfl_feature *feature)
{
- struct platform_device *pdev = pdata->dev;
+ struct platform_device *pdev = fdata->dev;
struct resource *parent_res;
struct dfl_device *ddev;
int id, i, ret;
@@ -380,11 +369,11 @@ dfl_dev_add(struct dfl_feature_platform_data *pdata,
if (ret)
goto put_dev;

- ddev->type = feature_dev_id_type(pdev);
+ ddev->type = fdata->type;
ddev->feature_id = feature->id;
ddev->revision = feature->revision;
ddev->dfh_version = feature->dfh_version;
- ddev->cdev = pdata->dfl_cdev;
+ ddev->cdev = fdata->dfl_cdev;
if (feature->param_size) {
ddev->params = kmemdup(feature->params, feature->param_size, GFP_KERNEL);
if (!ddev->params) {
@@ -435,11 +424,11 @@ dfl_dev_add(struct dfl_feature_platform_data *pdata,
return ERR_PTR(ret);
}

-static void dfl_devs_remove(struct dfl_feature_platform_data *pdata)
+static void dfl_devs_remove(struct dfl_feature_dev_data *fdata)
{
struct dfl_feature *feature;

- dfl_fpga_dev_for_each_feature(pdata, feature) {
+ dfl_fpga_dev_for_each_feature(fdata, feature) {
if (feature->ddev) {
device_unregister(&feature->ddev->dev);
feature->ddev = NULL;
@@ -447,13 +436,13 @@ static void dfl_devs_remove(struct dfl_feature_platform_data *pdata)
}
}

-static int dfl_devs_add(struct dfl_feature_platform_data *pdata)
+static int dfl_devs_add(struct dfl_feature_dev_data *fdata)
{
struct dfl_feature *feature;
struct dfl_device *ddev;
int ret;

- dfl_fpga_dev_for_each_feature(pdata, feature) {
+ dfl_fpga_dev_for_each_feature(fdata, feature) {
if (feature->ioaddr)
continue;

@@ -462,7 +451,7 @@ static int dfl_devs_add(struct dfl_feature_platform_data *pdata)
goto err;
}

- ddev = dfl_dev_add(pdata, feature);
+ ddev = dfl_dev_add(fdata, feature);
if (IS_ERR(ddev)) {
ret = PTR_ERR(ddev);
goto err;
@@ -474,7 +463,7 @@ static int dfl_devs_add(struct dfl_feature_platform_data *pdata)
return 0;

err:
- dfl_devs_remove(pdata);
+ dfl_devs_remove(fdata);
return ret;
}

@@ -505,11 +494,12 @@ EXPORT_SYMBOL(dfl_driver_unregister);
void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = pdata->fdata;
struct dfl_feature *feature;

- dfl_devs_remove(pdata);
+ dfl_devs_remove(fdata);

- dfl_fpga_dev_for_each_feature(pdata, feature) {
+ dfl_fpga_dev_for_each_feature(fdata, feature) {
if (feature->ops) {
if (feature->ops->uinit)
feature->ops->uinit(pdev, feature);
@@ -580,12 +570,13 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev,
struct dfl_feature_driver *feature_drvs)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = pdata->fdata;
struct dfl_feature_driver *drv = feature_drvs;
struct dfl_feature *feature;
int ret;

while (drv->ops) {
- dfl_fpga_dev_for_each_feature(pdata, feature) {
+ dfl_fpga_dev_for_each_feature(fdata, feature) {
if (dfl_feature_drv_match(feature, drv)) {
ret = dfl_feature_instance_init(pdev, pdata,
feature, drv);
@@ -596,7 +587,7 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev,
drv++;
}

- ret = dfl_devs_add(pdata);
+ ret = dfl_devs_add(fdata);
if (ret)
goto exit;

@@ -695,7 +686,7 @@ EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
* @nr_irqs: number of irqs for all feature devices.
* @irq_table: Linux IRQ numbers for all irqs, indexed by local irq index of
* this device.
- * @feature_dev: current feature device.
+ * @type: the current FIU type.
* @ioaddr: header register region address of current FIU in enumeration.
* @start: register resource start of current FIU.
* @len: max register resource length of current FIU.
@@ -708,7 +699,7 @@ struct build_feature_devs_info {
unsigned int nr_irqs;
int *irq_table;

- struct platform_device *feature_dev;
+ enum dfl_id_type type;
void __iomem *ioaddr;
resource_size_t start;
resource_size_t len;
@@ -743,50 +734,51 @@ struct dfl_feature_info {
u64 params[];
};

-static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
- struct platform_device *port)
+static void dfl_fpga_cdev_add_port_data(struct dfl_fpga_cdev *cdev,
+ struct dfl_feature_dev_data *fdata)
{
- struct dfl_feature_platform_data *pdata = dev_get_platdata(&port->dev);
-
mutex_lock(&cdev->lock);
- list_add(&pdata->node, &cdev->port_dev_list);
- get_device(&pdata->dev->dev);
+ list_add(&fdata->node, &cdev->port_dev_list);
mutex_unlock(&cdev->lock);
}

-/*
- * register current feature device, it is called when we need to switch to
- * another feature parsing or we have parsed all features on given device
- * feature list.
- */
-static int build_info_commit_dev(struct build_feature_devs_info *binfo)
+static struct dfl_feature_dev_data *
+binfo_create_feature_dev_data(struct build_feature_devs_info *binfo)
{
- struct platform_device *fdev = binfo->feature_dev;
- struct dfl_feature_platform_data *pdata;
+ enum dfl_id_type type = binfo->type;
struct dfl_feature_info *finfo, *p;
- enum dfl_id_type type;
+ struct dfl_feature_dev_data *fdata;
int ret, index = 0, res_idx = 0;

- type = feature_dev_id_type(fdev);
if (WARN_ON_ONCE(type >= DFL_ID_MAX))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);

- /*
- * we do not need to care for the memory which is associated with
- * the platform device. After calling platform_device_unregister(),
- * it will be automatically freed by device's release() callback,
- * platform_device_release().
- */
- pdata = kzalloc(struct_size(pdata, features, binfo->feature_num), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
+ fdata = devm_kzalloc(binfo->dev, sizeof(*fdata), GFP_KERNEL);
+ if (!fdata)
+ return ERR_PTR(-ENOMEM);
+
+ fdata->features = devm_kcalloc(binfo->dev, binfo->feature_num,
+ sizeof(*fdata->features), GFP_KERNEL);
+ if (!fdata->features)
+ return ERR_PTR(-ENOMEM);
+
+ fdata->resources = devm_kcalloc(binfo->dev, binfo->feature_num,
+ sizeof(*fdata->resources), GFP_KERNEL);
+ if (!fdata->resources)
+ return ERR_PTR(-ENOMEM);
+
+ fdata->type = type;
+
+ fdata->pdev_id = dfl_id_alloc(type, binfo->dev);
+ if (fdata->pdev_id < 0)
+ return ERR_PTR(fdata->pdev_id);

- pdata->dev = fdev;
- pdata->num = binfo->feature_num;
- pdata->dfl_cdev = binfo->cdev;
- pdata->id = FEATURE_DEV_ID_UNUSED;
- mutex_init(&pdata->lock);
- lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type],
+ fdata->pdev_name = dfl_devs[type].name;
+ fdata->num = binfo->feature_num;
+ fdata->dfl_cdev = binfo->cdev;
+ fdata->id = FEATURE_DEV_ID_UNUSED;
+ mutex_init(&fdata->lock);
+ lockdep_set_class_and_name(&fdata->lock, &dfl_pdata_keys[type],
dfl_pdata_key_strings[type]);

/*
@@ -795,25 +787,15 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
* works properly for port device.
* and it should always be 0 for fme device.
*/
- WARN_ON(pdata->disable_count);
-
- fdev->dev.platform_data = pdata;
-
- /* each sub feature has one MMIO resource */
- fdev->num_resources = binfo->feature_num;
- fdev->resource = kcalloc(binfo->feature_num, sizeof(*fdev->resource),
- GFP_KERNEL);
- if (!fdev->resource)
- return -ENOMEM;
+ WARN_ON(fdata->disable_count);

/* fill features and resource information for feature dev */
list_for_each_entry_safe(finfo, p, &binfo->sub_features, node) {
- struct dfl_feature *feature = &pdata->features[index++];
+ struct dfl_feature *feature = &fdata->features[index++];
struct dfl_feature_irq_ctx *ctx;
unsigned int i;

/* save resource information for each feature */
- feature->dev = fdev;
feature->id = finfo->fid;
feature->revision = finfo->revision;
feature->dfh_version = finfo->dfh_version;
@@ -823,7 +805,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
finfo->params, finfo->param_size,
GFP_KERNEL);
if (!feature->params)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);

feature->param_size = finfo->param_size;
}
@@ -839,19 +821,22 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
feature->ioaddr =
devm_ioremap_resource(binfo->dev,
&finfo->mmio_res);
- if (IS_ERR(feature->ioaddr))
- return PTR_ERR(feature->ioaddr);
+ if (IS_ERR(feature->ioaddr)) {
+ ret = PTR_ERR(feature->ioaddr);
+ goto err_free_id;
+ }
} else {
feature->resource_index = res_idx;
- fdev->resource[res_idx++] = finfo->mmio_res;
+ fdata->resources[res_idx++] = finfo->mmio_res;
}

if (finfo->nr_irqs) {
ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs,
sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
+ if (!ctx) {
+ ret = -ENOMEM;
+ goto err_free_id;
+ }
for (i = 0; i < finfo->nr_irqs; i++)
ctx[i].irq =
binfo->irq_table[finfo->irq_base + i];
@@ -864,55 +849,90 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
kfree(finfo);
}

- ret = platform_device_add(binfo->feature_dev);
- if (!ret) {
- if (type == PORT_ID)
- dfl_fpga_cdev_add_port_dev(binfo->cdev,
- binfo->feature_dev);
- else
- binfo->cdev->fme_dev =
- get_device(&binfo->feature_dev->dev);
- /*
- * reset it to avoid build_info_free() freeing their resource.
- *
- * The resource of successfully registered feature devices
- * will be freed by platform_device_unregister(). See the
- * comments in build_info_create_dev().
- */
- binfo->feature_dev = NULL;
- }
+ fdata->resource_num = res_idx;

- return ret;
+ return fdata;
+
+err_free_id:
+ dfl_id_free(type, fdata->pdev_id);
+
+ return ERR_PTR(ret);
}

-static int
-build_info_create_dev(struct build_feature_devs_info *binfo,
- enum dfl_id_type type)
+/*
+ * register current feature device, it is called when we need to switch to
+ * another feature parsing or we have parsed all features on given device
+ * feature list.
+ */
+static int feature_dev_register(struct dfl_feature_dev_data *fdata)
{
+ struct dfl_feature_platform_data pdata = { 0 };
struct platform_device *fdev;
+ struct dfl_feature *feature;
+ int ret;

- if (type >= DFL_ID_MAX)
- return -EINVAL;
-
- /*
- * we use -ENODEV as the initialization indicator which indicates
- * whether the id need to be reclaimed
- */
- fdev = platform_device_alloc(dfl_devs[type].name, -ENODEV);
+ fdev = platform_device_alloc(fdata->pdev_name, fdata->pdev_id);
if (!fdev)
return -ENOMEM;

- binfo->feature_dev = fdev;
- binfo->feature_num = 0;
+ fdata->dev = fdev;

- INIT_LIST_HEAD(&binfo->sub_features);
+ fdev->dev.parent = &fdata->dfl_cdev->region->dev;
+ fdev->dev.devt = dfl_get_devt(dfl_devs[fdata->type].devt_type,
+ fdev->id);
+
+ dfl_fpga_dev_for_each_feature(fdata, feature)
+ feature->dev = fdev;

- fdev->id = dfl_id_alloc(type, &fdev->dev);
- if (fdev->id < 0)
- return fdev->id;
+ ret = platform_device_add_resources(fdev, fdata->resources,
+ fdata->resource_num);
+ if (ret)
+ goto err_put_dev;
+
+ pdata.fdata = fdata;
+ ret = platform_device_add_data(fdev, &pdata, sizeof(pdata));
+ if (ret)
+ goto err_put_dev;

- fdev->dev.parent = &binfo->cdev->region->dev;
- fdev->dev.devt = dfl_get_devt(dfl_devs[type].devt_type, fdev->id);
+ ret = platform_device_add(fdev);
+ if (ret)
+ goto err_put_dev;
+
+ return 0;
+
+err_put_dev:
+ platform_device_put(fdev);
+ fdata->dev = NULL;
+
+ return ret;
+}
+
+static void feature_dev_unregister(struct dfl_feature_dev_data *fdata)
+{
+ platform_device_unregister(fdata->dev);
+ fdata->dev = NULL;
+}
+
+static int build_info_commit_dev(struct build_feature_devs_info *binfo)
+{
+ struct dfl_feature_dev_data *fdata;
+ int ret;
+
+ fdata = binfo_create_feature_dev_data(binfo);
+ if (IS_ERR(fdata))
+ return PTR_ERR(fdata);
+
+ ret = feature_dev_register(fdata);
+ if (ret)
+ return ret;
+
+ if (binfo->type == PORT_ID)
+ dfl_fpga_cdev_add_port_data(binfo->cdev, fdata);
+ else
+ binfo->cdev->fme_dev = get_device(&fdata->dev->dev);
+
+ /* reset the binfo for next FIU */
+ binfo->type = DFL_ID_MAX;

return 0;
}
@@ -921,22 +941,11 @@ 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(feature_dev_id_type(binfo->feature_dev),
- 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);
-
devm_kfree(binfo->dev, binfo);
}

@@ -1025,7 +1034,7 @@ static int parse_feature_irqs(struct build_feature_devs_info *binfo,
* Instead, features with interrupt functionality provide
* the information in feature specific registers.
*/
- type = feature_dev_id_type(binfo->feature_dev);
+ type = binfo->type;
if (type == PORT_ID) {
switch (fid) {
case PORT_FEATURE_ID_UINT:
@@ -1217,7 +1226,7 @@ static int parse_feature_port_afu(struct build_feature_devs_info *binfo,
return create_feature_instance(binfo, ofst, size, FEATURE_ID_AFU);
}

-#define is_feature_dev_detected(binfo) (!!(binfo)->feature_dev)
+#define is_feature_dev_detected(binfo) ((binfo)->type != DFL_ID_MAX)

static int parse_feature_afu(struct build_feature_devs_info *binfo,
resource_size_t ofst)
@@ -1227,12 +1236,11 @@ static int parse_feature_afu(struct build_feature_devs_info *binfo,
return -EINVAL;
}

- switch (feature_dev_id_type(binfo->feature_dev)) {
+ switch (binfo->type) {
case PORT_ID:
return parse_feature_port_afu(binfo, ofst);
default:
- dev_info(binfo->dev, "AFU belonging to FIU %s is not supported yet.\n",
- binfo->feature_dev->name);
+ dev_info(binfo->dev, "AFU belonging to FIU is not supported yet.\n");
}

return 0;
@@ -1273,6 +1281,7 @@ static void build_info_complete(struct build_feature_devs_info *binfo)
static int parse_feature_fiu(struct build_feature_devs_info *binfo,
resource_size_t ofst)
{
+ enum dfl_id_type type;
int ret = 0;
u32 offset;
u16 id;
@@ -1294,10 +1303,13 @@ static int parse_feature_fiu(struct build_feature_devs_info *binfo,
v = readq(binfo->ioaddr + DFH);
id = FIELD_GET(DFH_ID, v);

- /* create platform device for dfl feature dev */
- ret = build_info_create_dev(binfo, dfh_id_to_type(id));
- if (ret)
- return ret;
+ type = dfh_id_to_type(id);
+ if (type >= DFL_ID_MAX)
+ return -EINVAL;
+
+ binfo->type = type;
+ binfo->feature_num = 0;
+ INIT_LIST_HEAD(&binfo->sub_features);

ret = create_feature_instance(binfo, 0, 0, 0);
if (ret)
@@ -1515,13 +1527,10 @@ EXPORT_SYMBOL_GPL(dfl_fpga_enum_info_add_irq);

static int remove_feature_dev(struct device *dev, void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
- enum dfl_id_type type = feature_dev_id_type(pdev);
- int id = pdev->id;
-
- platform_device_unregister(pdev);
+ struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);

- dfl_id_free(type, id);
+ feature_dev_unregister(fdata);
+ dfl_id_free(fdata->type, fdata->pdev_id);

return 0;
}
@@ -1573,6 +1582,7 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
goto unregister_region_exit;
}

+ binfo->type = DFL_ID_MAX;
binfo->dev = info->dev;
binfo->cdev = cdev;

@@ -1614,25 +1624,10 @@ EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_enumerate);
*/
void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
{
- struct dfl_feature_platform_data *pdata, *ptmp;
-
mutex_lock(&cdev->lock);
if (cdev->fme_dev)
put_device(cdev->fme_dev);

- list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
- struct platform_device *port_dev = pdata->dev;
-
- /* remove released ports */
- if (!device_is_registered(&port_dev->dev)) {
- dfl_id_free(feature_dev_id_type(port_dev),
- port_dev->id);
- platform_device_put(port_dev);
- }
-
- list_del(&pdata->node);
- put_device(&port_dev->dev);
- }
mutex_unlock(&cdev->lock);

remove_feature_devs(cdev);
@@ -1643,7 +1638,7 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove);

/**
- * __dfl_fpga_cdev_find_port - find a port under given container device
+ * __dfl_fpga_cdev_find_port_data - find a port under given container device
*
* @cdev: container device
* @data: data passed to match function
@@ -1656,23 +1651,21 @@ EXPORT_SYMBOL_GPL(dfl_fpga_feature_devs_remove);
*
* NOTE: you will need to drop the device reference with put_device() after use.
*/
-struct platform_device *
-__dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
- int (*match)(struct platform_device *, void *))
+struct dfl_feature_dev_data *
+__dfl_fpga_cdev_find_port_data(struct dfl_fpga_cdev *cdev, void *data,
+ int (*match)(struct dfl_feature_dev_data *,
+ void *))
{
- struct dfl_feature_platform_data *pdata;
- struct platform_device *port_dev;
-
- list_for_each_entry(pdata, &cdev->port_dev_list, node) {
- port_dev = pdata->dev;
+ struct dfl_feature_dev_data *fdata;

- if (match(port_dev, data) && get_device(&port_dev->dev))
- return port_dev;
+ list_for_each_entry(fdata, &cdev->port_dev_list, node) {
+ if (match(fdata, data))
+ return fdata;
}

return NULL;
}
-EXPORT_SYMBOL_GPL(__dfl_fpga_cdev_find_port);
+EXPORT_SYMBOL_GPL(__dfl_fpga_cdev_find_port_data);

static int __init dfl_fpga_init(void)
{
@@ -1706,33 +1699,29 @@ static int __init dfl_fpga_init(void)
*/
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
{
- struct dfl_feature_platform_data *pdata;
- struct platform_device *port_pdev;
+ struct dfl_feature_dev_data *fdata;
int ret = -ENODEV;

mutex_lock(&cdev->lock);
- port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
- dfl_fpga_check_port_id);
- if (!port_pdev)
+ fdata = __dfl_fpga_cdev_find_port_data(cdev, &port_id,
+ dfl_fpga_check_port_id);
+ if (!fdata)
goto unlock_exit;

- if (!device_is_registered(&port_pdev->dev)) {
+ if (!fdata->dev) {
ret = -EBUSY;
- goto put_dev_exit;
+ goto unlock_exit;
}

- pdata = dev_get_platdata(&port_pdev->dev);
-
- mutex_lock(&pdata->lock);
- ret = dfl_feature_dev_use_begin(pdata, true);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ ret = dfl_feature_dev_use_begin(fdata, true);
+ mutex_unlock(&fdata->lock);
if (ret)
- goto put_dev_exit;
+ goto unlock_exit;

- platform_device_del(port_pdev);
+ feature_dev_unregister(fdata);
cdev->released_port_num++;
-put_dev_exit:
- put_device(&port_pdev->dev);
+
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
@@ -1752,34 +1741,30 @@ EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
*/
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
{
- struct dfl_feature_platform_data *pdata;
- struct platform_device *port_pdev;
+ struct dfl_feature_dev_data *fdata;
int ret = -ENODEV;

mutex_lock(&cdev->lock);
- port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
- dfl_fpga_check_port_id);
- if (!port_pdev)
+ fdata = __dfl_fpga_cdev_find_port_data(cdev, &port_id,
+ dfl_fpga_check_port_id);
+ if (!fdata)
goto unlock_exit;

- if (device_is_registered(&port_pdev->dev)) {
+ if (fdata->dev) {
ret = -EBUSY;
- goto put_dev_exit;
+ goto unlock_exit;
}

- ret = platform_device_add(port_pdev);
+ ret = feature_dev_register(fdata);
if (ret)
- goto put_dev_exit;
-
- pdata = dev_get_platdata(&port_pdev->dev);
+ goto unlock_exit;

- mutex_lock(&pdata->lock);
- dfl_feature_dev_use_end(pdata);
- mutex_unlock(&pdata->lock);
+ mutex_lock(&fdata->lock);
+ dfl_feature_dev_use_end(fdata);
+ mutex_unlock(&fdata->lock);

cdev->released_port_num--;
-put_dev_exit:
- put_device(&port_pdev->dev);
+
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
@@ -1817,14 +1802,14 @@ static void config_port_access_mode(struct device *fme_dev, int port_id,
*/
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev)
{
- struct dfl_feature_platform_data *pdata;
+ struct dfl_feature_dev_data *fdata;

mutex_lock(&cdev->lock);
- list_for_each_entry(pdata, &cdev->port_dev_list, node) {
- if (device_is_registered(&pdata->dev->dev))
+ list_for_each_entry(fdata, &cdev->port_dev_list, node) {
+ if (fdata->dev)
continue;

- config_port_pf_mode(cdev->fme_dev, pdata->id);
+ config_port_pf_mode(cdev->fme_dev, fdata->id);
}
mutex_unlock(&cdev->lock);
}
@@ -1843,7 +1828,7 @@ EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf);
*/
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
{
- struct dfl_feature_platform_data *pdata;
+ struct dfl_feature_dev_data *fdata;
int ret = 0;

mutex_lock(&cdev->lock);
@@ -1857,11 +1842,11 @@ int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
goto done;
}

- list_for_each_entry(pdata, &cdev->port_dev_list, node) {
- if (device_is_registered(&pdata->dev->dev))
+ list_for_each_entry(fdata, &cdev->port_dev_list, node) {
+ if (fdata->dev)
continue;

- config_port_vf_mode(cdev->fme_dev, pdata->id);
+ config_port_vf_mode(cdev->fme_dev, fdata->id);
}
done:
mutex_unlock(&cdev->lock);
@@ -1995,6 +1980,7 @@ long dfl_feature_ioctl_set_irq(struct platform_device *pdev,
unsigned long arg)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct dfl_feature_dev_data *fdata = pdata->fdata;
struct dfl_fpga_irq_set hdr;
s32 *fds;
long ret;
@@ -2014,9 +2000,9 @@ long dfl_feature_ioctl_set_irq(struct platform_device *pdev,
if (IS_ERR(fds))
return PTR_ERR(fds);

- mutex_lock(&pdata->lock);
+ mutex_lock(&fdata->lock);
ret = dfl_fpga_set_irq_triggers(feature, hdr.start, hdr.count, fds);
- mutex_unlock(&pdata->lock);
+ mutex_unlock(&fdata->lock);

kfree(fds);
return ret;
diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index 7ea96788a969..612592f374e6 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -17,6 +17,7 @@
#include <linux/bitfield.h>
#include <linux/cdev.h>
#include <linux/delay.h>
+#include <linux/dfl.h>
#include <linux/eventfd.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
@@ -206,7 +207,7 @@
#define PORT_UINT_CAP_INT_NUM GENMASK_ULL(11, 0) /* Interrupts num */
#define PORT_UINT_CAP_FST_VECT GENMASK_ULL(23, 12) /* First Vector */

-#define dfl_feature_dev_data dfl_feature_platform_data
+struct dfl_feature_dev_data;

/**
* struct dfl_fpga_port_ops - port ops
@@ -221,15 +222,16 @@ struct dfl_fpga_port_ops {
const char *name;
struct module *owner;
struct list_head node;
- int (*get_id)(struct platform_device *pdev);
- int (*enable_set)(struct platform_device *pdev, bool enable);
+ int (*get_id)(struct dfl_feature_dev_data *fdata);
+ int (*enable_set)(struct dfl_feature_dev_data *fdata, bool enable);
};

void dfl_fpga_port_ops_add(struct dfl_fpga_port_ops *ops);
void dfl_fpga_port_ops_del(struct dfl_fpga_port_ops *ops);
-struct dfl_fpga_port_ops *dfl_fpga_port_ops_get(struct platform_device *pdev);
+struct dfl_fpga_port_ops *
+ dfl_fpga_port_ops_get(struct dfl_feature_dev_data *fdata);
void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops);
-int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id);
+int dfl_fpga_check_port_id(struct dfl_feature_dev_data *fdata, void *pport_id);

/**
* struct dfl_feature_id - dfl private feature id
@@ -302,26 +304,32 @@ struct dfl_feature {
#define FEATURE_DEV_ID_UNUSED (-1)

/**
- * struct dfl_feature_platform_data - platform data for feature devices
+ * struct dfl_feature_dev_data - dfl enumeration data for dfl feature dev.
*
- * @node: node to link feature devs to container device's port_dev_list.
- * @lock: mutex to protect platform data.
- * @cdev: cdev of feature dev.
- * @dev: ptr to platform device linked with this platform data.
+ * @node: node to link the data structure to container device's port_dev_list.
+ * @lock: mutex to protect feature dev data.
+ * @dev: ptr to the feature's platform device linked with this structure.
+ * @type: type of DFL FIU for the feature dev. See enum dfl_id_type.
+ * @pdev_id: platform device id for the feature dev.
+ * @pdev_name: platform device name for the feature dev.
* @dfl_cdev: ptr to container device.
- * @id: id used for this feature device.
+ * @id: id used for the feature device.
* @disable_count: count for port disable.
* @excl_open: set on feature device exclusive open.
* @open_count: count for feature device open.
* @num: number for sub features.
* @private: ptr to feature dev private data.
- * @features: sub features of this feature dev.
+ * @features: sub features for the feature dev.
+ * @resource_num: number of resources for the feature dev.
+ * @resources: resources for the feature dev.
*/
-struct dfl_feature_platform_data {
+struct dfl_feature_dev_data {
struct list_head node;
struct mutex lock;
- struct cdev cdev;
struct platform_device *dev;
+ enum dfl_id_type type;
+ int pdev_id;
+ const char *pdev_name;
struct dfl_fpga_cdev *dfl_cdev;
int id;
unsigned int disable_count;
@@ -329,7 +337,20 @@ struct dfl_feature_platform_data {
int open_count;
void *private;
int num;
- struct dfl_feature features[];
+ struct dfl_feature *features;
+ int resource_num;
+ struct resource *resources;
+};
+
+/**
+ * struct dfl_feature_platform_data - platform data for feature devices
+ *
+ * @cdev: cdev of feature dev.
+ * @fdata: dfl enumeration data for the dfl feature device.
+ */
+struct dfl_feature_platform_data {
+ struct cdev cdev;
+ struct dfl_feature_dev_data *fdata;
};

static inline
@@ -407,7 +428,7 @@ struct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)

pdata = container_of(inode->i_cdev, struct dfl_feature_platform_data,
cdev);
- return pdata->dev;
+ return pdata->fdata->dev;
}

#define dfl_fpga_dev_for_each_feature(fdata, feature) \
@@ -438,7 +459,13 @@ dfl_get_feature_ioaddr_by_id(struct dfl_feature_dev_data *fdata, u16 id)
return NULL;
}

-#define to_dfl_feature_dev_data dev_get_platdata
+static inline struct dfl_feature_dev_data *
+to_dfl_feature_dev_data(struct device *dev)
+{
+ struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
+
+ return pdata->fdata;
+}

static inline
struct device *dfl_fpga_fdata_to_parent(struct dfl_feature_dev_data *fdata)
@@ -525,26 +552,23 @@ struct dfl_fpga_cdev *
dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info);
void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev);

-/*
- * need to drop the device reference with put_device() after use port platform
- * device returned by __dfl_fpga_cdev_find_port and dfl_fpga_cdev_find_port
- * functions.
- */
-struct platform_device *
-__dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
- int (*match)(struct platform_device *, void *));
+struct dfl_feature_dev_data *
+__dfl_fpga_cdev_find_port_data(struct dfl_fpga_cdev *cdev, void *data,
+ int (*match)(struct dfl_feature_dev_data *,
+ void *));

-static inline struct platform_device *
-dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
- int (*match)(struct platform_device *, void *))
+static inline struct dfl_feature_dev_data *
+dfl_fpga_cdev_find_port_data(struct dfl_fpga_cdev *cdev, void *data,
+ int (*match)(struct dfl_feature_dev_data *,
+ void *))
{
- struct platform_device *pdev;
+ struct dfl_feature_dev_data *fdata;

mutex_lock(&cdev->lock);
- pdev = __dfl_fpga_cdev_find_port(cdev, data, match);
+ fdata = __dfl_fpga_cdev_find_port_data(cdev, data, match);
mutex_unlock(&cdev->lock);

- return pdev;
+ return fdata;
}

int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id);
--
2.44.0


2024-04-09 23:58:35

by Colberg, Peter

[permalink] [raw]
Subject: Re: [RFC PATCH v2 3/9] fpga: dfl: migrate AFU MMIO region management driver to dfl_feature_dev_data

On Tue, 2024-04-09 at 19:39 -0400, Peter Colberg wrote:
> This change separates out most of the symbol name changes required by this
> patch series for the file: drivers/fpga/dfl-afu-region.c. This is done to
> split a single monolithic change into multiple, smaller patches at the
> request of the maintainer.
>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> ---
> drivers/fpga/dfl-afu-region.c | 51 ++++++++++++++++++-----------------
> 1 file changed, 26 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-region.c b/drivers/fpga/dfl-afu-region.c
> index 2e7b41629406..b11a5b21e666 100644
> --- a/drivers/fpga/dfl-afu-region.c
> +++ b/drivers/fpga/dfl-afu-region.c
> @@ -12,11 +12,11 @@
>
> /**
> * afu_mmio_region_init - init function for afu mmio region support
> - * @pdata: afu platform device's pdata.
> + * @fdata: afu feature dev data
> */
> -void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
> +void afu_mmio_region_init(struct dfl_feature_dev_data *fdata)
> {
> - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
>
> INIT_LIST_HEAD(&afu->regions);
> }
> @@ -39,7 +39,7 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
> /**
> * afu_mmio_region_add - add a mmio region to given feature dev.
> *
> - * @pdata: afu platform device's pdata.
> + * @fdata: afu feature dev data
> * @region_index: region index.
> * @region_size: region size.
> * @phys: region's physical address of this region.
> @@ -47,14 +47,15 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
> *
> * Return: 0 on success, negative error code otherwise.
> */
> -int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
> +int afu_mmio_region_add(struct dfl_feature_dev_data *fdata,
> u32 region_index, u64 region_size, u64 phys, u32 flags)
> {
> + struct device *dev = &fdata->dev->dev;
> struct dfl_afu_mmio_region *region;
> struct dfl_afu *afu;
> int ret = 0;
>
> - region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
> + region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
> if (!region)
> return -ENOMEM;
>
> @@ -63,13 +64,13 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
> region->phys = phys;
> region->flags = flags;
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
>
> - afu = dfl_fpga_pdata_get_private(pdata);
> + afu = dfl_fpga_fdata_get_private(fdata);
>
> /* check if @index already exists */
> if (get_region_by_index(afu, region_index)) {
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
> ret = -EEXIST;
> goto exit;
> }
> @@ -80,37 +81,37 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
>
> afu->region_cur_offset += region_size;
> afu->num_regions++;
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return 0;
>
> exit:
> - devm_kfree(&pdata->dev->dev, region);
> + devm_kfree(dev, region);

An internal reviewer commented that calling devm_kfree() in almost all
cases shows a misunderstanding of object lifetime and may unveil bugs.
They suggested to either drop the explicit devm_kfree(), or move from
devm_*() to plain allocation.

I could not find specific documentation on the recommended use cases
for devm_kfree() to immediately free a resource on error, but the
description of devres groups advises that explicit freeing using
devres_release_group() is usually useful in midlayer drivers where
interface functions should not have side effects [1].

Which implementation would you prefer and why? Dropping devm_kfree(),
moving to plain allocation, or leaving everything as is?

[1] https://docs.kernel.org/driver-api/driver-model/devres.html#devres-group

Thanks,
Peter

> return ret;
> }
>
> /**
> * afu_mmio_region_destroy - destroy all mmio regions under given feature dev.
> - * @pdata: afu platform device's pdata.
> + * @fdata: afu feature dev data
> */
> -void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
> +void afu_mmio_region_destroy(struct dfl_feature_dev_data *fdata)
> {
> - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
> struct dfl_afu_mmio_region *tmp, *region;
>
> list_for_each_entry_safe(region, tmp, &afu->regions, node)
> - devm_kfree(&pdata->dev->dev, region);
> + devm_kfree(&fdata->dev->dev, region);
> }
>
> /**
> * afu_mmio_region_get_by_index - find an afu region by index.
> - * @pdata: afu platform device's pdata.
> + * @fdata: afu feature dev data
> * @region_index: region index.
> * @pregion: ptr to region for result.
> *
> * Return: 0 on success, negative error code otherwise.
> */
> -int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> +int afu_mmio_region_get_by_index(struct dfl_feature_dev_data *fdata,
> u32 region_index,
> struct dfl_afu_mmio_region *pregion)
> {
> @@ -118,8 +119,8 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> struct dfl_afu *afu;
> int ret = 0;
>
> - mutex_lock(&pdata->lock);
> - afu = dfl_fpga_pdata_get_private(pdata);
> + mutex_lock(&fdata->lock);
> + afu = dfl_fpga_fdata_get_private(fdata);
> region = get_region_by_index(afu, region_index);
> if (!region) {
> ret = -EINVAL;
> @@ -127,14 +128,14 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> }
> *pregion = *region;
> exit:
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
> return ret;
> }
>
> /**
> * afu_mmio_region_get_by_offset - find an afu mmio region by offset and size
> *
> - * @pdata: afu platform device's pdata.
> + * @fdata: afu feature dev data
> * @offset: region offset from start of the device fd.
> * @size: region size.
> * @pregion: ptr to region for result.
> @@ -144,7 +145,7 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> *
> * Return: 0 on success, negative error code otherwise.
> */
> -int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> +int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata,
> u64 offset, u64 size,
> struct dfl_afu_mmio_region *pregion)
> {
> @@ -152,8 +153,8 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> struct dfl_afu *afu;
> int ret = 0;
>
> - mutex_lock(&pdata->lock);
> - afu = dfl_fpga_pdata_get_private(pdata);
> + mutex_lock(&fdata->lock);
> + afu = dfl_fpga_fdata_get_private(fdata);
> for_each_region(region, afu)
> if (region->offset <= offset &&
> region->offset + region->size >= offset + size) {
> @@ -162,6 +163,6 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> }
> ret = -EINVAL;
> exit:
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
> return ret;
> }

2024-04-23 09:44:09

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 4/9] fpga: dfl: migrate FPGA Management Engine driver to dfl_feature_dev_data

On Tue, Apr 09, 2024 at 07:39:37PM -0400, Peter Colberg wrote:
> This change separates out most of the symbol name changes required by this
> patch series for the file: drivers/fpga/dfl-fme-main.c. This is done to
> split a single monolithic change into multiple, smaller patches at the
> request of the maintainer.
>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> - Change fme_hdr_ioctl_*() to receive dfl_feature_dev_data instead of
> dfl_feature_platform_data.
> - Remove unused local variable pdata in fme_dev_{init,destroy}().
> ---
> drivers/fpga/dfl-fme-main.c | 68 ++++++++++++++++++++-----------------
> 1 file changed, 36 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
> index 864924f68f5e..7f119b09b54e 100644
> --- a/drivers/fpga/dfl-fme-main.c
> +++ b/drivers/fpga/dfl-fme-main.c
> @@ -135,10 +135,10 @@ static const struct attribute_group fme_hdr_group = {
> .attrs = fme_hdr_attrs,
> };
>
> -static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
> +static long fme_hdr_ioctl_release_port(struct dfl_feature_dev_data *fdata,
> unsigned long arg)
> {
> - struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
> + struct dfl_fpga_cdev *cdev = fdata->dfl_cdev;
> int port_id;
>
> if (get_user(port_id, (int __user *)arg))
> @@ -147,10 +147,10 @@ static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
> return dfl_fpga_cdev_release_port(cdev, port_id);
> }
>
> -static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
> +static long fme_hdr_ioctl_assign_port(struct dfl_feature_dev_data *fdata,
> unsigned long arg)
> {
> - struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
> + struct dfl_fpga_cdev *cdev = fdata->dfl_cdev;
> int port_id;
>
> if (get_user(port_id, (int __user *)arg))
> @@ -163,13 +163,13 @@ static long fme_hdr_ioctl(struct platform_device *pdev,
> struct dfl_feature *feature,
> unsigned int cmd, unsigned long arg)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);

Maybe firstly make a patch to:

#define to_dfl_feature_platform_data dev_get_platdata

And s/to_dfl_feature_platform_data/dev_get_platdata

Then we could do replacements in this patch more friendly.

> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
>
> switch (cmd) {
> case DFL_FPGA_FME_PORT_RELEASE:
> - return fme_hdr_ioctl_release_port(pdata, arg);
> + return fme_hdr_ioctl_release_port(fdata, arg);
> case DFL_FPGA_FME_PORT_ASSIGN:
> - return fme_hdr_ioctl_assign_port(pdata, arg);
> + return fme_hdr_ioctl_assign_port(fdata, arg);
> }
>
> return -ENODEV;
> @@ -411,14 +411,14 @@ static int power_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
> u32 attr, int channel, long val)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev->parent);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> struct dfl_feature *feature = dev_get_drvdata(dev);
> int ret = 0;
> u64 v;
>
> val = clamp_val(val / MICRO, 0, PWR_THRESHOLD_MAX);
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
>
> switch (attr) {
> case hwmon_power_max:
> @@ -438,7 +438,7 @@ static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
> break;
> }
>
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return ret;
> }
> @@ -589,7 +589,7 @@ static struct dfl_feature_driver fme_feature_drvs[] = {
> },
> };
>
> -static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
> +static long fme_ioctl_check_extension(struct dfl_feature_dev_data *fdata,
> unsigned long arg)
> {
> /* No extension support for now */
> @@ -600,19 +600,21 @@ static int fme_open(struct inode *inode, struct file *filp)
> {
> struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
> struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);

Why not do the same replacement here?

> + struct dfl_feature_dev_data *fdata;
> int ret;
>
> if (WARN_ON(!pdata))
> return -ENODEV;
>
> - mutex_lock(&pdata->lock);
> - ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
> + fdata = pdata;
> + mutex_lock(&fdata->lock);
> + ret = dfl_feature_dev_use_begin(fdata, filp->f_flags & O_EXCL);
> if (!ret) {
> dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
> - dfl_feature_dev_use_count(pdata));
> + dfl_feature_dev_use_count(fdata));
> filp->private_data = pdata;
> }
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return ret;
> }
> @@ -620,19 +622,20 @@ static int fme_open(struct inode *inode, struct file *filp)
> static int fme_release(struct inode *inode, struct file *filp)
> {
> struct dfl_feature_platform_data *pdata = filp->private_data;
> - struct platform_device *pdev = pdata->dev;
> + struct dfl_feature_dev_data *fdata = pdata;

ditto.

> + struct platform_device *pdev = fdata->dev;
> struct dfl_feature *feature;
>
> dev_dbg(&pdev->dev, "Device File Release\n");
>
> - mutex_lock(&pdata->lock);
> - dfl_feature_dev_use_end(pdata);
> + mutex_lock(&fdata->lock);
> + dfl_feature_dev_use_end(fdata);
>
> - if (!dfl_feature_dev_use_count(pdata))
> - dfl_fpga_dev_for_each_feature(pdata, feature)
> + if (!dfl_feature_dev_use_count(fdata))
> + dfl_fpga_dev_for_each_feature(fdata, feature)
> dfl_fpga_set_irq_triggers(feature, 0,
> feature->nr_irqs, NULL);
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return 0;
> }
> @@ -640,7 +643,8 @@ static int fme_release(struct inode *inode, struct file *filp)
> static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> {
> struct dfl_feature_platform_data *pdata = filp->private_data;
> - struct platform_device *pdev = pdata->dev;
> + struct dfl_feature_dev_data *fdata = pdata;

ditto

> + struct platform_device *pdev = fdata->dev;
> struct dfl_feature *f;
> long ret;
>
> @@ -650,7 +654,7 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> case DFL_FPGA_GET_API_VERSION:
> return DFL_FPGA_API_VERSION;
> case DFL_FPGA_CHECK_EXTENSION:
> - return fme_ioctl_check_extension(pdata, arg);
> + return fme_ioctl_check_extension(fdata, arg);
> default:
> /*
> * Let sub-feature's ioctl function to handle the cmd.
> @@ -658,7 +662,7 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> * handled in this sub feature, and returns 0 or other
> * error code if cmd is handled.
> */
> - dfl_fpga_dev_for_each_feature(pdata, f) {
> + dfl_fpga_dev_for_each_feature(fdata, f) {
> if (f->ops && f->ops->ioctl) {
> ret = f->ops->ioctl(pdev, f, cmd, arg);
> if (ret != -ENODEV)
> @@ -672,27 +676,27 @@ static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>
> static int fme_dev_init(struct platform_device *pdev)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
> struct dfl_fme *fme;
>
> fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
> if (!fme)
> return -ENOMEM;
>
> - mutex_lock(&pdata->lock);
> - dfl_fpga_pdata_set_private(pdata, fme);
> - mutex_unlock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> + dfl_fpga_fdata_set_private(fdata, fme);
> + mutex_unlock(&fdata->lock);
>
> return 0;
> }
>
> static void fme_dev_destroy(struct platform_device *pdev)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
>
> - mutex_lock(&pdata->lock);
> - dfl_fpga_pdata_set_private(pdata, NULL);
> - mutex_unlock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> + dfl_fpga_fdata_set_private(fdata, NULL);
> + mutex_unlock(&fdata->lock);
> }
>
> static const struct file_operations fme_fops = {
> --
> 2.44.0
>
>

2024-04-23 10:08:27

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 2/9] fpga: dfl: migrate AFU DMA region management driver to dfl_feature_dev_data

On Tue, Apr 09, 2024 at 07:39:35PM -0400, Peter Colberg wrote:
> This change separates out most of the symbol name changes required by this
> patch series for the file: drivers/fpga/dfl-afu-dma-region.c.

> This is done
> to split a single monolithic change into multiple, smaller patches at the
> request of the maintainer.

This sentence provides no useful info.

>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> - Reorder local variables in afu_dma_unpin_pages() to reverse Christmas
> tree order.
> ---
> drivers/fpga/dfl-afu-dma-region.c | 119 +++++++++++++++---------------
> 1 file changed, 61 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
> index 02b60fde0430..fb45e51b12af 100644
> --- a/drivers/fpga/dfl-afu-dma-region.c
> +++ b/drivers/fpga/dfl-afu-dma-region.c
> @@ -16,26 +16,26 @@
>
> #include "dfl-afu.h"
>
> -void afu_dma_region_init(struct dfl_feature_platform_data *pdata)
> +void afu_dma_region_init(struct dfl_feature_dev_data *fdata)
> {
> - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
>
> afu->dma_regions = RB_ROOT;
> }
>
> /**
> * afu_dma_pin_pages - pin pages of given dma memory region
> - * @pdata: feature device platform data
> + * @fdata: feature dev data
> * @region: dma memory region to be pinned
> *
> * Pin all the pages of given dfl_afu_dma_region.
> * Return 0 for success or negative error code.
> */
> -static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
> +static int afu_dma_pin_pages(struct dfl_feature_dev_data *fdata,
> struct dfl_afu_dma_region *region)
> {
> int npages = region->length >> PAGE_SHIFT;
> - struct device *dev = &pdata->dev->dev;
> + struct device *dev = &fdata->dev->dev;
> int ret, pinned;
>
> ret = account_locked_vm(current->mm, npages, true);
> @@ -73,17 +73,17 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
>
> /**
> * afu_dma_unpin_pages - unpin pages of given dma memory region
> - * @pdata: feature device platform data
> + * @fdata: feature dev data
> * @region: dma memory region to be unpinned
> *
> * Unpin all the pages of given dfl_afu_dma_region.
> * Return 0 for success or negative error code.
> */
> -static void afu_dma_unpin_pages(struct dfl_feature_platform_data *pdata,
> +static void afu_dma_unpin_pages(struct dfl_feature_dev_data *fdata,
> struct dfl_afu_dma_region *region)
> {
> long npages = region->length >> PAGE_SHIFT;
> - struct device *dev = &pdata->dev->dev;
> + struct device *dev = &fdata->dev->dev;
>
> unpin_user_pages(region->pages, npages);
> kfree(region->pages);
> @@ -133,20 +133,21 @@ static bool dma_region_check_iova(struct dfl_afu_dma_region *region,
>
> /**
> * afu_dma_region_add - add given dma region to rbtree
> - * @pdata: feature device platform data
> + * @fdata: feature dev data
> * @region: dma region to be added
> *
> * Return 0 for success, -EEXIST if dma region has already been added.
> *
> - * Needs to be called with pdata->lock heold.
> + * Needs to be called with fdata->lock held.
> */
> -static int afu_dma_region_add(struct dfl_feature_platform_data *pdata,
> +static int afu_dma_region_add(struct dfl_feature_dev_data *fdata,
> struct dfl_afu_dma_region *region)
> {
> - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
> + struct device *dev = &fdata->dev->dev;

Don't introduce any other unnecessary changes in the big
symbol replacement patch. People could read over all the same
replacements quickly, even if they are massive. But if there are
some other changes in between...

> struct rb_node **new, *parent = NULL;
>
> - dev_dbg(&pdata->dev->dev, "add region (iova = %llx)\n",
> + dev_dbg(dev, "add region (iova = %llx)\n",
> (unsigned long long)region->iova);

2024-04-23 12:34:14

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

On Tue, Apr 09, 2024 at 07:39:33PM -0400, Peter Colberg wrote:
> DFL ports are registered as platform devices in PF mode. The port device
> should be removed from the host when the user wants to configure the
> port as a VF and pass through to a virtual machine. The FME device
> ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.
>
> In the previous implementation, the port platform device is not completely
> destroyed on port release: it is removed from the system by
> platform_device_del(), but the platform device instance is retained.
> When the port assign ioctl is called, the platform device is added back by
> platform_device_add(), which conflicts with this comment of device_add():
> "Do not call this routine more than once for any device structure", and
> will cause a kernel warning at runtime.
>
> This patch tries to completely unregister the port platform device on
> release and registers a new one on assign. But the main work is to remove
> the dependency on struct dfl_feature_platform_data for many internal DFL
> APIs. This structure holds many DFL enumeration infos for feature devices.
> Many DFL APIs are expected to work with these info even when the port
> platform device is unregistered. But with the change the platform_data will
> be freed in this case. So this patch introduces a new structure
> dfl_feature_dev_data for these APIs, which acts similarly to the previous
> dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
> pointer to dfl_feature_dev_data to make the feature device driver work.
>
> The single monolithic v1 patch is split into multiple, smaller patches
> at the request of the maintainer. The first patch adds temporary macros
> that alias dfl_feature_dev_data ("fdata") to dfl_feature_platform_data
> ("pdata") and associated functions from the "fdata" to the corresponding
> "pdata" variants. Subsequent patches separate out most of the symbol
> name changes required by this patch series, one patch per file. The last

One patch per file is not a requirement, simple replacement across
multiple files won't cause trouble for reviewers. The important thing is
that don't bury the key changes in these symbol replacement so that
people can't get the point.

2024-04-23 14:36:36

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 6/9] fpga: dfl: migrate Accelerated Function Unit driver to dfl_feature_dev_data

On Tue, Apr 09, 2024 at 07:39:39PM -0400, Peter Colberg wrote:
> This change separates out most of the symbol name changes required by this
> patch series for the file: drivers/fpga/dfl-afu-main.c. This is done to
> split a single monolithic change into multiple, smaller patches at the
> request of the maintainer.
>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> - Change afu_ioctl_*() to receive dfl_feature_dev_data instead of
> dfl_feature_platform_data.
> - Replace local variable pdata with fdata in afu_mmap().
> - Remove unused local variable pdata in afu_dev_{init,destroy}().
> ---
> drivers/fpga/dfl-afu-main.c | 110 ++++++++++++++++++------------------
> 1 file changed, 56 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> index 6b97c073849e..61868cdd5b0b 100644
> --- a/drivers/fpga/dfl-afu-main.c
> +++ b/drivers/fpga/dfl-afu-main.c
> @@ -504,9 +504,11 @@ static const struct attribute_group port_afu_group = {
> static int port_afu_init(struct platform_device *pdev,
> struct dfl_feature *feature)
> {
> + struct dfl_feature_dev_data *fdata =
> + to_dfl_feature_dev_data(&pdev->dev);
> struct resource *res = &pdev->resource[feature->resource_index];
>
> - return afu_mmio_region_add(dev_get_platdata(&pdev->dev),
> + return afu_mmio_region_add(fdata,

Again, please keep the change simple for massive replacement. If you
want other adjustments, do it in another patch.

Thanks,
Yilun

2024-04-23 15:22:50

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 8/9] fpga: dfl: migrate dfl_get_feature_by_id() to dfl_feature_dev_data

On Tue, Apr 09, 2024 at 07:39:41PM -0400, Peter Colberg wrote:
> This change separates out most of the symbol name changes required by this
> patch series for the function: dfl_get_feature_by_id(). This is done to
> split a single monolithic change into multiple, smaller patches at the
> request of the maintainer.
>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> ---
> drivers/fpga/dfl-afu-error.c | 59 +++++++------
> drivers/fpga/dfl-afu-main.c | 166 ++++++++++++++++++-----------------
> drivers/fpga/dfl-afu.h | 26 +++---
> drivers/fpga/dfl-fme-error.c | 98 +++++++++++----------
> drivers/fpga/dfl-fme-main.c | 18 ++--
> drivers/fpga/dfl-fme-pr.c | 6 +-
> drivers/fpga/dfl.c | 3 +-
> drivers/fpga/dfl.h | 13 ++-
> 8 files changed, 203 insertions(+), 186 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
> index ab7be6217368..0f392d1f6d45 100644
> --- a/drivers/fpga/dfl-afu-error.c
> +++ b/drivers/fpga/dfl-afu-error.c
> @@ -28,37 +28,36 @@
> #define ERROR_MASK GENMASK_ULL(63, 0)
>
> /* mask or unmask port errors by the error mask register. */
> -static void __afu_port_err_mask(struct device *dev, bool mask)
> +static void __afu_port_err_mask(struct dfl_feature_dev_data *fdata, bool mask)

Maybe first replace all "struct device *dev" arguments with "struct
dfl_feature_platform data *pdata", then you could do simple
pdata->fdata replacement the same as other patches.

> {
> void __iomem *base;
>
> - base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> + base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
>
> writeq(mask ? ERROR_MASK : 0, base + PORT_ERROR_MASK);
> }
>
> static void afu_port_err_mask(struct device *dev, bool mask)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
>
> - mutex_lock(&pdata->lock);
> - __afu_port_err_mask(dev, mask);
> - mutex_unlock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> + __afu_port_err_mask(fdata, mask);
> + mutex_unlock(&fdata->lock);
> }
>
> /* clear port errors. */
> static int afu_port_err_clear(struct device *dev, u64 err)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
> - struct platform_device *pdev = to_platform_device(dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> void __iomem *base_err, *base_hdr;
> int enable_ret = 0, ret = -EBUSY;
> u64 v;
>
> - base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> - base_hdr = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
> + base_err = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
> + base_hdr = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
>
> /*
> * clear Port Errors
> @@ -80,12 +79,12 @@ static int afu_port_err_clear(struct device *dev, u64 err)
> }
>
> /* Halt Port by keeping Port in reset */
> - ret = __afu_port_disable(pdev);
> + ret = __afu_port_disable(fdata);
> if (ret)
> goto done;
>
> /* Mask all errors */
> - __afu_port_err_mask(dev, true);
> + __afu_port_err_mask(fdata, true);
>
> /* Clear errors if err input matches with current port errors.*/
> v = readq(base_err + PORT_ERROR);
> @@ -102,28 +101,28 @@ static int afu_port_err_clear(struct device *dev, u64 err)
> }
>
> /* Clear mask */
> - __afu_port_err_mask(dev, false);
> + __afu_port_err_mask(fdata, false);
>
> /* Enable the Port by clearing the reset */
> - enable_ret = __afu_port_enable(pdev);
> + enable_ret = __afu_port_enable(fdata);
>
> done:
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
> return enable_ret ? enable_ret : ret;
> }
>
> static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> void __iomem *base;
> u64 error;
>
> - base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> + base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> error = readq(base + PORT_ERROR);
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return sprintf(buf, "0x%llx\n", (unsigned long long)error);
> }
> @@ -146,15 +145,15 @@ static DEVICE_ATTR_RW(errors);
> static ssize_t first_error_show(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> void __iomem *base;
> u64 error;
>
> - base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> + base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> error = readq(base + PORT_FIRST_ERROR);
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return sprintf(buf, "0x%llx\n", (unsigned long long)error);
> }
> @@ -164,16 +163,16 @@ static ssize_t first_malformed_req_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> void __iomem *base;
> u64 req0, req1;
>
> - base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> + base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
>
> - mutex_lock(&pdata->lock);
> + mutex_lock(&fdata->lock);
> req0 = readq(base + PORT_MALFORMED_REQ0);
> req1 = readq(base + PORT_MALFORMED_REQ1);
> - mutex_unlock(&pdata->lock);
> + mutex_unlock(&fdata->lock);
>
> return sprintf(buf, "0x%016llx%016llx\n",
> (unsigned long long)req1, (unsigned long long)req0);
> @@ -191,12 +190,14 @@ static umode_t port_err_attrs_visible(struct kobject *kobj,
> struct attribute *attr, int n)
> {
> struct device *dev = kobj_to_dev(kobj);
> + struct dfl_feature_dev_data *fdata;
>
> + fdata = to_dfl_feature_dev_data(dev);
> /*
> * sysfs entries are visible only if related private feature is
> * enumerated.
> */
> - if (!dfl_get_feature_by_id(dev, PORT_FEATURE_ID_ERROR))
> + if (!dfl_get_feature_by_id(fdata, PORT_FEATURE_ID_ERROR))
> return 0;
>
> return attr->mode;
> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> index 61868cdd5b0b..42928cc7e42b 100644
> --- a/drivers/fpga/dfl-afu-main.c
> +++ b/drivers/fpga/dfl-afu-main.c
> @@ -26,7 +26,7 @@
>
> /**
> * __afu_port_enable - enable a port by clear reset
> - * @pdev: port platform device.
> + * @fdata: port feature dev data.
> *
> * Enable Port by clear the port soft reset bit, which is set by default.
> * The AFU is unable to respond to any MMIO access while in reset.
> @@ -35,18 +35,17 @@
> *
> * The caller needs to hold lock for protection.
> */
> -int __afu_port_enable(struct platform_device *pdev)
> +int __afu_port_enable(struct dfl_feature_dev_data *fdata)

Same suggestion. Replace "struct platform_device *pdev" with "struct
dfl_feature_platform_data *pdata" first. Then do massive pdata->fdata
replacement.

Thanks,
Yilun

2024-04-23 15:41:47

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 9/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

On Tue, Apr 09, 2024 at 07:39:42PM -0400, Peter Colberg wrote:
> From: Xu Yilun <[email protected]>
>
> DFL ports are registered as platform devices in PF mode. The port device
> should be removed from the host when the user wants to configure the
> port as a VF and pass through to a virtual machine. The FME device
> ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.
>
> In the previous implementation, the port platform device is not completely
> destroyed on port release: it is removed from the system by
> platform_device_del(), but the platform device instance is retained.
> When the port assign ioctl is called, the platform device is added back by
> platform_device_add(), which conflicts with this comment of device_add():
> "Do not call this routine more than once for any device structure", and
> will cause a kernel warning at runtime.
>
> This patch tries to completely unregister the port platform device on
> release and registers a new one on assign. But the main work is to remove
> the dependency on struct dfl_feature_platform_data for many internal DFL
> APIs. This structure holds many DFL enumeration infos for feature devices.
> Many DFL APIs are expected to work with these info even when the port
> platform device is unregistered. But with the change the platform_data will
> be freed in this case. So this patch introduces a new structure
> dfl_feature_dev_data for these APIs, which acts similarly to the previous
> dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
> pointer to dfl_feature_dev_data to make the feature device driver work.
>
> Signed-off-by: Xu Yilun <[email protected]>
> Signed-off-by: Russ Weight <[email protected]>
> Signed-off-by: Peter Colberg <[email protected]>
> ---
> v2:
> - Split monolithic patch into series at request of maintainer
> - Substitute binfo->type for removed function feature_dev_id_type() in
> parse_feature_irqs().
> - Return ERR_PTR(-ENOMEM) on !feature->params in
> binfo_create_feature_dev_data().
> - Reorder cdev as first member of struct dfl_feature_platform_data
> such that container_of() to obtain pdata evaluates to a no-op.
> - Align kernel-doc function name for __dfl_fpga_cdev_find_port_data().
> ---
> drivers/fpga/dfl-afu-main.c | 9 +-
> drivers/fpga/dfl-fme-br.c | 24 +-
> drivers/fpga/dfl-fme-main.c | 6 +-
> drivers/fpga/dfl.c | 430 +++++++++++++++++-------------------
> drivers/fpga/dfl.h | 86 +++++---
> 5 files changed, 281 insertions(+), 274 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> index 42928cc7e42b..ead03b7aea70 100644
> --- a/drivers/fpga/dfl-afu-main.c
> +++ b/drivers/fpga/dfl-afu-main.c
> @@ -143,9 +143,8 @@ static int port_reset(struct platform_device *pdev)
> return ret;
> }
>
> -static int port_get_id(struct platform_device *pdev)
> +static int port_get_id(struct dfl_feature_dev_data *fdata)
> {
> - struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
> void __iomem *base;
>
> base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);
> @@ -156,7 +155,8 @@ static int port_get_id(struct platform_device *pdev)
> static ssize_t
> id_show(struct device *dev, struct device_attribute *attr, char *buf)
> {
> - int id = port_get_id(to_platform_device(dev));
> + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> + int id = port_get_id(fdata);

My quick idea is we go with these steps:
1. refactor struct dfl_feature_platform_data then replace all dev/pdev
arguments with pdata when necessary.
2. factor out fdata from pdata, add fdata helpers.
3. massive pdata->fdata replacement.
4. delete all unused pdata helpers.

Please check if it is possible.

Thanks,
Yilun

2024-04-23 17:08:58

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 3/9] fpga: dfl: migrate AFU MMIO region management driver to dfl_feature_dev_data

On Tue, Apr 09, 2024 at 11:56:19PM +0000, Colberg, Peter wrote:
> On Tue, 2024-04-09 at 19:39 -0400, Peter Colberg wrote:
> > This change separates out most of the symbol name changes required by this
> > patch series for the file: drivers/fpga/dfl-afu-region.c. This is done to
> > split a single monolithic change into multiple, smaller patches at the
> > request of the maintainer.
> >
> > Signed-off-by: Peter Colberg <[email protected]>
> > ---
> > v2:
> > - Split monolithic patch into series at request of maintainer
> > ---
> > drivers/fpga/dfl-afu-region.c | 51 ++++++++++++++++++-----------------
> > 1 file changed, 26 insertions(+), 25 deletions(-)
> >
> > diff --git a/drivers/fpga/dfl-afu-region.c b/drivers/fpga/dfl-afu-region.c
> > index 2e7b41629406..b11a5b21e666 100644
> > --- a/drivers/fpga/dfl-afu-region.c
> > +++ b/drivers/fpga/dfl-afu-region.c
> > @@ -12,11 +12,11 @@
> >
> > /**
> > * afu_mmio_region_init - init function for afu mmio region support
> > - * @pdata: afu platform device's pdata.
> > + * @fdata: afu feature dev data
> > */
> > -void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
> > +void afu_mmio_region_init(struct dfl_feature_dev_data *fdata)
> > {
> > - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> > + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
> >
> > INIT_LIST_HEAD(&afu->regions);
> > }
> > @@ -39,7 +39,7 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
> > /**
> > * afu_mmio_region_add - add a mmio region to given feature dev.
> > *
> > - * @pdata: afu platform device's pdata.
> > + * @fdata: afu feature dev data
> > * @region_index: region index.
> > * @region_size: region size.
> > * @phys: region's physical address of this region.
> > @@ -47,14 +47,15 @@ static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
> > *
> > * Return: 0 on success, negative error code otherwise.
> > */
> > -int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
> > +int afu_mmio_region_add(struct dfl_feature_dev_data *fdata,
> > u32 region_index, u64 region_size, u64 phys, u32 flags)
> > {
> > + struct device *dev = &fdata->dev->dev;
> > struct dfl_afu_mmio_region *region;
> > struct dfl_afu *afu;
> > int ret = 0;
> >
> > - region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
> > + region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
> > if (!region)
> > return -ENOMEM;
> >
> > @@ -63,13 +64,13 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
> > region->phys = phys;
> > region->flags = flags;
> >
> > - mutex_lock(&pdata->lock);
> > + mutex_lock(&fdata->lock);
> >
> > - afu = dfl_fpga_pdata_get_private(pdata);
> > + afu = dfl_fpga_fdata_get_private(fdata);
> >
> > /* check if @index already exists */
> > if (get_region_by_index(afu, region_index)) {
> > - mutex_unlock(&pdata->lock);
> > + mutex_unlock(&fdata->lock);
> > ret = -EEXIST;
> > goto exit;
> > }
> > @@ -80,37 +81,37 @@ int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
> >
> > afu->region_cur_offset += region_size;
> > afu->num_regions++;
> > - mutex_unlock(&pdata->lock);
> > + mutex_unlock(&fdata->lock);
> >
> > return 0;
> >
> > exit:
> > - devm_kfree(&pdata->dev->dev, region);
> > + devm_kfree(dev, region);
>
> An internal reviewer commented that calling devm_kfree() in almost all
> cases shows a misunderstanding of object lifetime and may unveil bugs.
> They suggested to either drop the explicit devm_kfree(), or move from
> devm_*() to plain allocation.
>
> I could not find specific documentation on the recommended use cases
> for devm_kfree() to immediately free a resource on error, but the
> description of devres groups advises that explicit freeing using
> devres_release_group() is usually useful in midlayer drivers where
> interface functions should not have side effects [1].
>
> Which implementation would you prefer and why? Dropping devm_kfree(),
> moving to plain allocation, or leaving everything as is?

Using devm_*() usually means the lifecycle of the allocated object
should be the same as the device. Otherwise use the plain allocation.
Please check which case fits for you.

Thanks,
Yilun

>
> [1] https://docs.kernel.org/driver-api/driver-model/devres.html#devres-group
>
> Thanks,
> Peter
>
> > return ret;
> > }
> >
> > /**
> > * afu_mmio_region_destroy - destroy all mmio regions under given feature dev.
> > - * @pdata: afu platform device's pdata.
> > + * @fdata: afu feature dev data
> > */
> > -void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
> > +void afu_mmio_region_destroy(struct dfl_feature_dev_data *fdata)
> > {
> > - struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
> > + struct dfl_afu *afu = dfl_fpga_fdata_get_private(fdata);
> > struct dfl_afu_mmio_region *tmp, *region;
> >
> > list_for_each_entry_safe(region, tmp, &afu->regions, node)
> > - devm_kfree(&pdata->dev->dev, region);
> > + devm_kfree(&fdata->dev->dev, region);
> > }
> >
> > /**
> > * afu_mmio_region_get_by_index - find an afu region by index.
> > - * @pdata: afu platform device's pdata.
> > + * @fdata: afu feature dev data
> > * @region_index: region index.
> > * @pregion: ptr to region for result.
> > *
> > * Return: 0 on success, negative error code otherwise.
> > */
> > -int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> > +int afu_mmio_region_get_by_index(struct dfl_feature_dev_data *fdata,
> > u32 region_index,
> > struct dfl_afu_mmio_region *pregion)
> > {
> > @@ -118,8 +119,8 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> > struct dfl_afu *afu;
> > int ret = 0;
> >
> > - mutex_lock(&pdata->lock);
> > - afu = dfl_fpga_pdata_get_private(pdata);
> > + mutex_lock(&fdata->lock);
> > + afu = dfl_fpga_fdata_get_private(fdata);
> > region = get_region_by_index(afu, region_index);
> > if (!region) {
> > ret = -EINVAL;
> > @@ -127,14 +128,14 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> > }
> > *pregion = *region;
> > exit:
> > - mutex_unlock(&pdata->lock);
> > + mutex_unlock(&fdata->lock);
> > return ret;
> > }
> >
> > /**
> > * afu_mmio_region_get_by_offset - find an afu mmio region by offset and size
> > *
> > - * @pdata: afu platform device's pdata.
> > + * @fdata: afu feature dev data
> > * @offset: region offset from start of the device fd.
> > * @size: region size.
> > * @pregion: ptr to region for result.
> > @@ -144,7 +145,7 @@ int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
> > *
> > * Return: 0 on success, negative error code otherwise.
> > */
> > -int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> > +int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata,
> > u64 offset, u64 size,
> > struct dfl_afu_mmio_region *pregion)
> > {
> > @@ -152,8 +153,8 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> > struct dfl_afu *afu;
> > int ret = 0;
> >
> > - mutex_lock(&pdata->lock);
> > - afu = dfl_fpga_pdata_get_private(pdata);
> > + mutex_lock(&fdata->lock);
> > + afu = dfl_fpga_fdata_get_private(fdata);
> > for_each_region(region, afu)
> > if (region->offset <= offset &&
> > region->offset + region->size >= offset + size) {
> > @@ -162,6 +163,6 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
> > }
> > ret = -EINVAL;
> > exit:
> > - mutex_unlock(&pdata->lock);
> > + mutex_unlock(&fdata->lock);
> > return ret;
> > }
>

2024-06-12 22:16:49

by Colberg, Peter

[permalink] [raw]
Subject: Re: [RFC PATCH v2 9/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

On Tue, 2024-04-23 at 23:36 +0800, Xu Yilun wrote:
> On Tue, Apr 09, 2024 at 07:39:42PM -0400, Peter Colberg wrote:
> > From: Xu Yilun <[email protected]>
> >
> > DFL ports are registered as platform devices in PF mode. The port device
> > should be removed from the host when the user wants to configure the
> > port as a VF and pass through to a virtual machine. The FME device
> > ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.
> >
> > In the previous implementation, the port platform device is not completely
> > destroyed on port release: it is removed from the system by
> > platform_device_del(), but the platform device instance is retained.
> > When the port assign ioctl is called, the platform device is added back by
> > platform_device_add(), which conflicts with this comment of device_add():
> > "Do not call this routine more than once for any device structure", and
> > will cause a kernel warning at runtime.
> >
> > This patch tries to completely unregister the port platform device on
> > release and registers a new one on assign. But the main work is to remove
> > the dependency on struct dfl_feature_platform_data for many internal DFL
> > APIs. This structure holds many DFL enumeration infos for feature devices.
> > Many DFL APIs are expected to work with these info even when the port
> > platform device is unregistered. But with the change the platform_data will
> > be freed in this case. So this patch introduces a new structure
> > dfl_feature_dev_data for these APIs, which acts similarly to the previous
> > dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
> > pointer to dfl_feature_dev_data to make the feature device driver work.
> >
> > Signed-off-by: Xu Yilun <[email protected]>
> > Signed-off-by: Russ Weight <[email protected]>
> > Signed-off-by: Peter Colberg <[email protected]>
> > ---
> > v2:
> > - Split monolithic patch into series at request of maintainer
> > - Substitute binfo->type for removed function feature_dev_id_type() in
> > parse_feature_irqs().
> > - Return ERR_PTR(-ENOMEM) on !feature->params in
> > binfo_create_feature_dev_data().
> > - Reorder cdev as first member of struct dfl_feature_platform_data
> > such that container_of() to obtain pdata evaluates to a no-op.
> > - Align kernel-doc function name for __dfl_fpga_cdev_find_port_data().
> > ---
> > drivers/fpga/dfl-afu-main.c | 9 +-
> > drivers/fpga/dfl-fme-br.c | 24 +-
> > drivers/fpga/dfl-fme-main.c | 6 +-
> > drivers/fpga/dfl.c | 430 +++++++++++++++++-------------------
> > drivers/fpga/dfl.h | 86 +++++---
> > 5 files changed, 281 insertions(+), 274 deletions(-)
> >
> > diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> > index 42928cc7e42b..ead03b7aea70 100644
> > --- a/drivers/fpga/dfl-afu-main.c
> > +++ b/drivers/fpga/dfl-afu-main.c
> > @@ -143,9 +143,8 @@ static int port_reset(struct platform_device *pdev)
> > return ret;
> > }
> >
> > -static int port_get_id(struct platform_device *pdev)
> > +static int port_get_id(struct dfl_feature_dev_data *fdata)
> > {
> > - struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
> > void __iomem *base;
> >
> > base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);
> > @@ -156,7 +155,8 @@ static int port_get_id(struct platform_device *pdev)
> > static ssize_t
> > id_show(struct device *dev, struct device_attribute *attr, char *buf)
> > {
> > - int id = port_get_id(to_platform_device(dev));
> > + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> > + int id = port_get_id(fdata);
>

Thank you for the comprehensive review.

> My quick idea is we go with these steps:
> 1. refactor struct dfl_feature_platform_data then replace all dev/pdev
> arguments with pdata when necessary.

Could you outline how far the refactoring should go? The main changes
are introduced with the destruction of the platform device on port
release. If the refactoring retains the platform device but adds all
the new members to pdata, I find that this patch would introduce non-
trivial intermediate code that is then deleted in a subsequent patch.

> 2. factor out fdata from pdata, add fdata helpers.
> 3. massive pdata->fdata replacement.
> 4. delete all unused pdata helpers.

The (roughly) reverse order seems to produce the smallest patch set:

1. Replace function argument `struct device *dev` with `struct
dfl_feature_platform_data *pdata` as needed.
2. #define dfl_feature_dev_data dfl_feature_platform_data and massive
pdata -> fdata replacement.
3. Remove #define dfl_feature_dev_data, factor out dfl_feature_dev_data
from dfl_feature_platform_data, and destroy platform device on release.

Thanks,
Peter

2024-06-14 02:52:36

by Xu Yilun

[permalink] [raw]
Subject: Re: [RFC PATCH v2 9/9] fpga: dfl: fix kernel warning on port release/assign for SRIOV

On Wed, Jun 12, 2024 at 10:16:29PM +0000, Colberg, Peter wrote:
> On Tue, 2024-04-23 at 23:36 +0800, Xu Yilun wrote:
> > On Tue, Apr 09, 2024 at 07:39:42PM -0400, Peter Colberg wrote:
> > > From: Xu Yilun <[email protected]>
> > >
> > > DFL ports are registered as platform devices in PF mode. The port device
> > > should be removed from the host when the user wants to configure the
> > > port as a VF and pass through to a virtual machine. The FME device
> > > ioctls DFL_FPGA_FME_PORT_RELEASE/ASSIGN are designed for this purpose.
> > >
> > > In the previous implementation, the port platform device is not completely
> > > destroyed on port release: it is removed from the system by
> > > platform_device_del(), but the platform device instance is retained.
> > > When the port assign ioctl is called, the platform device is added back by
> > > platform_device_add(), which conflicts with this comment of device_add():
> > > "Do not call this routine more than once for any device structure", and
> > > will cause a kernel warning at runtime.
> > >
> > > This patch tries to completely unregister the port platform device on
> > > release and registers a new one on assign. But the main work is to remove
> > > the dependency on struct dfl_feature_platform_data for many internal DFL
> > > APIs. This structure holds many DFL enumeration infos for feature devices.
> > > Many DFL APIs are expected to work with these info even when the port
> > > platform device is unregistered. But with the change the platform_data will
> > > be freed in this case. So this patch introduces a new structure
> > > dfl_feature_dev_data for these APIs, which acts similarly to the previous
> > > dfl_feature_platform_data. The dfl_feature_platform_data then only needs a
> > > pointer to dfl_feature_dev_data to make the feature device driver work.
> > >
> > > Signed-off-by: Xu Yilun <[email protected]>
> > > Signed-off-by: Russ Weight <[email protected]>
> > > Signed-off-by: Peter Colberg <[email protected]>
> > > ---
> > > v2:
> > > - Split monolithic patch into series at request of maintainer
> > > - Substitute binfo->type for removed function feature_dev_id_type() in
> > > parse_feature_irqs().
> > > - Return ERR_PTR(-ENOMEM) on !feature->params in
> > > binfo_create_feature_dev_data().
> > > - Reorder cdev as first member of struct dfl_feature_platform_data
> > > such that container_of() to obtain pdata evaluates to a no-op.
> > > - Align kernel-doc function name for __dfl_fpga_cdev_find_port_data().
> > > ---
> > > drivers/fpga/dfl-afu-main.c | 9 +-
> > > drivers/fpga/dfl-fme-br.c | 24 +-
> > > drivers/fpga/dfl-fme-main.c | 6 +-
> > > drivers/fpga/dfl.c | 430 +++++++++++++++++-------------------
> > > drivers/fpga/dfl.h | 86 +++++---
> > > 5 files changed, 281 insertions(+), 274 deletions(-)
> > >
> > > diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> > > index 42928cc7e42b..ead03b7aea70 100644
> > > --- a/drivers/fpga/dfl-afu-main.c
> > > +++ b/drivers/fpga/dfl-afu-main.c
> > > @@ -143,9 +143,8 @@ static int port_reset(struct platform_device *pdev)
> > > return ret;
> > > }
> > >
> > > -static int port_get_id(struct platform_device *pdev)
> > > +static int port_get_id(struct dfl_feature_dev_data *fdata)
> > > {
> > > - struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(&pdev->dev);
> > > void __iomem *base;
> > >
> > > base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);
> > > @@ -156,7 +155,8 @@ static int port_get_id(struct platform_device *pdev)
> > > static ssize_t
> > > id_show(struct device *dev, struct device_attribute *attr, char *buf)
> > > {
> > > - int id = port_get_id(to_platform_device(dev));
> > > + struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
> > > + int id = port_get_id(fdata);
> >
>
> Thank you for the comprehensive review.
>
> > My quick idea is we go with these steps:
> > 1. refactor struct dfl_feature_platform_data then replace all dev/pdev
> > arguments with pdata when necessary.
>
> Could you outline how far the refactoring should go? The main changes
> are introduced with the destruction of the platform device on port

Yes, exactly. And the goal is to make the change in a standalone patch
so that everyone can find it, rather than bury in other massive
replacements.

> release. If the refactoring retains the platform device but adds all
> the new members to pdata, I find that this patch would introduce non-
> trivial intermediate code that is then deleted in a subsequent patch.

That would not be a problem, as long as they clearly get explained, and
in one patch series. Sometimes we need intermediate code to ensure a
patch for one change, which makes people easy to read.

>
> > 2. factor out fdata from pdata, add fdata helpers.
> > 3. massive pdata->fdata replacement.
> > 4. delete all unused pdata helpers.
>
> The (roughly) reverse order seems to produce the smallest patch set:

I don't think 'smallest' is the major concern, but it's fine if you
firstly addressed other concerns. I cannot actually tell if it is
better until the code is seen. But to emphasize on, the core change is
splited out, the massive replacement patches are just replacements so
they can be easily overviewed and skipped.

Thanks,
Yilun

>
> 1. Replace function argument `struct device *dev` with `struct
> dfl_feature_platform_data *pdata` as needed.
> 2. #define dfl_feature_dev_data dfl_feature_platform_data and massive
> pdata -> fdata replacement.
> 3. Remove #define dfl_feature_dev_data, factor out dfl_feature_dev_data
> from dfl_feature_platform_data, and destroy platform device on release.
>
> Thanks,
> Peter