Re: [PATCH 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle
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
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
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
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
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
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
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
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
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
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
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
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
From: Honghui ZhangUsing 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
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, ); +