Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Honghui Zhang
On Thu, 2018-05-03 at 14:05 +0100, Marc Zyngier wrote:
> On 03/05/18 10:41, Honghui Zhang wrote:
> > On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
> >> On 02/05/18 10:41, Honghui Zhang wrote:
> >>> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
>  Hi Zhang,
> 
>  On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> > From: Honghui Zhang 
> >
> > Using irq_chip solution to setup IRQs for the consistent with IRQ 
> > framework.
> >
> > Signed-off-by: Honghui Zhang 
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 192 
> > +--
> >  1 file changed, 105 insertions(+), 87 deletions(-)
> >
> > diff --git a/drivers/pci/host/pcie-mediatek.c 
> > b/drivers/pci/host/pcie-mediatek.c
> > index c3dc549..1d9c6f1 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -11,8 +11,10 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >  /**
> >   * struct mtk_pcie_soc - differentiate between host generations
> >   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> > or not
> > - * @has_msi: whether this host supports MSI interrupts or not
> >   * @ops: pointer to configuration access functions
> >   * @startup: pointer to controller setting functions
> >   * @setup_irq: pointer to initialize IRQ functions
> >   */
> >  struct mtk_pcie_soc {
> > bool need_fix_class_id;
> > -   bool has_msi;
> > struct pci_ops *ops;
> > int (*startup)(struct mtk_pcie_port *port);
> > int (*setup_irq)(struct mtk_pcie_port *port, struct device_node 
> > *node);
> > @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >   * @lane: lane count
> >   * @slot: port slot
> >   * @irq_domain: legacy INTx IRQ domain
> > + * @inner_domain: inner IRQ domain
> >   * @msi_domain: MSI IRQ domain
> > + * @lock: protect the msi_irq_in_use bitmap
> >   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >   */
> >  struct mtk_pcie_port {
> > @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> > u32 lane;
> > u32 slot;
> > struct irq_domain *irq_domain;
> > +   struct irq_domain *inner_domain;
> > struct irq_domain *msi_domain;
> > +   struct mutex lock;
> > DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >  };
> >  
> > @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> > mtk_pcie_port *port)
> > return 0;
> >  }
> >  
> > -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> > +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> > *msg)
> >  {
> > -   int msi;
> > +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> > +   phys_addr_t addr;
> >  
> > -   msi = find_first_zero_bit(port->msi_irq_in_use, 
> > MTK_MSI_IRQS_NUM);
> > -   if (msi < MTK_MSI_IRQS_NUM)
> > -   set_bit(msi, port->msi_irq_in_use);
> > -   else
> > -   return -ENOSPC;
> > +   /* MT2712/MT7622 only support 32-bit MSI addresses */
> > +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> > +   msg->address_hi = 0;
> > +   msg->address_lo = lower_32_bits(addr);
> >  
> > -   return msi;
> > +   msg->data = data->hwirq;
> > +
> > +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo 
> > %#x\n",
> > +   (int)data->hwirq, msg->address_hi, msg->address_lo);
> >  }
> >  
> > -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned 
> > long hwirq)
> > +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> > +  const struct cpumask *mask, bool 
> > force)
> >  {
> > -   clear_bit(hwirq, port->msi_irq_in_use);
> > +   return -EINVAL;
> >  }
> >  
> > -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> > - struct pci_dev *pdev, struct msi_desc 
> > *desc)
> > -{
> > -   struct mtk_pcie_port *port;
> > -   struct msi_msg msg;
> > -   unsigned int irq;
> > -   int hwirq;
> > -   phys_addr_t msg_addr;
> > +static struct irq_chip mtk_msi_bottom_irq_chip = {
> > +   .name   = "MTK MSI",
> > +   .irq_compose_msi_msg= mtk_compose_msi_msg,
> > +   .irq_set_affinity   = mtk_msi_set_affinity,
> > +   

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Honghui Zhang
On Thu, 2018-05-03 at 14:05 +0100, Marc Zyngier wrote:
> On 03/05/18 10:41, Honghui Zhang wrote:
> > On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
> >> On 02/05/18 10:41, Honghui Zhang wrote:
> >>> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
>  Hi Zhang,
> 
>  On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> > From: Honghui Zhang 
> >
> > Using irq_chip solution to setup IRQs for the consistent with IRQ 
> > framework.
> >
> > Signed-off-by: Honghui Zhang 
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 192 
> > +--
> >  1 file changed, 105 insertions(+), 87 deletions(-)
> >
> > diff --git a/drivers/pci/host/pcie-mediatek.c 
> > b/drivers/pci/host/pcie-mediatek.c
> > index c3dc549..1d9c6f1 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -11,8 +11,10 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >  /**
> >   * struct mtk_pcie_soc - differentiate between host generations
> >   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> > or not
> > - * @has_msi: whether this host supports MSI interrupts or not
> >   * @ops: pointer to configuration access functions
> >   * @startup: pointer to controller setting functions
> >   * @setup_irq: pointer to initialize IRQ functions
> >   */
> >  struct mtk_pcie_soc {
> > bool need_fix_class_id;
> > -   bool has_msi;
> > struct pci_ops *ops;
> > int (*startup)(struct mtk_pcie_port *port);
> > int (*setup_irq)(struct mtk_pcie_port *port, struct device_node 
> > *node);
> > @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >   * @lane: lane count
> >   * @slot: port slot
> >   * @irq_domain: legacy INTx IRQ domain
> > + * @inner_domain: inner IRQ domain
> >   * @msi_domain: MSI IRQ domain
> > + * @lock: protect the msi_irq_in_use bitmap
> >   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >   */
> >  struct mtk_pcie_port {
> > @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> > u32 lane;
> > u32 slot;
> > struct irq_domain *irq_domain;
> > +   struct irq_domain *inner_domain;
> > struct irq_domain *msi_domain;
> > +   struct mutex lock;
> > DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >  };
> >  
> > @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> > mtk_pcie_port *port)
> > return 0;
> >  }
> >  
> > -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> > +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> > *msg)
> >  {
> > -   int msi;
> > +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> > +   phys_addr_t addr;
> >  
> > -   msi = find_first_zero_bit(port->msi_irq_in_use, 
> > MTK_MSI_IRQS_NUM);
> > -   if (msi < MTK_MSI_IRQS_NUM)
> > -   set_bit(msi, port->msi_irq_in_use);
> > -   else
> > -   return -ENOSPC;
> > +   /* MT2712/MT7622 only support 32-bit MSI addresses */
> > +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> > +   msg->address_hi = 0;
> > +   msg->address_lo = lower_32_bits(addr);
> >  
> > -   return msi;
> > +   msg->data = data->hwirq;
> > +
> > +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo 
> > %#x\n",
> > +   (int)data->hwirq, msg->address_hi, msg->address_lo);
> >  }
> >  
> > -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned 
> > long hwirq)
> > +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> > +  const struct cpumask *mask, bool 
> > force)
> >  {
> > -   clear_bit(hwirq, port->msi_irq_in_use);
> > +   return -EINVAL;
> >  }
> >  
> > -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> > - struct pci_dev *pdev, struct msi_desc 
> > *desc)
> > -{
> > -   struct mtk_pcie_port *port;
> > -   struct msi_msg msg;
> > -   unsigned int irq;
> > -   int hwirq;
> > -   phys_addr_t msg_addr;
> > +static struct irq_chip mtk_msi_bottom_irq_chip = {
> > +   .name   = "MTK MSI",
> > +   .irq_compose_msi_msg= mtk_compose_msi_msg,
> > +   .irq_set_affinity   = mtk_msi_set_affinity,
> > +   .irq_mask   = pci_msi_mask_irq,
> > +   

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Marc Zyngier
On 03/05/18 10:41, Honghui Zhang wrote:
> On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
>> On 02/05/18 10:41, Honghui Zhang wrote:
>>> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
 Hi Zhang,

 On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> From: Honghui Zhang 
>
> Using irq_chip solution to setup IRQs for the consistent with IRQ 
> framework.
>
> Signed-off-by: Honghui Zhang 
> ---
>  drivers/pci/host/pcie-mediatek.c | 192 
> +--
>  1 file changed, 105 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-mediatek.c 
> b/drivers/pci/host/pcie-mediatek.c
> index c3dc549..1d9c6f1 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -11,8 +11,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> or not
> - * @has_msi: whether this host supports MSI interrupts or not
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
>   * @setup_irq: pointer to initialize IRQ functions
>   */
>  struct mtk_pcie_soc {
>   bool need_fix_class_id;
> - bool has_msi;
>   struct pci_ops *ops;
>   int (*startup)(struct mtk_pcie_port *port);
>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>   * @lane: lane count
>   * @slot: port slot
>   * @irq_domain: legacy INTx IRQ domain
> + * @inner_domain: inner IRQ domain
>   * @msi_domain: MSI IRQ domain
> + * @lock: protect the msi_irq_in_use bitmap
>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>   */
>  struct mtk_pcie_port {
> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>   u32 lane;
>   u32 slot;
>   struct irq_domain *irq_domain;
> + struct irq_domain *inner_domain;
>   struct irq_domain *msi_domain;
> + struct mutex lock;
>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>  };
>  
> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> mtk_pcie_port *port)
>   return 0;
>  }
>  
> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> *msg)
>  {
> - int msi;
> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> + phys_addr_t addr;
>  
> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> - if (msi < MTK_MSI_IRQS_NUM)
> - set_bit(msi, port->msi_irq_in_use);
> - else
> - return -ENOSPC;
> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> + msg->address_hi = 0;
> + msg->address_lo = lower_32_bits(addr);
>  
> - return msi;
> + msg->data = data->hwirq;
> +
> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> + (int)data->hwirq, msg->address_hi, msg->address_lo);
>  }
>  
> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> hwirq)
> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> +const struct cpumask *mask, bool force)
>  {
> - clear_bit(hwirq, port->msi_irq_in_use);
> + return -EINVAL;
>  }
>  
> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> -   struct pci_dev *pdev, struct msi_desc *desc)
> -{
> - struct mtk_pcie_port *port;
> - struct msi_msg msg;
> - unsigned int irq;
> - int hwirq;
> - phys_addr_t msg_addr;
> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> + .name   = "MTK MSI",
> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> + .irq_set_affinity   = mtk_msi_set_affinity,
> + .irq_mask   = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
> +};
>  
> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> - if (!port)
> - return -EINVAL;
> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> int virq,
> +  unsigned int nr_irqs, void *args)
> +{
> + struct mtk_pcie_port *port = domain->host_data;
> + unsigned long bit;
>  
> - hwirq = mtk_pcie_msi_alloc(port);
> - if (hwirq < 0)
> - return hwirq;
> + 

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Marc Zyngier
On 03/05/18 10:41, Honghui Zhang wrote:
> On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
>> On 02/05/18 10:41, Honghui Zhang wrote:
>>> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
 Hi Zhang,

 On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> From: Honghui Zhang 
>
> Using irq_chip solution to setup IRQs for the consistent with IRQ 
> framework.
>
> Signed-off-by: Honghui Zhang 
> ---
>  drivers/pci/host/pcie-mediatek.c | 192 
> +--
>  1 file changed, 105 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-mediatek.c 
> b/drivers/pci/host/pcie-mediatek.c
> index c3dc549..1d9c6f1 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -11,8 +11,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> or not
> - * @has_msi: whether this host supports MSI interrupts or not
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
>   * @setup_irq: pointer to initialize IRQ functions
>   */
>  struct mtk_pcie_soc {
>   bool need_fix_class_id;
> - bool has_msi;
>   struct pci_ops *ops;
>   int (*startup)(struct mtk_pcie_port *port);
>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>   * @lane: lane count
>   * @slot: port slot
>   * @irq_domain: legacy INTx IRQ domain
> + * @inner_domain: inner IRQ domain
>   * @msi_domain: MSI IRQ domain
> + * @lock: protect the msi_irq_in_use bitmap
>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>   */
>  struct mtk_pcie_port {
> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>   u32 lane;
>   u32 slot;
>   struct irq_domain *irq_domain;
> + struct irq_domain *inner_domain;
>   struct irq_domain *msi_domain;
> + struct mutex lock;
>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>  };
>  
> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> mtk_pcie_port *port)
>   return 0;
>  }
>  
> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> *msg)
>  {
> - int msi;
> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> + phys_addr_t addr;
>  
> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> - if (msi < MTK_MSI_IRQS_NUM)
> - set_bit(msi, port->msi_irq_in_use);
> - else
> - return -ENOSPC;
> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> + msg->address_hi = 0;
> + msg->address_lo = lower_32_bits(addr);
>  
> - return msi;
> + msg->data = data->hwirq;
> +
> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> + (int)data->hwirq, msg->address_hi, msg->address_lo);
>  }
>  
> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> hwirq)
> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> +const struct cpumask *mask, bool force)
>  {
> - clear_bit(hwirq, port->msi_irq_in_use);
> + return -EINVAL;
>  }
>  
> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> -   struct pci_dev *pdev, struct msi_desc *desc)
> -{
> - struct mtk_pcie_port *port;
> - struct msi_msg msg;
> - unsigned int irq;
> - int hwirq;
> - phys_addr_t msg_addr;
> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> + .name   = "MTK MSI",
> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> + .irq_set_affinity   = mtk_msi_set_affinity,
> + .irq_mask   = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
> +};
>  
> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> - if (!port)
> - return -EINVAL;
> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> int virq,
> +  unsigned int nr_irqs, void *args)
> +{
> + struct mtk_pcie_port *port = domain->host_data;
> + unsigned long bit;
>  
> - hwirq = mtk_pcie_msi_alloc(port);
> - if (hwirq < 0)
> - return hwirq;
> + WARN_ON(nr_irqs != 1);
> + mutex_lock(>lock);
>  
> - irq 

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Honghui Zhang
On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
> On 02/05/18 10:41, Honghui Zhang wrote:
> > On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
> >> Hi Zhang,
> >>
> >> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> >>> From: Honghui Zhang 
> >>>
> >>> Using irq_chip solution to setup IRQs for the consistent with IRQ 
> >>> framework.
> >>>
> >>> Signed-off-by: Honghui Zhang 
> >>> ---
> >>>  drivers/pci/host/pcie-mediatek.c | 192 
> >>> +--
> >>>  1 file changed, 105 insertions(+), 87 deletions(-)
> >>>
> >>> diff --git a/drivers/pci/host/pcie-mediatek.c 
> >>> b/drivers/pci/host/pcie-mediatek.c
> >>> index c3dc549..1d9c6f1 100644
> >>> --- a/drivers/pci/host/pcie-mediatek.c
> >>> +++ b/drivers/pci/host/pcie-mediatek.c
> >>> @@ -11,8 +11,10 @@
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> +#include 
> >>>  #include 
> >>>  #include 
> >>> +#include 
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >>>  /**
> >>>   * struct mtk_pcie_soc - differentiate between host generations
> >>>   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> >>> or not
> >>> - * @has_msi: whether this host supports MSI interrupts or not
> >>>   * @ops: pointer to configuration access functions
> >>>   * @startup: pointer to controller setting functions
> >>>   * @setup_irq: pointer to initialize IRQ functions
> >>>   */
> >>>  struct mtk_pcie_soc {
> >>>   bool need_fix_class_id;
> >>> - bool has_msi;
> >>>   struct pci_ops *ops;
> >>>   int (*startup)(struct mtk_pcie_port *port);
> >>>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> >>> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >>>   * @lane: lane count
> >>>   * @slot: port slot
> >>>   * @irq_domain: legacy INTx IRQ domain
> >>> + * @inner_domain: inner IRQ domain
> >>>   * @msi_domain: MSI IRQ domain
> >>> + * @lock: protect the msi_irq_in_use bitmap
> >>>   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >>>   */
> >>>  struct mtk_pcie_port {
> >>> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> >>>   u32 lane;
> >>>   u32 slot;
> >>>   struct irq_domain *irq_domain;
> >>> + struct irq_domain *inner_domain;
> >>>   struct irq_domain *msi_domain;
> >>> + struct mutex lock;
> >>>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >>>  };
> >>>  
> >>> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> >>> mtk_pcie_port *port)
> >>>   return 0;
> >>>  }
> >>>  
> >>> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> >>> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> >>> *msg)
> >>>  {
> >>> - int msi;
> >>> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> >>> + phys_addr_t addr;
> >>>  
> >>> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >>> - if (msi < MTK_MSI_IRQS_NUM)
> >>> - set_bit(msi, port->msi_irq_in_use);
> >>> - else
> >>> - return -ENOSPC;
> >>> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> >>> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> >>> + msg->address_hi = 0;
> >>> + msg->address_lo = lower_32_bits(addr);
> >>>  
> >>> - return msi;
> >>> + msg->data = data->hwirq;
> >>> +
> >>> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> >>> + (int)data->hwirq, msg->address_hi, msg->address_lo);
> >>>  }
> >>>  
> >>> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> >>> hwirq)
> >>> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> >>> +const struct cpumask *mask, bool force)
> >>>  {
> >>> - clear_bit(hwirq, port->msi_irq_in_use);
> >>> + return -EINVAL;
> >>>  }
> >>>  
> >>> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> >>> -   struct pci_dev *pdev, struct msi_desc *desc)
> >>> -{
> >>> - struct mtk_pcie_port *port;
> >>> - struct msi_msg msg;
> >>> - unsigned int irq;
> >>> - int hwirq;
> >>> - phys_addr_t msg_addr;
> >>> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> >>> + .name   = "MTK MSI",
> >>> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> >>> + .irq_set_affinity   = mtk_msi_set_affinity,
> >>> + .irq_mask   = pci_msi_mask_irq,
> >>> + .irq_unmask = pci_msi_unmask_irq,
> >>> +};
> >>>  
> >>> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> >>> - if (!port)
> >>> - return -EINVAL;
> >>> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> >>> int virq,
> >>> +  unsigned int nr_irqs, void *args)
> >>> +{
> >>> + struct mtk_pcie_port *port = domain->host_data;
> >>> + unsigned long bit;
> >>>  
> >>> - hwirq = mtk_pcie_msi_alloc(port);
> >>> - if (hwirq < 0)
> >>> - return hwirq;
> >>> + WARN_ON(nr_irqs != 1);
> >>> + mutex_lock(>lock);
> >>>  

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-03 Thread Honghui Zhang
On Wed, 2018-05-02 at 11:09 +0100, Marc Zyngier wrote:
> On 02/05/18 10:41, Honghui Zhang wrote:
> > On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
> >> Hi Zhang,
> >>
> >> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> >>> From: Honghui Zhang 
> >>>
> >>> Using irq_chip solution to setup IRQs for the consistent with IRQ 
> >>> framework.
> >>>
> >>> Signed-off-by: Honghui Zhang 
> >>> ---
> >>>  drivers/pci/host/pcie-mediatek.c | 192 
> >>> +--
> >>>  1 file changed, 105 insertions(+), 87 deletions(-)
> >>>
> >>> diff --git a/drivers/pci/host/pcie-mediatek.c 
> >>> b/drivers/pci/host/pcie-mediatek.c
> >>> index c3dc549..1d9c6f1 100644
> >>> --- a/drivers/pci/host/pcie-mediatek.c
> >>> +++ b/drivers/pci/host/pcie-mediatek.c
> >>> @@ -11,8 +11,10 @@
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> +#include 
> >>>  #include 
> >>>  #include 
> >>> +#include 
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >>>  /**
> >>>   * struct mtk_pcie_soc - differentiate between host generations
> >>>   * @need_fix_class_id: whether this host's class ID needed to be fixed 
> >>> or not
> >>> - * @has_msi: whether this host supports MSI interrupts or not
> >>>   * @ops: pointer to configuration access functions
> >>>   * @startup: pointer to controller setting functions
> >>>   * @setup_irq: pointer to initialize IRQ functions
> >>>   */
> >>>  struct mtk_pcie_soc {
> >>>   bool need_fix_class_id;
> >>> - bool has_msi;
> >>>   struct pci_ops *ops;
> >>>   int (*startup)(struct mtk_pcie_port *port);
> >>>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> >>> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >>>   * @lane: lane count
> >>>   * @slot: port slot
> >>>   * @irq_domain: legacy INTx IRQ domain
> >>> + * @inner_domain: inner IRQ domain
> >>>   * @msi_domain: MSI IRQ domain
> >>> + * @lock: protect the msi_irq_in_use bitmap
> >>>   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >>>   */
> >>>  struct mtk_pcie_port {
> >>> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> >>>   u32 lane;
> >>>   u32 slot;
> >>>   struct irq_domain *irq_domain;
> >>> + struct irq_domain *inner_domain;
> >>>   struct irq_domain *msi_domain;
> >>> + struct mutex lock;
> >>>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >>>  };
> >>>  
> >>> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> >>> mtk_pcie_port *port)
> >>>   return 0;
> >>>  }
> >>>  
> >>> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> >>> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg 
> >>> *msg)
> >>>  {
> >>> - int msi;
> >>> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> >>> + phys_addr_t addr;
> >>>  
> >>> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >>> - if (msi < MTK_MSI_IRQS_NUM)
> >>> - set_bit(msi, port->msi_irq_in_use);
> >>> - else
> >>> - return -ENOSPC;
> >>> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> >>> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> >>> + msg->address_hi = 0;
> >>> + msg->address_lo = lower_32_bits(addr);
> >>>  
> >>> - return msi;
> >>> + msg->data = data->hwirq;
> >>> +
> >>> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> >>> + (int)data->hwirq, msg->address_hi, msg->address_lo);
> >>>  }
> >>>  
> >>> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> >>> hwirq)
> >>> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> >>> +const struct cpumask *mask, bool force)
> >>>  {
> >>> - clear_bit(hwirq, port->msi_irq_in_use);
> >>> + return -EINVAL;
> >>>  }
> >>>  
> >>> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> >>> -   struct pci_dev *pdev, struct msi_desc *desc)
> >>> -{
> >>> - struct mtk_pcie_port *port;
> >>> - struct msi_msg msg;
> >>> - unsigned int irq;
> >>> - int hwirq;
> >>> - phys_addr_t msg_addr;
> >>> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> >>> + .name   = "MTK MSI",
> >>> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> >>> + .irq_set_affinity   = mtk_msi_set_affinity,
> >>> + .irq_mask   = pci_msi_mask_irq,
> >>> + .irq_unmask = pci_msi_unmask_irq,
> >>> +};
> >>>  
> >>> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> >>> - if (!port)
> >>> - return -EINVAL;
> >>> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> >>> int virq,
> >>> +  unsigned int nr_irqs, void *args)
> >>> +{
> >>> + struct mtk_pcie_port *port = domain->host_data;
> >>> + unsigned long bit;
> >>>  
> >>> - hwirq = mtk_pcie_msi_alloc(port);
> >>> - if (hwirq < 0)
> >>> - return hwirq;
> >>> + WARN_ON(nr_irqs != 1);
> >>> + mutex_lock(>lock);
> >>>  
> >>> - irq = irq_create_mapping(port->msi_domain, 

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-02 Thread Honghui Zhang
On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
> Hi Zhang,
> 
> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> > From: Honghui Zhang 
> > 
> > Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
> > 
> > Signed-off-by: Honghui Zhang 
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 192 
> > +--
> >  1 file changed, 105 insertions(+), 87 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c 
> > b/drivers/pci/host/pcie-mediatek.c
> > index c3dc549..1d9c6f1 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -11,8 +11,10 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >  /**
> >   * struct mtk_pcie_soc - differentiate between host generations
> >   * @need_fix_class_id: whether this host's class ID needed to be fixed or 
> > not
> > - * @has_msi: whether this host supports MSI interrupts or not
> >   * @ops: pointer to configuration access functions
> >   * @startup: pointer to controller setting functions
> >   * @setup_irq: pointer to initialize IRQ functions
> >   */
> >  struct mtk_pcie_soc {
> > bool need_fix_class_id;
> > -   bool has_msi;
> > struct pci_ops *ops;
> > int (*startup)(struct mtk_pcie_port *port);
> > int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> > @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >   * @lane: lane count
> >   * @slot: port slot
> >   * @irq_domain: legacy INTx IRQ domain
> > + * @inner_domain: inner IRQ domain
> >   * @msi_domain: MSI IRQ domain
> > + * @lock: protect the msi_irq_in_use bitmap
> >   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >   */
> >  struct mtk_pcie_port {
> > @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> > u32 lane;
> > u32 slot;
> > struct irq_domain *irq_domain;
> > +   struct irq_domain *inner_domain;
> > struct irq_domain *msi_domain;
> > +   struct mutex lock;
> > DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >  };
> >  
> > @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> > mtk_pcie_port *port)
> > return 0;
> >  }
> >  
> > -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> > +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
> >  {
> > -   int msi;
> > +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> > +   phys_addr_t addr;
> >  
> > -   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> > -   if (msi < MTK_MSI_IRQS_NUM)
> > -   set_bit(msi, port->msi_irq_in_use);
> > -   else
> > -   return -ENOSPC;
> > +   /* MT2712/MT7622 only support 32-bit MSI addresses */
> > +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> > +   msg->address_hi = 0;
> > +   msg->address_lo = lower_32_bits(addr);
> >  
> > -   return msi;
> > +   msg->data = data->hwirq;
> > +
> > +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> > +   (int)data->hwirq, msg->address_hi, msg->address_lo);
> >  }
> >  
> > -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> > hwirq)
> > +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> > +  const struct cpumask *mask, bool force)
> >  {
> > -   clear_bit(hwirq, port->msi_irq_in_use);
> > +   return -EINVAL;
> >  }
> >  
> > -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> > - struct pci_dev *pdev, struct msi_desc *desc)
> > -{
> > -   struct mtk_pcie_port *port;
> > -   struct msi_msg msg;
> > -   unsigned int irq;
> > -   int hwirq;
> > -   phys_addr_t msg_addr;
> > +static struct irq_chip mtk_msi_bottom_irq_chip = {
> > +   .name   = "MTK MSI",
> > +   .irq_compose_msi_msg= mtk_compose_msi_msg,
> > +   .irq_set_affinity   = mtk_msi_set_affinity,
> > +   .irq_mask   = pci_msi_mask_irq,
> > +   .irq_unmask = pci_msi_unmask_irq,
> > +};
> >  
> > -   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> > -   if (!port)
> > -   return -EINVAL;
> > +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> > int virq,
> > +unsigned int nr_irqs, void *args)
> > +{
> > +   struct mtk_pcie_port *port = domain->host_data;
> > +   unsigned long bit;
> >  
> > -   hwirq = mtk_pcie_msi_alloc(port);
> > -   if (hwirq < 0)
> > -   return hwirq;
> > +   WARN_ON(nr_irqs != 1);
> > +   mutex_lock(>lock);
> >  
> > -   irq = irq_create_mapping(port->msi_domain, hwirq);
> > -   if (!irq) {
> > -   mtk_pcie_msi_free(port, hwirq);
> > -   return -EINVAL;
> > +   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> > +   if (bit >= MTK_MSI_IRQS_NUM) {
> 

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-02 Thread Honghui Zhang
On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
> Hi Zhang,
> 
> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> > From: Honghui Zhang 
> > 
> > Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
> > 
> > Signed-off-by: Honghui Zhang 
> > ---
> >  drivers/pci/host/pcie-mediatek.c | 192 
> > +--
> >  1 file changed, 105 insertions(+), 87 deletions(-)
> > 
> > diff --git a/drivers/pci/host/pcie-mediatek.c 
> > b/drivers/pci/host/pcie-mediatek.c
> > index c3dc549..1d9c6f1 100644
> > --- a/drivers/pci/host/pcie-mediatek.c
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -11,8 +11,10 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -130,14 +132,12 @@ struct mtk_pcie_port;
> >  /**
> >   * struct mtk_pcie_soc - differentiate between host generations
> >   * @need_fix_class_id: whether this host's class ID needed to be fixed or 
> > not
> > - * @has_msi: whether this host supports MSI interrupts or not
> >   * @ops: pointer to configuration access functions
> >   * @startup: pointer to controller setting functions
> >   * @setup_irq: pointer to initialize IRQ functions
> >   */
> >  struct mtk_pcie_soc {
> > bool need_fix_class_id;
> > -   bool has_msi;
> > struct pci_ops *ops;
> > int (*startup)(struct mtk_pcie_port *port);
> > int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> > @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
> >   * @lane: lane count
> >   * @slot: port slot
> >   * @irq_domain: legacy INTx IRQ domain
> > + * @inner_domain: inner IRQ domain
> >   * @msi_domain: MSI IRQ domain
> > + * @lock: protect the msi_irq_in_use bitmap
> >   * @msi_irq_in_use: bit map for assigned MSI IRQ
> >   */
> >  struct mtk_pcie_port {
> > @@ -179,7 +181,9 @@ struct mtk_pcie_port {
> > u32 lane;
> > u32 slot;
> > struct irq_domain *irq_domain;
> > +   struct irq_domain *inner_domain;
> > struct irq_domain *msi_domain;
> > +   struct mutex lock;
> > DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >  };
> >  
> > @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> > mtk_pcie_port *port)
> > return 0;
> >  }
> >  
> > -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> > +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
> >  {
> > -   int msi;
> > +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> > +   phys_addr_t addr;
> >  
> > -   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> > -   if (msi < MTK_MSI_IRQS_NUM)
> > -   set_bit(msi, port->msi_irq_in_use);
> > -   else
> > -   return -ENOSPC;
> > +   /* MT2712/MT7622 only support 32-bit MSI addresses */
> > +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> > +   msg->address_hi = 0;
> > +   msg->address_lo = lower_32_bits(addr);
> >  
> > -   return msi;
> > +   msg->data = data->hwirq;
> > +
> > +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> > +   (int)data->hwirq, msg->address_hi, msg->address_lo);
> >  }
> >  
> > -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> > hwirq)
> > +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> > +  const struct cpumask *mask, bool force)
> >  {
> > -   clear_bit(hwirq, port->msi_irq_in_use);
> > +   return -EINVAL;
> >  }
> >  
> > -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> > - struct pci_dev *pdev, struct msi_desc *desc)
> > -{
> > -   struct mtk_pcie_port *port;
> > -   struct msi_msg msg;
> > -   unsigned int irq;
> > -   int hwirq;
> > -   phys_addr_t msg_addr;
> > +static struct irq_chip mtk_msi_bottom_irq_chip = {
> > +   .name   = "MTK MSI",
> > +   .irq_compose_msi_msg= mtk_compose_msi_msg,
> > +   .irq_set_affinity   = mtk_msi_set_affinity,
> > +   .irq_mask   = pci_msi_mask_irq,
> > +   .irq_unmask = pci_msi_unmask_irq,
> > +};
> >  
> > -   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> > -   if (!port)
> > -   return -EINVAL;
> > +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> > int virq,
> > +unsigned int nr_irqs, void *args)
> > +{
> > +   struct mtk_pcie_port *port = domain->host_data;
> > +   unsigned long bit;
> >  
> > -   hwirq = mtk_pcie_msi_alloc(port);
> > -   if (hwirq < 0)
> > -   return hwirq;
> > +   WARN_ON(nr_irqs != 1);
> > +   mutex_lock(>lock);
> >  
> > -   irq = irq_create_mapping(port->msi_domain, hwirq);
> > -   if (!irq) {
> > -   mtk_pcie_msi_free(port, hwirq);
> > -   return -EINVAL;
> > +   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> > +   if (bit >= MTK_MSI_IRQS_NUM) {
> > +   mutex_unlock(>lock);
> > +   

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-02 Thread Marc Zyngier
On 02/05/18 10:41, Honghui Zhang wrote:
> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
>> Hi Zhang,
>>
>> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
>>> From: Honghui Zhang 
>>>
>>> Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
>>>
>>> Signed-off-by: Honghui Zhang 
>>> ---
>>>  drivers/pci/host/pcie-mediatek.c | 192 
>>> +--
>>>  1 file changed, 105 insertions(+), 87 deletions(-)
>>>
>>> diff --git a/drivers/pci/host/pcie-mediatek.c 
>>> b/drivers/pci/host/pcie-mediatek.c
>>> index c3dc549..1d9c6f1 100644
>>> --- a/drivers/pci/host/pcie-mediatek.c
>>> +++ b/drivers/pci/host/pcie-mediatek.c
>>> @@ -11,8 +11,10 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>>>  /**
>>>   * struct mtk_pcie_soc - differentiate between host generations
>>>   * @need_fix_class_id: whether this host's class ID needed to be fixed or 
>>> not
>>> - * @has_msi: whether this host supports MSI interrupts or not
>>>   * @ops: pointer to configuration access functions
>>>   * @startup: pointer to controller setting functions
>>>   * @setup_irq: pointer to initialize IRQ functions
>>>   */
>>>  struct mtk_pcie_soc {
>>> bool need_fix_class_id;
>>> -   bool has_msi;
>>> struct pci_ops *ops;
>>> int (*startup)(struct mtk_pcie_port *port);
>>> int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
>>> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>>>   * @lane: lane count
>>>   * @slot: port slot
>>>   * @irq_domain: legacy INTx IRQ domain
>>> + * @inner_domain: inner IRQ domain
>>>   * @msi_domain: MSI IRQ domain
>>> + * @lock: protect the msi_irq_in_use bitmap
>>>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>>>   */
>>>  struct mtk_pcie_port {
>>> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>>> u32 lane;
>>> u32 slot;
>>> struct irq_domain *irq_domain;
>>> +   struct irq_domain *inner_domain;
>>> struct irq_domain *msi_domain;
>>> +   struct mutex lock;
>>> DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>>>  };
>>>  
>>> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
>>> mtk_pcie_port *port)
>>> return 0;
>>>  }
>>>  
>>> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
>>> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>>>  {
>>> -   int msi;
>>> +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
>>> +   phys_addr_t addr;
>>>  
>>> -   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
>>> -   if (msi < MTK_MSI_IRQS_NUM)
>>> -   set_bit(msi, port->msi_irq_in_use);
>>> -   else
>>> -   return -ENOSPC;
>>> +   /* MT2712/MT7622 only support 32-bit MSI addresses */
>>> +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
>>> +   msg->address_hi = 0;
>>> +   msg->address_lo = lower_32_bits(addr);
>>>  
>>> -   return msi;
>>> +   msg->data = data->hwirq;
>>> +
>>> +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
>>> +   (int)data->hwirq, msg->address_hi, msg->address_lo);
>>>  }
>>>  
>>> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
>>> hwirq)
>>> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
>>> +  const struct cpumask *mask, bool force)
>>>  {
>>> -   clear_bit(hwirq, port->msi_irq_in_use);
>>> +   return -EINVAL;
>>>  }
>>>  
>>> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
>>> - struct pci_dev *pdev, struct msi_desc *desc)
>>> -{
>>> -   struct mtk_pcie_port *port;
>>> -   struct msi_msg msg;
>>> -   unsigned int irq;
>>> -   int hwirq;
>>> -   phys_addr_t msg_addr;
>>> +static struct irq_chip mtk_msi_bottom_irq_chip = {
>>> +   .name   = "MTK MSI",
>>> +   .irq_compose_msi_msg= mtk_compose_msi_msg,
>>> +   .irq_set_affinity   = mtk_msi_set_affinity,
>>> +   .irq_mask   = pci_msi_mask_irq,
>>> +   .irq_unmask = pci_msi_unmask_irq,
>>> +};
>>>  
>>> -   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
>>> -   if (!port)
>>> -   return -EINVAL;
>>> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
>>> int virq,
>>> +unsigned int nr_irqs, void *args)
>>> +{
>>> +   struct mtk_pcie_port *port = domain->host_data;
>>> +   unsigned long bit;
>>>  
>>> -   hwirq = mtk_pcie_msi_alloc(port);
>>> -   if (hwirq < 0)
>>> -   return hwirq;
>>> +   WARN_ON(nr_irqs != 1);
>>> +   mutex_lock(>lock);
>>>  
>>> -   irq = irq_create_mapping(port->msi_domain, hwirq);
>>> -   if (!irq) {
>>> -   mtk_pcie_msi_free(port, hwirq);
>>> -   return -EINVAL;
>>> +   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-05-02 Thread Marc Zyngier
On 02/05/18 10:41, Honghui Zhang wrote:
> On Mon, 2018-04-30 at 12:03 +0100, Marc Zyngier wrote:
>> Hi Zhang,
>>
>> On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
>>> From: Honghui Zhang 
>>>
>>> Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
>>>
>>> Signed-off-by: Honghui Zhang 
>>> ---
>>>  drivers/pci/host/pcie-mediatek.c | 192 
>>> +--
>>>  1 file changed, 105 insertions(+), 87 deletions(-)
>>>
>>> diff --git a/drivers/pci/host/pcie-mediatek.c 
>>> b/drivers/pci/host/pcie-mediatek.c
>>> index c3dc549..1d9c6f1 100644
>>> --- a/drivers/pci/host/pcie-mediatek.c
>>> +++ b/drivers/pci/host/pcie-mediatek.c
>>> @@ -11,8 +11,10 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>>>  /**
>>>   * struct mtk_pcie_soc - differentiate between host generations
>>>   * @need_fix_class_id: whether this host's class ID needed to be fixed or 
>>> not
>>> - * @has_msi: whether this host supports MSI interrupts or not
>>>   * @ops: pointer to configuration access functions
>>>   * @startup: pointer to controller setting functions
>>>   * @setup_irq: pointer to initialize IRQ functions
>>>   */
>>>  struct mtk_pcie_soc {
>>> bool need_fix_class_id;
>>> -   bool has_msi;
>>> struct pci_ops *ops;
>>> int (*startup)(struct mtk_pcie_port *port);
>>> int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
>>> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>>>   * @lane: lane count
>>>   * @slot: port slot
>>>   * @irq_domain: legacy INTx IRQ domain
>>> + * @inner_domain: inner IRQ domain
>>>   * @msi_domain: MSI IRQ domain
>>> + * @lock: protect the msi_irq_in_use bitmap
>>>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>>>   */
>>>  struct mtk_pcie_port {
>>> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>>> u32 lane;
>>> u32 slot;
>>> struct irq_domain *irq_domain;
>>> +   struct irq_domain *inner_domain;
>>> struct irq_domain *msi_domain;
>>> +   struct mutex lock;
>>> DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>>>  };
>>>  
>>> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
>>> mtk_pcie_port *port)
>>> return 0;
>>>  }
>>>  
>>> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
>>> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>>>  {
>>> -   int msi;
>>> +   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
>>> +   phys_addr_t addr;
>>>  
>>> -   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
>>> -   if (msi < MTK_MSI_IRQS_NUM)
>>> -   set_bit(msi, port->msi_irq_in_use);
>>> -   else
>>> -   return -ENOSPC;
>>> +   /* MT2712/MT7622 only support 32-bit MSI addresses */
>>> +   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
>>> +   msg->address_hi = 0;
>>> +   msg->address_lo = lower_32_bits(addr);
>>>  
>>> -   return msi;
>>> +   msg->data = data->hwirq;
>>> +
>>> +   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
>>> +   (int)data->hwirq, msg->address_hi, msg->address_lo);
>>>  }
>>>  
>>> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
>>> hwirq)
>>> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
>>> +  const struct cpumask *mask, bool force)
>>>  {
>>> -   clear_bit(hwirq, port->msi_irq_in_use);
>>> +   return -EINVAL;
>>>  }
>>>  
>>> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
>>> - struct pci_dev *pdev, struct msi_desc *desc)
>>> -{
>>> -   struct mtk_pcie_port *port;
>>> -   struct msi_msg msg;
>>> -   unsigned int irq;
>>> -   int hwirq;
>>> -   phys_addr_t msg_addr;
>>> +static struct irq_chip mtk_msi_bottom_irq_chip = {
>>> +   .name   = "MTK MSI",
>>> +   .irq_compose_msi_msg= mtk_compose_msi_msg,
>>> +   .irq_set_affinity   = mtk_msi_set_affinity,
>>> +   .irq_mask   = pci_msi_mask_irq,
>>> +   .irq_unmask = pci_msi_unmask_irq,
>>> +};
>>>  
>>> -   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
>>> -   if (!port)
>>> -   return -EINVAL;
>>> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
>>> int virq,
>>> +unsigned int nr_irqs, void *args)
>>> +{
>>> +   struct mtk_pcie_port *port = domain->host_data;
>>> +   unsigned long bit;
>>>  
>>> -   hwirq = mtk_pcie_msi_alloc(port);
>>> -   if (hwirq < 0)
>>> -   return hwirq;
>>> +   WARN_ON(nr_irqs != 1);
>>> +   mutex_lock(>lock);
>>>  
>>> -   irq = irq_create_mapping(port->msi_domain, hwirq);
>>> -   if (!irq) {
>>> -   mtk_pcie_msi_free(port, hwirq);
>>> -   return -EINVAL;
>>> +   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
>>> +   if (bit >= MTK_MSI_IRQS_NUM) {
>>> +   

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-04-30 Thread Marc Zyngier
Hi Zhang,

On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> From: Honghui Zhang 
> 
> Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
> 
> Signed-off-by: Honghui Zhang 
> ---
>  drivers/pci/host/pcie-mediatek.c | 192 
> +--
>  1 file changed, 105 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c 
> b/drivers/pci/host/pcie-mediatek.c
> index c3dc549..1d9c6f1 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -11,8 +11,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @need_fix_class_id: whether this host's class ID needed to be fixed or not
> - * @has_msi: whether this host supports MSI interrupts or not
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
>   * @setup_irq: pointer to initialize IRQ functions
>   */
>  struct mtk_pcie_soc {
>   bool need_fix_class_id;
> - bool has_msi;
>   struct pci_ops *ops;
>   int (*startup)(struct mtk_pcie_port *port);
>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>   * @lane: lane count
>   * @slot: port slot
>   * @irq_domain: legacy INTx IRQ domain
> + * @inner_domain: inner IRQ domain
>   * @msi_domain: MSI IRQ domain
> + * @lock: protect the msi_irq_in_use bitmap
>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>   */
>  struct mtk_pcie_port {
> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>   u32 lane;
>   u32 slot;
>   struct irq_domain *irq_domain;
> + struct irq_domain *inner_domain;
>   struct irq_domain *msi_domain;
> + struct mutex lock;
>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>  };
>  
> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> mtk_pcie_port *port)
>   return 0;
>  }
>  
> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  {
> - int msi;
> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> + phys_addr_t addr;
>  
> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> - if (msi < MTK_MSI_IRQS_NUM)
> - set_bit(msi, port->msi_irq_in_use);
> - else
> - return -ENOSPC;
> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> + msg->address_hi = 0;
> + msg->address_lo = lower_32_bits(addr);
>  
> - return msi;
> + msg->data = data->hwirq;
> +
> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> + (int)data->hwirq, msg->address_hi, msg->address_lo);
>  }
>  
> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> hwirq)
> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> +const struct cpumask *mask, bool force)
>  {
> - clear_bit(hwirq, port->msi_irq_in_use);
> + return -EINVAL;
>  }
>  
> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> -   struct pci_dev *pdev, struct msi_desc *desc)
> -{
> - struct mtk_pcie_port *port;
> - struct msi_msg msg;
> - unsigned int irq;
> - int hwirq;
> - phys_addr_t msg_addr;
> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> + .name   = "MTK MSI",
> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> + .irq_set_affinity   = mtk_msi_set_affinity,
> + .irq_mask   = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
> +};
>  
> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> - if (!port)
> - return -EINVAL;
> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
> virq,
> +  unsigned int nr_irqs, void *args)
> +{
> + struct mtk_pcie_port *port = domain->host_data;
> + unsigned long bit;
>  
> - hwirq = mtk_pcie_msi_alloc(port);
> - if (hwirq < 0)
> - return hwirq;
> + WARN_ON(nr_irqs != 1);
> + mutex_lock(>lock);
>  
> - irq = irq_create_mapping(port->msi_domain, hwirq);
> - if (!irq) {
> - mtk_pcie_msi_free(port, hwirq);
> - return -EINVAL;
> + bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> + if (bit >= MTK_MSI_IRQS_NUM) {
> + mutex_unlock(>lock);
> + return -ENOSPC;
>   }
>  
> - chip->dev = >dev;
> -
> - irq_set_msi_desc(irq, desc);
> + __set_bit(bit, port->msi_irq_in_use);
>  
> - /* 

Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-04-30 Thread Marc Zyngier
Hi Zhang,

On 20/04/18 06:25, honghui.zh...@mediatek.com wrote:
> From: Honghui Zhang 
> 
> Using irq_chip solution to setup IRQs for the consistent with IRQ framework.
> 
> Signed-off-by: Honghui Zhang 
> ---
>  drivers/pci/host/pcie-mediatek.c | 192 
> +--
>  1 file changed, 105 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/pci/host/pcie-mediatek.c 
> b/drivers/pci/host/pcie-mediatek.c
> index c3dc549..1d9c6f1 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -11,8 +11,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -130,14 +132,12 @@ struct mtk_pcie_port;
>  /**
>   * struct mtk_pcie_soc - differentiate between host generations
>   * @need_fix_class_id: whether this host's class ID needed to be fixed or not
> - * @has_msi: whether this host supports MSI interrupts or not
>   * @ops: pointer to configuration access functions
>   * @startup: pointer to controller setting functions
>   * @setup_irq: pointer to initialize IRQ functions
>   */
>  struct mtk_pcie_soc {
>   bool need_fix_class_id;
> - bool has_msi;
>   struct pci_ops *ops;
>   int (*startup)(struct mtk_pcie_port *port);
>   int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
> @@ -161,7 +161,9 @@ struct mtk_pcie_soc {
>   * @lane: lane count
>   * @slot: port slot
>   * @irq_domain: legacy INTx IRQ domain
> + * @inner_domain: inner IRQ domain
>   * @msi_domain: MSI IRQ domain
> + * @lock: protect the msi_irq_in_use bitmap
>   * @msi_irq_in_use: bit map for assigned MSI IRQ
>   */
>  struct mtk_pcie_port {
> @@ -179,7 +181,9 @@ struct mtk_pcie_port {
>   u32 lane;
>   u32 slot;
>   struct irq_domain *irq_domain;
> + struct irq_domain *inner_domain;
>   struct irq_domain *msi_domain;
> + struct mutex lock;
>   DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
>  };
>  
> @@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
> mtk_pcie_port *port)
>   return 0;
>  }
>  
> -static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
> +static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  {
> - int msi;
> + struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
> + phys_addr_t addr;
>  
> - msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> - if (msi < MTK_MSI_IRQS_NUM)
> - set_bit(msi, port->msi_irq_in_use);
> - else
> - return -ENOSPC;
> + /* MT2712/MT7622 only support 32-bit MSI addresses */
> + addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
> + msg->address_hi = 0;
> + msg->address_lo = lower_32_bits(addr);
>  
> - return msi;
> + msg->data = data->hwirq;
> +
> + dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
> + (int)data->hwirq, msg->address_hi, msg->address_lo);
>  }
>  
> -static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long 
> hwirq)
> +static int mtk_msi_set_affinity(struct irq_data *irq_data,
> +const struct cpumask *mask, bool force)
>  {
> - clear_bit(hwirq, port->msi_irq_in_use);
> + return -EINVAL;
>  }
>  
> -static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
> -   struct pci_dev *pdev, struct msi_desc *desc)
> -{
> - struct mtk_pcie_port *port;
> - struct msi_msg msg;
> - unsigned int irq;
> - int hwirq;
> - phys_addr_t msg_addr;
> +static struct irq_chip mtk_msi_bottom_irq_chip = {
> + .name   = "MTK MSI",
> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> + .irq_set_affinity   = mtk_msi_set_affinity,
> + .irq_mask   = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
> +};
>  
> - port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
> - if (!port)
> - return -EINVAL;
> +static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
> virq,
> +  unsigned int nr_irqs, void *args)
> +{
> + struct mtk_pcie_port *port = domain->host_data;
> + unsigned long bit;
>  
> - hwirq = mtk_pcie_msi_alloc(port);
> - if (hwirq < 0)
> - return hwirq;
> + WARN_ON(nr_irqs != 1);
> + mutex_lock(>lock);
>  
> - irq = irq_create_mapping(port->msi_domain, hwirq);
> - if (!irq) {
> - mtk_pcie_msi_free(port, hwirq);
> - return -EINVAL;
> + bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> + if (bit >= MTK_MSI_IRQS_NUM) {
> + mutex_unlock(>lock);
> + return -ENOSPC;
>   }
>  
> - chip->dev = >dev;
> -
> - irq_set_msi_desc(irq, desc);
> + __set_bit(bit, port->msi_irq_in_use);
>  
> - /* MT2712/MT7622 only support 32-bit MSI addresses */
> - 

[PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-04-19 Thread honghui.zhang
From: Honghui Zhang 

Using irq_chip solution to setup IRQs for the consistent with IRQ framework.

Signed-off-by: Honghui Zhang 
---
 drivers/pci/host/pcie-mediatek.c | 192 +--
 1 file changed, 105 insertions(+), 87 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index c3dc549..1d9c6f1 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -11,8 +11,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -130,14 +132,12 @@ struct mtk_pcie_port;
 /**
  * struct mtk_pcie_soc - differentiate between host generations
  * @need_fix_class_id: whether this host's class ID needed to be fixed or not
- * @has_msi: whether this host supports MSI interrupts or not
  * @ops: pointer to configuration access functions
  * @startup: pointer to controller setting functions
  * @setup_irq: pointer to initialize IRQ functions
  */
 struct mtk_pcie_soc {
bool need_fix_class_id;
-   bool has_msi;
struct pci_ops *ops;
int (*startup)(struct mtk_pcie_port *port);
int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
@@ -161,7 +161,9 @@ struct mtk_pcie_soc {
  * @lane: lane count
  * @slot: port slot
  * @irq_domain: legacy INTx IRQ domain
+ * @inner_domain: inner IRQ domain
  * @msi_domain: MSI IRQ domain
+ * @lock: protect the msi_irq_in_use bitmap
  * @msi_irq_in_use: bit map for assigned MSI IRQ
  */
 struct mtk_pcie_port {
@@ -179,7 +181,9 @@ struct mtk_pcie_port {
u32 lane;
u32 slot;
struct irq_domain *irq_domain;
+   struct irq_domain *inner_domain;
struct irq_domain *msi_domain;
+   struct mutex lock;
DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
 };
 
@@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
mtk_pcie_port *port)
return 0;
 }
 
-static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
+static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 {
-   int msi;
+   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
+   phys_addr_t addr;
 
-   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
-   if (msi < MTK_MSI_IRQS_NUM)
-   set_bit(msi, port->msi_irq_in_use);
-   else
-   return -ENOSPC;
+   /* MT2712/MT7622 only support 32-bit MSI addresses */
+   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
+   msg->address_hi = 0;
+   msg->address_lo = lower_32_bits(addr);
 
-   return msi;
+   msg->data = data->hwirq;
+
+   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
+   (int)data->hwirq, msg->address_hi, msg->address_lo);
 }
 
-static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long hwirq)
+static int mtk_msi_set_affinity(struct irq_data *irq_data,
+  const struct cpumask *mask, bool force)
 {
-   clear_bit(hwirq, port->msi_irq_in_use);
+   return -EINVAL;
 }
 
-static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
- struct pci_dev *pdev, struct msi_desc *desc)
-{
-   struct mtk_pcie_port *port;
-   struct msi_msg msg;
-   unsigned int irq;
-   int hwirq;
-   phys_addr_t msg_addr;
+static struct irq_chip mtk_msi_bottom_irq_chip = {
+   .name   = "MTK MSI",
+   .irq_compose_msi_msg= mtk_compose_msi_msg,
+   .irq_set_affinity   = mtk_msi_set_affinity,
+   .irq_mask   = pci_msi_mask_irq,
+   .irq_unmask = pci_msi_unmask_irq,
+};
 
-   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
-   if (!port)
-   return -EINVAL;
+static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
virq,
+unsigned int nr_irqs, void *args)
+{
+   struct mtk_pcie_port *port = domain->host_data;
+   unsigned long bit;
 
-   hwirq = mtk_pcie_msi_alloc(port);
-   if (hwirq < 0)
-   return hwirq;
+   WARN_ON(nr_irqs != 1);
+   mutex_lock(>lock);
 
-   irq = irq_create_mapping(port->msi_domain, hwirq);
-   if (!irq) {
-   mtk_pcie_msi_free(port, hwirq);
-   return -EINVAL;
+   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
+   if (bit >= MTK_MSI_IRQS_NUM) {
+   mutex_unlock(>lock);
+   return -ENOSPC;
}
 
-   chip->dev = >dev;
-
-   irq_set_msi_desc(irq, desc);
+   __set_bit(bit, port->msi_irq_in_use);
 
-   /* MT2712/MT7622 only support 32-bit MSI addresses */
-   msg_addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
-   msg.address_hi = 0;
-   msg.address_lo = lower_32_bits(msg_addr);
-   msg.data = hwirq;
+   

[PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle

2018-04-19 Thread honghui.zhang
From: Honghui Zhang 

Using irq_chip solution to setup IRQs for the consistent with IRQ framework.

Signed-off-by: Honghui Zhang 
---
 drivers/pci/host/pcie-mediatek.c | 192 +--
 1 file changed, 105 insertions(+), 87 deletions(-)

diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
index c3dc549..1d9c6f1 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -11,8 +11,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -130,14 +132,12 @@ struct mtk_pcie_port;
 /**
  * struct mtk_pcie_soc - differentiate between host generations
  * @need_fix_class_id: whether this host's class ID needed to be fixed or not
- * @has_msi: whether this host supports MSI interrupts or not
  * @ops: pointer to configuration access functions
  * @startup: pointer to controller setting functions
  * @setup_irq: pointer to initialize IRQ functions
  */
 struct mtk_pcie_soc {
bool need_fix_class_id;
-   bool has_msi;
struct pci_ops *ops;
int (*startup)(struct mtk_pcie_port *port);
int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node);
@@ -161,7 +161,9 @@ struct mtk_pcie_soc {
  * @lane: lane count
  * @slot: port slot
  * @irq_domain: legacy INTx IRQ domain
+ * @inner_domain: inner IRQ domain
  * @msi_domain: MSI IRQ domain
+ * @lock: protect the msi_irq_in_use bitmap
  * @msi_irq_in_use: bit map for assigned MSI IRQ
  */
 struct mtk_pcie_port {
@@ -179,7 +181,9 @@ struct mtk_pcie_port {
u32 lane;
u32 slot;
struct irq_domain *irq_domain;
+   struct irq_domain *inner_domain;
struct irq_domain *msi_domain;
+   struct mutex lock;
DECLARE_BITMAP(msi_irq_in_use, MTK_MSI_IRQS_NUM);
 };
 
@@ -446,103 +450,122 @@ static int mtk_pcie_startup_port_v2(struct 
mtk_pcie_port *port)
return 0;
 }
 
-static int mtk_pcie_msi_alloc(struct mtk_pcie_port *port)
+static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 {
-   int msi;
+   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
+   phys_addr_t addr;
 
-   msi = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
-   if (msi < MTK_MSI_IRQS_NUM)
-   set_bit(msi, port->msi_irq_in_use);
-   else
-   return -ENOSPC;
+   /* MT2712/MT7622 only support 32-bit MSI addresses */
+   addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
+   msg->address_hi = 0;
+   msg->address_lo = lower_32_bits(addr);
 
-   return msi;
+   msg->data = data->hwirq;
+
+   dev_dbg(port->pcie->dev, "msi#%d address_hi %#x address_lo %#x\n",
+   (int)data->hwirq, msg->address_hi, msg->address_lo);
 }
 
-static void mtk_pcie_msi_free(struct mtk_pcie_port *port, unsigned long hwirq)
+static int mtk_msi_set_affinity(struct irq_data *irq_data,
+  const struct cpumask *mask, bool force)
 {
-   clear_bit(hwirq, port->msi_irq_in_use);
+   return -EINVAL;
 }
 
-static int mtk_pcie_msi_setup_irq(struct msi_controller *chip,
- struct pci_dev *pdev, struct msi_desc *desc)
-{
-   struct mtk_pcie_port *port;
-   struct msi_msg msg;
-   unsigned int irq;
-   int hwirq;
-   phys_addr_t msg_addr;
+static struct irq_chip mtk_msi_bottom_irq_chip = {
+   .name   = "MTK MSI",
+   .irq_compose_msi_msg= mtk_compose_msi_msg,
+   .irq_set_affinity   = mtk_msi_set_affinity,
+   .irq_mask   = pci_msi_mask_irq,
+   .irq_unmask = pci_msi_unmask_irq,
+};
 
-   port = mtk_pcie_find_port(pdev->bus, pdev->devfn);
-   if (!port)
-   return -EINVAL;
+static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
virq,
+unsigned int nr_irqs, void *args)
+{
+   struct mtk_pcie_port *port = domain->host_data;
+   unsigned long bit;
 
-   hwirq = mtk_pcie_msi_alloc(port);
-   if (hwirq < 0)
-   return hwirq;
+   WARN_ON(nr_irqs != 1);
+   mutex_lock(>lock);
 
-   irq = irq_create_mapping(port->msi_domain, hwirq);
-   if (!irq) {
-   mtk_pcie_msi_free(port, hwirq);
-   return -EINVAL;
+   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
+   if (bit >= MTK_MSI_IRQS_NUM) {
+   mutex_unlock(>lock);
+   return -ENOSPC;
}
 
-   chip->dev = >dev;
-
-   irq_set_msi_desc(irq, desc);
+   __set_bit(bit, port->msi_irq_in_use);
 
-   /* MT2712/MT7622 only support 32-bit MSI addresses */
-   msg_addr = virt_to_phys(port->base + PCIE_MSI_VECTOR);
-   msg.address_hi = 0;
-   msg.address_lo = lower_32_bits(msg_addr);
-   msg.data = hwirq;
+   mutex_unlock(>lock);
 
-   pci_write_msi_msg(irq, );
+