Re: [PATCH v7 1/7] fpga: dfl: parse interrupt info for feature devices on enumeration

2020-06-28 Thread Moritz Fischer
On Tue, Jun 16, 2020 at 12:08:42PM +0800, Xu Yilun wrote:
> DFL based FPGA devices could support interrupts for different purposes,
> but current DFL framework only supports feature device enumeration with
> given MMIO resources information via common DFL headers. This patch
> introduces one new API dfl_fpga_enum_info_add_irq for low level bus
> drivers (e.g. PCIe device driver) to pass its interrupt resources
> information to DFL framework for enumeration, and also adds interrupt
> enumeration code in framework to parse and assign interrupt resources
> for enumerated feature devices and their own sub features.
> 
> With this patch, DFL framework enumerates interrupt resources for core
> features, including PORT Error Reporting, FME (FPGA Management Engine)
> Error Reporting and also AFU User Interrupts.
> 
> Signed-off-by: Luwei Kang 
> Signed-off-by: Wu Hao 
> Signed-off-by: Xu Yilun 
> Reviewed-by: Marcelo Tosatti 
> Acked-by: Wu Hao 
> ---
> v2: early validating irq table for each feature in parse_feature_irq().
> Some code improvement and minor fix for Hao's comments.
> v3: put parse_feature_irqs() inside create_feature_instance()
> some minor fixes and more comments
> v4: no need to include asm/irq.h.
> fail the dfl enumeration when irq parsing error happens.
> v5: Some minor fix for Hao's comments
> v6: Remove unnecessary type casting.
> Some comment fix for Moritz's comments.
> v7: Add the header file , to fix build error on
> ARCH=xtensa
> ---
>  drivers/fpga/dfl.c | 153 
> +
>  drivers/fpga/dfl.h |  41 ++
>  2 files changed, 194 insertions(+)
> 
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 9909948..02c1ec4 100644
> --- a/drivers/fpga/dfl.c
> +++ b/drivers/fpga/dfl.c
> @@ -421,6 +421,9 @@ EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
>   *
>   * @dev: device to enumerate.
>   * @cdev: the container device for all feature devices.
> + * @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.
>   * @ioaddr: header register region address of feature device in enumeration.
>   * @sub_features: a sub features linked list for feature device in 
> enumeration.
> @@ -429,6 +432,9 @@ EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
>  struct build_feature_devs_info {
>   struct device *dev;
>   struct dfl_fpga_cdev *cdev;
> + unsigned int nr_irqs;
> + int *irq_table;
> +
>   struct platform_device *feature_dev;
>   void __iomem *ioaddr;
>   struct list_head sub_features;
> @@ -442,12 +448,16 @@ struct build_feature_devs_info {
>   * @mmio_res: mmio resource of this sub feature.
>   * @ioaddr: mapped base address of mmio resource.
>   * @node: node in sub_features linked list.
> + * @irq_base: start of irq index in this sub feature.
> + * @nr_irqs: number of irqs of this sub feature.
>   */
>  struct dfl_feature_info {
>   u64 fid;
>   struct resource mmio_res;
>   void __iomem *ioaddr;
>   struct list_head node;
> + unsigned int irq_base;
> + unsigned int nr_irqs;
>  };
>  
>  static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
> @@ -520,6 +530,8 @@ static int build_info_commit_dev(struct 
> build_feature_devs_info *binfo)
>   /* fill features and resource information for feature dev */
>   list_for_each_entry_safe(finfo, p, >sub_features, node) {
>   struct dfl_feature *feature = >features[index];
> + struct dfl_feature_irq_ctx *ctx;
> + unsigned int i;
>  
>   /* save resource information for each feature */
>   feature->id = finfo->fid;
> @@ -527,6 +539,20 @@ static int build_info_commit_dev(struct 
> build_feature_devs_info *binfo)
>   feature->ioaddr = finfo->ioaddr;
>   fdev->resource[index++] = finfo->mmio_res;
>  
> + if (finfo->nr_irqs) {
> + ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs,
> +sizeof(*ctx), GFP_KERNEL);
> + if (!ctx)
> + return -ENOMEM;
> +
> + for (i = 0; i < finfo->nr_irqs; i++)
> + ctx[i].irq =
> + binfo->irq_table[finfo->irq_base + i];
> +
> + feature->irq_ctx = ctx;
> + feature->nr_irqs = finfo->nr_irqs;
> + }
> +
>   list_del(>node);
>   kfree(finfo);
>   }
> @@ -638,6 +664,78 @@ static u64 feature_id(void __iomem *start)
>   return 0;
>  }
>  
> +static int parse_feature_irqs(struct build_feature_devs_info *binfo,
> +   resource_size_t ofst, u64 fid,
> +   unsigned int *irq_base, unsigned int *nr_irqs)
> +{
> + void __iomem *base = 

[PATCH v7 1/7] fpga: dfl: parse interrupt info for feature devices on enumeration

2020-06-15 Thread Xu Yilun
DFL based FPGA devices could support interrupts for different purposes,
but current DFL framework only supports feature device enumeration with
given MMIO resources information via common DFL headers. This patch
introduces one new API dfl_fpga_enum_info_add_irq for low level bus
drivers (e.g. PCIe device driver) to pass its interrupt resources
information to DFL framework for enumeration, and also adds interrupt
enumeration code in framework to parse and assign interrupt resources
for enumerated feature devices and their own sub features.

With this patch, DFL framework enumerates interrupt resources for core
features, including PORT Error Reporting, FME (FPGA Management Engine)
Error Reporting and also AFU User Interrupts.

Signed-off-by: Luwei Kang 
Signed-off-by: Wu Hao 
Signed-off-by: Xu Yilun 
Reviewed-by: Marcelo Tosatti 
Acked-by: Wu Hao 
---
v2: early validating irq table for each feature in parse_feature_irq().
Some code improvement and minor fix for Hao's comments.
v3: put parse_feature_irqs() inside create_feature_instance()
some minor fixes and more comments
v4: no need to include asm/irq.h.
fail the dfl enumeration when irq parsing error happens.
v5: Some minor fix for Hao's comments
v6: Remove unnecessary type casting.
Some comment fix for Moritz's comments.
v7: Add the header file , to fix build error on
ARCH=xtensa
---
 drivers/fpga/dfl.c | 153 +
 drivers/fpga/dfl.h |  41 ++
 2 files changed, 194 insertions(+)

diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 9909948..02c1ec4 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -421,6 +421,9 @@ EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
  *
  * @dev: device to enumerate.
  * @cdev: the container device for all feature devices.
+ * @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.
  * @ioaddr: header register region address of feature device in enumeration.
  * @sub_features: a sub features linked list for feature device in enumeration.
@@ -429,6 +432,9 @@ EXPORT_SYMBOL_GPL(dfl_fpga_dev_ops_unregister);
 struct build_feature_devs_info {
struct device *dev;
struct dfl_fpga_cdev *cdev;
+   unsigned int nr_irqs;
+   int *irq_table;
+
struct platform_device *feature_dev;
void __iomem *ioaddr;
struct list_head sub_features;
@@ -442,12 +448,16 @@ struct build_feature_devs_info {
  * @mmio_res: mmio resource of this sub feature.
  * @ioaddr: mapped base address of mmio resource.
  * @node: node in sub_features linked list.
+ * @irq_base: start of irq index in this sub feature.
+ * @nr_irqs: number of irqs of this sub feature.
  */
 struct dfl_feature_info {
u64 fid;
struct resource mmio_res;
void __iomem *ioaddr;
struct list_head node;
+   unsigned int irq_base;
+   unsigned int nr_irqs;
 };
 
 static void dfl_fpga_cdev_add_port_dev(struct dfl_fpga_cdev *cdev,
@@ -520,6 +530,8 @@ static int build_info_commit_dev(struct 
build_feature_devs_info *binfo)
/* fill features and resource information for feature dev */
list_for_each_entry_safe(finfo, p, >sub_features, node) {
struct dfl_feature *feature = >features[index];
+   struct dfl_feature_irq_ctx *ctx;
+   unsigned int i;
 
/* save resource information for each feature */
feature->id = finfo->fid;
@@ -527,6 +539,20 @@ static int build_info_commit_dev(struct 
build_feature_devs_info *binfo)
feature->ioaddr = finfo->ioaddr;
fdev->resource[index++] = finfo->mmio_res;
 
+   if (finfo->nr_irqs) {
+   ctx = devm_kcalloc(binfo->dev, finfo->nr_irqs,
+  sizeof(*ctx), GFP_KERNEL);
+   if (!ctx)
+   return -ENOMEM;
+
+   for (i = 0; i < finfo->nr_irqs; i++)
+   ctx[i].irq =
+   binfo->irq_table[finfo->irq_base + i];
+
+   feature->irq_ctx = ctx;
+   feature->nr_irqs = finfo->nr_irqs;
+   }
+
list_del(>node);
kfree(finfo);
}
@@ -638,6 +664,78 @@ static u64 feature_id(void __iomem *start)
return 0;
 }
 
+static int parse_feature_irqs(struct build_feature_devs_info *binfo,
+ resource_size_t ofst, u64 fid,
+ unsigned int *irq_base, unsigned int *nr_irqs)
+{
+   void __iomem *base = binfo->ioaddr + ofst;
+   unsigned int i, ibase, inr = 0;
+   int virq;
+   u64 v;
+
+   /*
+* Ideally DFL framework should only read info from DFL header, but
+* current version DFL only