Re: [v1] PCI: mediatek: Remove MSI inner domain

2019-05-02 Thread Lorenzo Pieralisi
On Thu, Jan 31, 2019 at 08:49:57PM +0800, Jianjun Wang wrote:
> On Thu, 2019-01-31 at 09:44 +, Marc Zyngier wrote:
> > On 31/01/2019 09:19, Honghui Zhang wrote:
> > > On Tue, 2019-01-22 at 17:37 +0800, Jianjun Wang wrote:
> > >> There is no need to create the inner domain as a parent for MSI domian,
> > >> some feature has been implemented by MSI framework.
> > >>
> > >> Remove the inner domain and its irq chip, it will be more closer to
> > >> hardware implementation.
> > 
> > This is not about being closer to any HW implementation. This is about
> > having a uniform way to deal with MSI controllers, no matter how they
> > are implemented by the HW.
> > 
> > So maybe you could start by explaining what this is trying to achieve.
> > 
> > >>
> > > Hi, jianjun, I'm not quite familiar with the irq_chip framework, It was
> > > under Marc's great help with the first version of irq_chip solution
> > > code. I would like you to add him for the review.
> > > 
> > > Thanks.
> > > 
> > >> Signed-off-by: Jianjun Wang 
> > >> ---
> > >>  drivers/pci/controller/pcie-mediatek.c | 86 +++---
> > >>  1 file changed, 37 insertions(+), 49 deletions(-)
> > >>
> > >> diff --git a/drivers/pci/controller/pcie-mediatek.c 
> > >> b/drivers/pci/controller/pcie-mediatek.c
> > >> index 8d05df56158b..f996a9a6331f 100644
> > >> --- a/drivers/pci/controller/pcie-mediatek.c
> > >> +++ b/drivers/pci/controller/pcie-mediatek.c
> > >> @@ -169,7 +169,6 @@ struct mtk_pcie_soc {
> > >>   * @slot: port slot
> > >>   * @irq: GIC irq
> > >>   * @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
> > >> @@ -190,7 +189,6 @@ struct mtk_pcie_port {
> > >>  u32 slot;
> > >>  int irq;
> > >>  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);
> > >> @@ -418,22 +416,15 @@ static void mtk_msi_ack_irq(struct irq_data *data)
> > >>  u32 hwirq = data->hwirq;
> > >>  
> > >>  writel(1 << hwirq, port->base + PCIE_IMSI_STATUS);
> > >> +writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
> > >>  }
> > >>  
> > >> -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_ack= mtk_msi_ack_irq,
> > >> -};
> > >> -
> > >> -static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, 
> > >> unsigned int virq,
> > >> - unsigned int nr_irqs, void *args)
> > >> +static irq_hw_number_t mtk_pcie_msi_get_hwirq(struct msi_domain_info 
> > >> *info,
> > >> +  msi_alloc_info_t *arg)
> > >>  {
> > >> -struct mtk_pcie_port *port = domain->host_data;
> > >> -unsigned long bit;
> > >> +struct mtk_pcie_port *port = info->chip_data;
> > >> +irq_hw_number_t bit;
> > >>  
> > >> -WARN_ON(nr_irqs != 1);
> > >>  mutex_lock(>lock);
> > >>  
> > >>  bit = find_first_zero_bit(port->msi_irq_in_use, 
> > >> MTK_MSI_IRQS_NUM);
> > >> @@ -446,18 +437,14 @@ static int mtk_pcie_irq_domain_alloc(struct 
> > >> irq_domain *domain, unsigned int vir
> > >>  
> > >>  mutex_unlock(>lock);
> > >>  
> > >> -irq_domain_set_info(domain, virq, bit, _msi_bottom_irq_chip,
> > >> -domain->host_data, handle_edge_irq,
> > >> -NULL, NULL);
> > >> -
> > >> -return 0;
> > >> +return bit;
> > 
> > Why do you need to override the get_hwirq method? Using the generic
> > PCI/MSI version has the advantage of giving you a universal encoding
> > which makes debugging much easier.
> 
> Hi Marc,
> 
> In previous patch, we create a inner_domain as a parent for msi_domain,
> when we allocate a irq for MSI, the work flow of each domain will be the
> following:
> 
> inner_domain:
> 1. Allocated a irq bit from bitmap as this domain's hwirq;
> 2. Mapping with system virtual irq number;
> 3. Set irq chip and irq handler;
> 4. Send MSI message to EP.
> 
> msi_domain:
> 1. Calculate a hwirq;
> 2. Mapping with system virtual irq number;
> 3. Set irq chip which from info->chip and irq handler if defined in
> info.
> 4. Send MSI message to EP or trigger parent domain to send the message.
> 
> The last three steps looks similar, if we override the get_hwirq method
> and set irq chip and handler to info structure, MSI framework will do
> the rest of thing. I think it will be more simple and easy to understand
> the driver's work flow.
> 
> Further more, if we try to enhance the interrupt 

Re: [v1] PCI: mediatek: Remove MSI inner domain

2019-01-31 Thread Jianjun Wang
On Thu, 2019-01-31 at 09:44 +, Marc Zyngier wrote:
> On 31/01/2019 09:19, Honghui Zhang wrote:
> > On Tue, 2019-01-22 at 17:37 +0800, Jianjun Wang wrote:
> >> There is no need to create the inner domain as a parent for MSI domian,
> >> some feature has been implemented by MSI framework.
> >>
> >> Remove the inner domain and its irq chip, it will be more closer to
> >> hardware implementation.
> 
> This is not about being closer to any HW implementation. This is about
> having a uniform way to deal with MSI controllers, no matter how they
> are implemented by the HW.
> 
> So maybe you could start by explaining what this is trying to achieve.
> 
> >>
> > Hi, jianjun, I'm not quite familiar with the irq_chip framework, It was
> > under Marc's great help with the first version of irq_chip solution
> > code. I would like you to add him for the review.
> > 
> > Thanks.
> > 
> >> Signed-off-by: Jianjun Wang 
> >> ---
> >>  drivers/pci/controller/pcie-mediatek.c | 86 +++---
> >>  1 file changed, 37 insertions(+), 49 deletions(-)
> >>
> >> diff --git a/drivers/pci/controller/pcie-mediatek.c 
> >> b/drivers/pci/controller/pcie-mediatek.c
> >> index 8d05df56158b..f996a9a6331f 100644
> >> --- a/drivers/pci/controller/pcie-mediatek.c
> >> +++ b/drivers/pci/controller/pcie-mediatek.c
> >> @@ -169,7 +169,6 @@ struct mtk_pcie_soc {
> >>   * @slot: port slot
> >>   * @irq: GIC irq
> >>   * @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
> >> @@ -190,7 +189,6 @@ struct mtk_pcie_port {
> >>u32 slot;
> >>int irq;
> >>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);
> >> @@ -418,22 +416,15 @@ static void mtk_msi_ack_irq(struct irq_data *data)
> >>u32 hwirq = data->hwirq;
> >>  
> >>writel(1 << hwirq, port->base + PCIE_IMSI_STATUS);
> >> +  writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
> >>  }
> >>  
> >> -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_ack= mtk_msi_ack_irq,
> >> -};
> >> -
> >> -static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
> >> int virq,
> >> -   unsigned int nr_irqs, void *args)
> >> +static irq_hw_number_t mtk_pcie_msi_get_hwirq(struct msi_domain_info 
> >> *info,
> >> +msi_alloc_info_t *arg)
> >>  {
> >> -  struct mtk_pcie_port *port = domain->host_data;
> >> -  unsigned long bit;
> >> +  struct mtk_pcie_port *port = info->chip_data;
> >> +  irq_hw_number_t bit;
> >>  
> >> -  WARN_ON(nr_irqs != 1);
> >>mutex_lock(>lock);
> >>  
> >>bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> >> @@ -446,18 +437,14 @@ static int mtk_pcie_irq_domain_alloc(struct 
> >> irq_domain *domain, unsigned int vir
> >>  
> >>mutex_unlock(>lock);
> >>  
> >> -  irq_domain_set_info(domain, virq, bit, _msi_bottom_irq_chip,
> >> -  domain->host_data, handle_edge_irq,
> >> -  NULL, NULL);
> >> -
> >> -  return 0;
> >> +  return bit;
> 
> Why do you need to override the get_hwirq method? Using the generic
> PCI/MSI version has the advantage of giving you a universal encoding
> which makes debugging much easier.

Hi Marc,

In previous patch, we create a inner_domain as a parent for msi_domain,
when we allocate a irq for MSI, the work flow of each domain will be the
following:

inner_domain:
1. Allocated a irq bit from bitmap as this domain's hwirq;
2. Mapping with system virtual irq number;
3. Set irq chip and irq handler;
4. Send MSI message to EP.

msi_domain:
1. Calculate a hwirq;
2. Mapping with system virtual irq number;
3. Set irq chip which from info->chip and irq handler if defined in
info.
4. Send MSI message to EP or trigger parent domain to send the message.

The last three steps looks similar, if we override the get_hwirq method
and set irq chip and handler to info structure, MSI framework will do
the rest of thing. I think it will be more simple and easy to understand
the driver's work flow.

Further more, if we try to enhance the interrupt performance, such as
connect the MSI interrupt line to GIC directly in hardware, we will need
to set gic domain as the parent, in that case, there will be a lot of
work to do to replace the inner domain.

Thanks.
> 
> >>  }
> >>  
> >> -static void mtk_pcie_irq_domain_free(struct irq_domain *domain,
> >> -   unsigned int virq, unsigned int nr_irqs)
> >> +static void mtk_pcie_msi_free(struct irq_domain *domain,
> >> +struct 

Re: [v1] PCI: mediatek: Remove MSI inner domain

2019-01-31 Thread Marc Zyngier
On 31/01/2019 09:19, Honghui Zhang wrote:
> On Tue, 2019-01-22 at 17:37 +0800, Jianjun Wang wrote:
>> There is no need to create the inner domain as a parent for MSI domian,
>> some feature has been implemented by MSI framework.
>>
>> Remove the inner domain and its irq chip, it will be more closer to
>> hardware implementation.

This is not about being closer to any HW implementation. This is about
having a uniform way to deal with MSI controllers, no matter how they
are implemented by the HW.

So maybe you could start by explaining what this is trying to achieve.

>>
> Hi, jianjun, I'm not quite familiar with the irq_chip framework, It was
> under Marc's great help with the first version of irq_chip solution
> code. I would like you to add him for the review.
> 
> Thanks.
> 
>> Signed-off-by: Jianjun Wang 
>> ---
>>  drivers/pci/controller/pcie-mediatek.c | 86 +++---
>>  1 file changed, 37 insertions(+), 49 deletions(-)
>>
>> diff --git a/drivers/pci/controller/pcie-mediatek.c 
>> b/drivers/pci/controller/pcie-mediatek.c
>> index 8d05df56158b..f996a9a6331f 100644
>> --- a/drivers/pci/controller/pcie-mediatek.c
>> +++ b/drivers/pci/controller/pcie-mediatek.c
>> @@ -169,7 +169,6 @@ struct mtk_pcie_soc {
>>   * @slot: port slot
>>   * @irq: GIC irq
>>   * @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
>> @@ -190,7 +189,6 @@ struct mtk_pcie_port {
>>  u32 slot;
>>  int irq;
>>  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);
>> @@ -418,22 +416,15 @@ static void mtk_msi_ack_irq(struct irq_data *data)
>>  u32 hwirq = data->hwirq;
>>  
>>  writel(1 << hwirq, port->base + PCIE_IMSI_STATUS);
>> +writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
>>  }
>>  
>> -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_ack= mtk_msi_ack_irq,
>> -};
>> -
>> -static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned 
>> int virq,
>> - unsigned int nr_irqs, void *args)
>> +static irq_hw_number_t mtk_pcie_msi_get_hwirq(struct msi_domain_info *info,
>> +  msi_alloc_info_t *arg)
>>  {
>> -struct mtk_pcie_port *port = domain->host_data;
>> -unsigned long bit;
>> +struct mtk_pcie_port *port = info->chip_data;
>> +irq_hw_number_t bit;
>>  
>> -WARN_ON(nr_irqs != 1);
>>  mutex_lock(>lock);
>>  
>>  bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
>> @@ -446,18 +437,14 @@ static int mtk_pcie_irq_domain_alloc(struct irq_domain 
>> *domain, unsigned int vir
>>  
>>  mutex_unlock(>lock);
>>  
>> -irq_domain_set_info(domain, virq, bit, _msi_bottom_irq_chip,
>> -domain->host_data, handle_edge_irq,
>> -NULL, NULL);
>> -
>> -return 0;
>> +return bit;

Why do you need to override the get_hwirq method? Using the generic
PCI/MSI version has the advantage of giving you a universal encoding
which makes debugging much easier.

>>  }
>>  
>> -static void mtk_pcie_irq_domain_free(struct irq_domain *domain,
>> - unsigned int virq, unsigned int nr_irqs)
>> +static void mtk_pcie_msi_free(struct irq_domain *domain,
>> +  struct msi_domain_info *info, unsigned int virq)
>>  {
>>  struct irq_data *d = irq_domain_get_irq_data(domain, virq);
>> -struct mtk_pcie_port *port = irq_data_get_irq_chip_data(d);
>> +struct mtk_pcie_port *port = info->chip_data;
>>  
>>  mutex_lock(>lock);
>>  
>> @@ -468,46 +455,50 @@ static void mtk_pcie_irq_domain_free(struct irq_domain 
>> *domain,
>>  __clear_bit(d->hwirq, port->msi_irq_in_use);
>>  
>>  mutex_unlock(>lock);
>> -
>> -irq_domain_free_irqs_parent(domain, virq, nr_irqs);
>>  }
>>  
>> -static const struct irq_domain_ops msi_domain_ops = {
>> -.alloc  = mtk_pcie_irq_domain_alloc,
>> -.free   = mtk_pcie_irq_domain_free,
>> +static struct msi_domain_ops mtk_msi_domain_ops = {
>> +.get_hwirq  = mtk_pcie_msi_get_hwirq,
>> +.msi_free   = mtk_pcie_msi_free,
>>  };
>>  
>>  static struct irq_chip mtk_msi_irq_chip = {
>> -.name   = "MTK PCIe MSI",
>> -.irq_ack= irq_chip_ack_parent,
>> -.irq_mask   = pci_msi_mask_irq,
>> -.irq_unmask = pci_msi_unmask_irq,
>> +.name   = "MTK PCIe",
>> +.irq_compose_msi_msg= mtk_compose_msi_msg,
>> +.irq_write_msi_msg  = pci_msi_domain_write_msg,
>> +.irq_set_affinity   = 

Re: [v1] PCI: mediatek: Remove MSI inner domain

2019-01-31 Thread Honghui Zhang
On Tue, 2019-01-22 at 17:37 +0800, Jianjun Wang wrote:
> There is no need to create the inner domain as a parent for MSI domian,
> some feature has been implemented by MSI framework.
> 
> Remove the inner domain and its irq chip, it will be more closer to
> hardware implementation.
> 
Hi, jianjun, I'm not quite familiar with the irq_chip framework, It was
under Marc's great help with the first version of irq_chip solution
code. I would like you to add him for the review.

Thanks.

> Signed-off-by: Jianjun Wang 
> ---
>  drivers/pci/controller/pcie-mediatek.c | 86 +++---
>  1 file changed, 37 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-mediatek.c 
> b/drivers/pci/controller/pcie-mediatek.c
> index 8d05df56158b..f996a9a6331f 100644
> --- a/drivers/pci/controller/pcie-mediatek.c
> +++ b/drivers/pci/controller/pcie-mediatek.c
> @@ -169,7 +169,6 @@ struct mtk_pcie_soc {
>   * @slot: port slot
>   * @irq: GIC irq
>   * @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
> @@ -190,7 +189,6 @@ struct mtk_pcie_port {
>   u32 slot;
>   int irq;
>   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);
> @@ -418,22 +416,15 @@ static void mtk_msi_ack_irq(struct irq_data *data)
>   u32 hwirq = data->hwirq;
>  
>   writel(1 << hwirq, port->base + PCIE_IMSI_STATUS);
> + writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
>  }
>  
> -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_ack= mtk_msi_ack_irq,
> -};
> -
> -static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
> virq,
> -  unsigned int nr_irqs, void *args)
> +static irq_hw_number_t mtk_pcie_msi_get_hwirq(struct msi_domain_info *info,
> +   msi_alloc_info_t *arg)
>  {
> - struct mtk_pcie_port *port = domain->host_data;
> - unsigned long bit;
> + struct mtk_pcie_port *port = info->chip_data;
> + irq_hw_number_t bit;
>  
> - WARN_ON(nr_irqs != 1);
>   mutex_lock(>lock);
>  
>   bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
> @@ -446,18 +437,14 @@ static int mtk_pcie_irq_domain_alloc(struct irq_domain 
> *domain, unsigned int vir
>  
>   mutex_unlock(>lock);
>  
> - irq_domain_set_info(domain, virq, bit, _msi_bottom_irq_chip,
> - domain->host_data, handle_edge_irq,
> - NULL, NULL);
> -
> - return 0;
> + return bit;
>  }
>  
> -static void mtk_pcie_irq_domain_free(struct irq_domain *domain,
> -  unsigned int virq, unsigned int nr_irqs)
> +static void mtk_pcie_msi_free(struct irq_domain *domain,
> +   struct msi_domain_info *info, unsigned int virq)
>  {
>   struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> - struct mtk_pcie_port *port = irq_data_get_irq_chip_data(d);
> + struct mtk_pcie_port *port = info->chip_data;
>  
>   mutex_lock(>lock);
>  
> @@ -468,46 +455,50 @@ static void mtk_pcie_irq_domain_free(struct irq_domain 
> *domain,
>   __clear_bit(d->hwirq, port->msi_irq_in_use);
>  
>   mutex_unlock(>lock);
> -
> - irq_domain_free_irqs_parent(domain, virq, nr_irqs);
>  }
>  
> -static const struct irq_domain_ops msi_domain_ops = {
> - .alloc  = mtk_pcie_irq_domain_alloc,
> - .free   = mtk_pcie_irq_domain_free,
> +static struct msi_domain_ops mtk_msi_domain_ops = {
> + .get_hwirq  = mtk_pcie_msi_get_hwirq,
> + .msi_free   = mtk_pcie_msi_free,
>  };
>  
>  static struct irq_chip mtk_msi_irq_chip = {
> - .name   = "MTK PCIe MSI",
> - .irq_ack= irq_chip_ack_parent,
> - .irq_mask   = pci_msi_mask_irq,
> - .irq_unmask = pci_msi_unmask_irq,
> + .name   = "MTK PCIe",
> + .irq_compose_msi_msg= mtk_compose_msi_msg,
> + .irq_write_msi_msg  = pci_msi_domain_write_msg,
> + .irq_set_affinity   = mtk_msi_set_affinity,
> + .irq_ack= mtk_msi_ack_irq,
> + .irq_mask   = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
>  };
>  
>  static struct msi_domain_info mtk_msi_domain_info = {
> - .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
> -MSI_FLAG_PCI_MSIX),
> - .chip   = _msi_irq_chip,
> + .flags  = (MSI_FLAG_USE_DEF_DOM_OPS |
> +MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_PCI_MSIX),
> + 

[v1] PCI: mediatek: Remove MSI inner domain

2019-01-22 Thread Jianjun Wang
There is no need to create the inner domain as a parent for MSI domian,
some feature has been implemented by MSI framework.

Remove the inner domain and its irq chip, it will be more closer to
hardware implementation.

Signed-off-by: Jianjun Wang 
---
 drivers/pci/controller/pcie-mediatek.c | 86 +++---
 1 file changed, 37 insertions(+), 49 deletions(-)

diff --git a/drivers/pci/controller/pcie-mediatek.c 
b/drivers/pci/controller/pcie-mediatek.c
index 8d05df56158b..f996a9a6331f 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -169,7 +169,6 @@ struct mtk_pcie_soc {
  * @slot: port slot
  * @irq: GIC irq
  * @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
@@ -190,7 +189,6 @@ struct mtk_pcie_port {
u32 slot;
int irq;
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);
@@ -418,22 +416,15 @@ static void mtk_msi_ack_irq(struct irq_data *data)
u32 hwirq = data->hwirq;
 
writel(1 << hwirq, port->base + PCIE_IMSI_STATUS);
+   writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
 }
 
-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_ack= mtk_msi_ack_irq,
-};
-
-static int mtk_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int 
virq,
-unsigned int nr_irqs, void *args)
+static irq_hw_number_t mtk_pcie_msi_get_hwirq(struct msi_domain_info *info,
+ msi_alloc_info_t *arg)
 {
-   struct mtk_pcie_port *port = domain->host_data;
-   unsigned long bit;
+   struct mtk_pcie_port *port = info->chip_data;
+   irq_hw_number_t bit;
 
-   WARN_ON(nr_irqs != 1);
mutex_lock(>lock);
 
bit = find_first_zero_bit(port->msi_irq_in_use, MTK_MSI_IRQS_NUM);
@@ -446,18 +437,14 @@ static int mtk_pcie_irq_domain_alloc(struct irq_domain 
*domain, unsigned int vir
 
mutex_unlock(>lock);
 
-   irq_domain_set_info(domain, virq, bit, _msi_bottom_irq_chip,
-   domain->host_data, handle_edge_irq,
-   NULL, NULL);
-
-   return 0;
+   return bit;
 }
 
-static void mtk_pcie_irq_domain_free(struct irq_domain *domain,
-unsigned int virq, unsigned int nr_irqs)
+static void mtk_pcie_msi_free(struct irq_domain *domain,
+ struct msi_domain_info *info, unsigned int virq)
 {
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-   struct mtk_pcie_port *port = irq_data_get_irq_chip_data(d);
+   struct mtk_pcie_port *port = info->chip_data;
 
mutex_lock(>lock);
 
@@ -468,46 +455,50 @@ static void mtk_pcie_irq_domain_free(struct irq_domain 
*domain,
__clear_bit(d->hwirq, port->msi_irq_in_use);
 
mutex_unlock(>lock);
-
-   irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
-static const struct irq_domain_ops msi_domain_ops = {
-   .alloc  = mtk_pcie_irq_domain_alloc,
-   .free   = mtk_pcie_irq_domain_free,
+static struct msi_domain_ops mtk_msi_domain_ops = {
+   .get_hwirq  = mtk_pcie_msi_get_hwirq,
+   .msi_free   = mtk_pcie_msi_free,
 };
 
 static struct irq_chip mtk_msi_irq_chip = {
-   .name   = "MTK PCIe MSI",
-   .irq_ack= irq_chip_ack_parent,
-   .irq_mask   = pci_msi_mask_irq,
-   .irq_unmask = pci_msi_unmask_irq,
+   .name   = "MTK PCIe",
+   .irq_compose_msi_msg= mtk_compose_msi_msg,
+   .irq_write_msi_msg  = pci_msi_domain_write_msg,
+   .irq_set_affinity   = mtk_msi_set_affinity,
+   .irq_ack= mtk_msi_ack_irq,
+   .irq_mask   = pci_msi_mask_irq,
+   .irq_unmask = pci_msi_unmask_irq,
 };
 
 static struct msi_domain_info mtk_msi_domain_info = {
-   .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-  MSI_FLAG_PCI_MSIX),
-   .chip   = _msi_irq_chip,
+   .flags  = (MSI_FLAG_USE_DEF_DOM_OPS |
+  MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_PCI_MSIX),
+   .ops= _msi_domain_ops,
+   .chip   = _msi_irq_chip,
+   .handler= handle_edge_irq,
+   .handler_name   = "MSI",
 };
 
 static int mtk_pcie_allocate_msi_domains(struct mtk_pcie_port *port)
 {
-   struct fwnode_handle *fwnode = 
of_node_to_fwnode(port->pcie->dev->of_node);
+   struct device *dev = port->pcie->dev;
+   struct