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

2020-05-25 Thread Marcelo Tosatti
On Mon, Apr 20, 2020 at 04:11:37PM +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 
> 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
> ---
>  drivers/fpga/dfl.c | 154 
> +
>  drivers/fpga/dfl.h |  40 ++
>  2 files changed, 194 insertions(+)
> 
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 9909948..b49fbed 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, &binfo->sub_features, node) {
>   struct dfl_feature *feature = &pdata->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(&finfo->node);
>   kfree(finfo);
>   }
> @@ -638,6 +664,79 @@ 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

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

2020-05-13 Thread Xu Yilun
On Mon, May 11, 2020 at 09:09:07PM -0700, Moritz Fischer wrote:
> On Mon, Apr 20, 2020 at 04:11:37PM +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 
> > 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
> > ---
> >  drivers/fpga/dfl.c | 154 
> > +
> >  drivers/fpga/dfl.h |  40 ++
> >  2 files changed, 194 insertions(+)
> > 
> > diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> > index 9909948..b49fbed 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, &binfo->sub_features, node) {
> > struct dfl_feature *feature = &pdata->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(&finfo->node);
> > kfree(finfo);
> > }
> > @@ -638,6 +664,79 @@ 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 i

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

2020-05-11 Thread Moritz Fischer
On Mon, Apr 20, 2020 at 04:11:37PM +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 
> 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
> ---
>  drivers/fpga/dfl.c | 154 
> +
>  drivers/fpga/dfl.h |  40 ++
>  2 files changed, 194 insertions(+)
> 
> diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
> index 9909948..b49fbed 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, &binfo->sub_features, node) {
>   struct dfl_feature *feature = &pdata->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(&finfo->node);
>   kfree(finfo);
>   }
> @@ -638,6 +664,79 @@ 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