add new irq api to pcie-designware
Subsystems (3)
cover add new irq api to pcie-designware
This patch series adds the new interrupt api to pcie-designware make it possible to use features like MSIX.
The work consisted of adapting the pcie-designware-host and each SoC specific driver.
Joao Pinto (8):
pci: adding new irq api to pci-designware
pci: exynos SoC driver adapted to new irq API
pci: imx6 SoC driver adapted to new irq API
pci: artpec6 SoC driver adapted to new irq API
pci: generic PCIe DW driver adapted to new irq API
pci: qcom SoC driver adapted to new irq API
pci: keystone SoC driver adapted to new irq API
pci: removing old irq api from pcie-designware
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 97 +-------- drivers/pci/dwc/pci-keystone.c | 1 + drivers/pci/dwc/pci-keystone.h | 4 +- drivers/pci/dwc/pci-layerscape.c | 4 +- drivers/pci/dwc/pcie-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 349 ++++++++++++++++++--------------- drivers/pci/dwc/pcie-designware-plat.c | 15 -- drivers/pci/dwc/pcie-designware.h | 8 +- drivers/pci/dwc/pcie-qcom.c | 15 -- 11 files changed, 205 insertions(+), 342 deletions(-)
Signature · 1 line
2.9.3
RFC 1/8 pci: adding new irq api to pci-designware
This patch adds the new interrupt api to pecie-designware, keeping the old one. A define was added to toggle between the two apis (for testing purposes).
--- drivers/pci/dwc/pcie-designware-host.c | 241 ++++++++++++++++++++++++++++++++- drivers/pci/dwc/pcie-designware.h | 5 + 2 files changed, 244 insertions(+), 2 deletions(-)
drivers/pci/dwc/pcie-designware-host.c +239 -2
@@ -11,6 +11,7 @@* published by the Free Software Foundation. */ +#include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/of_address.h> #include <linux/of_pci.h>
@@ -19,6 +20,9 @@#include "pcie-designware.h" +/* Temporary: Activate to use new IRQ API */ +/*#define CONFIG_PCIEDW_NEW_IRQ_API*/ +static struct pci_ops dw_pcie_ops; static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
@@ -45,6 +49,7 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,return dw_pcie_write (pci->dbi_base + where, size, val); } +#ifndef CONFIG_PCIEDW_NEW_IRQ_API static struct irq_chip dw_msi_irq_chip = { .name ="PCI-MSI" , .irq_enable = pci_msi_unmask_irq,
@@ -52,6 +57,29 @@ static struct irq_chip dw_msi_irq_chip = { .irq_mask = pci_msi_mask_irq, .irq_unmask = pci_msi_unmask_irq, }; +#else +static void dw_msi_mask_irq (struct irq_data *d) { +pci_msi_mask_irq (d); +irq_chip_mask_parent (d); +} + +static void dw_msi_unmask_irq (struct irq_data *d) { +pci_msi_unmask_irq (d); +irq_chip_unmask_parent (d); +} + +static struct irq_chip dw_msi_irq_chip = { + .name ="PCI-MSI" , + .irq_mask = dw_msi_mask_irq, + .irq_unmask = dw_msi_unmask_irq, +}; + +static struct msi_domain_info dw_pcie_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS |MSI_FLAG_USE_DEF_CHIP_OPS | +MSI_FLAG_PCI_MSIX ), + .chip = &dw_msi_irq_chip, +}; +#endif /* MSI int handler */ irqreturn_t dw_handle_msi_irq (struct pcie_port *pp)
@@ -81,6 +109,190 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)return ret; } +#ifdef CONFIG_PCIEDW_NEW_IRQ_API +/* Chained MSI interrupt service routine */ +static void dw_chained_msi_isr (struct irq_desc *desc) +{ +struct irq_chip *chip =irq_desc_get_chip (desc); +struct pcie_port *pp; +struct dw_pcie *pci; + +chained_irq_enter (chip, desc); + pci =irq_desc_get_handler_data (desc); + pp = &pci->pp; + +dw_handle_msi_irq (pp); + +chained_irq_exit (chip, desc); +} + +static void dw_pci_setup_msi_msg (struct irq_data *data,struct msi_msg *msg) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +u64 msi_target; + +if (pp->ops->get_msi_addr) + msi_target = pp->ops->get_msi_addr (pp); +else + msi_target =virt_to_phys ((void *)pp->msi_data); + + msg->address_lo = (u32)(msi_target &0xffffffff ); + msg->address_hi = (u32)(msi_target >>32 &0xffffffff ); + +if (pp->ops->get_msi_data) + msg->data = pp->ops->get_msi_data (pp, data->hwirq); +else + msg->data = data->hwirq; + +dev_dbg (pci->dev,"msi#%d address_hi %#x address_lo %#x\n" , + (int )data->hwirq, msg->address_hi, msg->address_lo); +} + +static int dw_pci_msi_set_affinity (struct irq_data *irq_data, +const struct cpumask *mask,bool force) +{ +return -EINVAL ; +} + +static void dw_pci_bottom_mask (struct irq_data *data) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +unsigned int res, bit, val; + +mutex_lock (&pp->lock); + +if (pp->ops->msi_clear_irq) + pp->ops->msi_clear_irq (pp, data->hwirq); +else { + res = (data->hwirq /32 ) *12 ; + bit = data->hwirq %32 ; + +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , &val); + val &= ~(1 << bit); +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , val); + } + +mutex_unlock (&pp->lock); +} + +static void dw_pci_bottom_unmask (struct irq_data *data) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +unsigned int res, bit, val; + +mutex_lock (&pp->lock); + +if (pp->ops->msi_set_irq) + pp->ops->msi_set_irq (pp, data->hwirq); +else { + res = (data->hwirq /32 ) *12 ; + bit = data->hwirq %32 ; + +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , &val); + val |=1 << bit; +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , val); + } + +mutex_unlock (&pp->lock); +} + +static struct irq_chip dw_pci_msi_bottom_irq_chip = { + .name ="DWPCI-MSI" , + .irq_compose_msi_msg = dw_pci_setup_msi_msg, + .irq_set_affinity = dw_pci_msi_set_affinity, + .irq_mask = dw_pci_bottom_mask, + .irq_unmask = dw_pci_bottom_unmask, +}; + +static int dw_pcie_irq_domain_alloc (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs, +void *args) +{ +struct dw_pcie *pci = domain->host_data; +struct pcie_port *pp = &pci->pp; +unsigned long bit; + +mutex_lock (&pp->lock); + +WARN_ON (nr_irqs !=1 ); + + bit =find_first_zero_bit (pp->msi_irq_in_use, pp->num_vectors); +if (bit >= pp->num_vectors) { +mutex_unlock (&pp->lock); +return -ENOSPC ; + } + +set_bit (bit, pp->msi_irq_in_use); + +mutex_unlock (&pp->lock); + +irq_domain_set_info (domain, virq, bit, &dw_pci_msi_bottom_irq_chip, + domain->host_data, handle_simple_irq, +NULL ,NULL ); + +return 0 ; +} + +static void dw_pcie_irq_domain_free (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs) +{ +struct irq_data *data =irq_domain_get_irq_data (domain, virq); +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; + +mutex_lock (&pp->lock); + +if (!test_bit (data->hwirq, pp->msi_irq_in_use)) +dev_err (pci->dev,"trying to free unused MSI#%lu\n" , + data->hwirq); +else +__clear_bit (data->hwirq, pp->msi_irq_in_use); + +mutex_unlock (&pp->lock); +} + +static const struct irq_domain_ops dw_pcie_msi_domain_ops = { + .alloc = dw_pcie_irq_domain_alloc, + .free = dw_pcie_irq_domain_free, +}; + +int dw_pcie_allocate_domains (struct dw_pcie *pci) +{ +struct pcie_port *pp = &pci->pp; +struct fwnode_handle *fwnode =of_node_to_fwnode (pci->dev->of_node); + + pp->irq_domain =irq_domain_add_linear (NULL , pp->num_vectors, + &dw_pcie_msi_domain_ops, pci); +if (!pp->irq_domain) { +dev_err (pci->dev,"failed to create IRQ domain\n" ); +return -ENOMEM ; + } + + pp->msi_domain =pci_msi_create_irq_domain (fwnode, + &dw_pcie_msi_domain_info, + pp->irq_domain); +if (!pp->msi_domain) { +dev_err (pci->dev,"failed to create MSI domain\n" ); +irq_domain_remove (pp->irq_domain); +return -ENOMEM ; + } + +return 0 ; +} + +void dw_pcie_free_msi (struct pcie_port *pp) +{ +irq_set_chained_handler (pp->msi_irq,NULL ); +irq_set_handler_data (pp->msi_irq,NULL ); + +irq_domain_remove (pp->msi_domain); +irq_domain_remove (pp->irq_domain); +} +#endif +void dw_pcie_msi_init (struct pcie_port *pp) {u64 msi_target;
@@ -279,11 +491,16 @@ int dw_pcie_host_init(struct pcie_port *pp)struct device *dev = pci->dev;struct device_node *np = dev->of_node;struct platform_device *pdev =to_platform_device (dev); +struct resource_entry *win, *tmp;struct pci_bus *bus, *child;struct resource *cfg_res; -int i, ret; +#ifndef CONFIG_PCIEDW_NEW_IRQ_API +int i; +#endif +int ret;LIST_HEAD (res); -struct resource_entry *win, *tmp; + +mutex_init (&pci->pp.lock); cfg_res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"config" );if (cfg_res) {
@@ -378,6 +595,12 @@ int dw_pcie_host_init(struct pcie_port *pp)if (IS_ENABLED (CONFIG_PCI_MSI )) {if (!pp->ops->msi_host_init) { + ret =of_property_read_u32 (np,"num-vectors" , + &pp->num_vectors); +if (ret) + pp->num_vectors =1 ; + +#ifndef CONFIG_PCIEDW_NEW_IRQ_API pp->irq_domain =irq_domain_add_linear (dev->of_node,MAX_MSI_IRQS , &msi_domain_ops, &dw_pcie_msi_chip);
@@ -389,6 +612,15 @@ int dw_pcie_host_init(struct pcie_port *pp)for (i =0 ; i <MAX_MSI_IRQS ; i++)irq_create_mapping (pp->irq_domain, i); +#else + ret =dw_pcie_allocate_domains (pci); +if (ret) + goto error; + +irq_set_chained_handler_and_data (pci->pp.msi_irq, + dw_chained_msi_isr, + pci); +#endif }else { ret = pp->ops->msi_host_init (pp, &dw_pcie_msi_chip);if (ret <0 )
@@ -400,6 +632,7 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->ops->host_init (pp); pp->root_bus_nr = pp->busn->start; +#ifndef CONFIG_PCIEDW_NEW_IRQ_API if (IS_ENABLED (CONFIG_PCI_MSI )) { bus = pci_scan_root_bus_msi(dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res,
@@ -408,6 +641,10 @@ int dw_pcie_host_init(struct pcie_port *pp) } else bus =pci_scan_root_bus (dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res); +#else + bus =pci_scan_root_bus (dev, pp->root_bus_nr, &dw_pcie_ops, + pp, &res); +#endif if (!bus) { ret = -ENOMEM ; goto error;
drivers/pci/dwc/pcie-designware.h +5 -0
@@ -165,7 +165,10 @@ struct pcie_port {struct dw_pcie_host_ops *ops;int msi_irq;struct irq_domain *irq_domain; +struct irq_domain *msi_domain;unsigned long msi_data; +u32 num_vectors; +struct mutex lock;DECLARE_BITMAP (msi_irq_in_use,MAX_MSI_IRQS ); };
@@ -282,8 +285,10 @@ static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)#ifdef CONFIG_PCIE_DW_HOST irqreturn_t dw_handle_msi_irq (struct pcie_port *pp);void dw_pcie_msi_init (struct pcie_port *pp); +void dw_pcie_free_msi (struct pcie_port *pp);void dw_pcie_setup_rc (struct pcie_port *pp);int dw_pcie_host_init (struct pcie_port *pp); +int dw_pcie_allocate_domains (struct dw_pcie *pci);#else static inline irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) {
Signature · 1 line
2.9.3
Re: [RFC 1/8] pci: adding new irq api to pci-designware
Am Freitag, den 12.05.2017, 17:56 +0100 schrieb Joao Pinto:
Quoted 13 lines
This patch adds the new interrupt api to pecie-designware, keeping the old one. A define was added to toggle between the two apis (for testing purposes).
Signed-off-by Joao Pinto <[email protected]>--- drivers/pci/dwc/pcie-designware-host.c | 241 ++++++++++++++++++++++++++++++++- drivers/pci/dwc/pcie-designware.h | 5 + 2 files changed, 244 insertions(+), 2 deletions(-)drivers/pci/dwc/pcie-designware-host.c +0
-0
[...]
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 220
Quoted 11 lines
drivers/pci/dwc/pcie-designware-host.c +11
-0+static int dw_pcie_irq_domain_alloc (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs, +void *args) +{ +struct dw_pcie *pci = domain->host_data; +struct pcie_port *pp = &pci->pp; +unsigned long bit; + +mutex_lock (&pp->lock); + +WARN_ON (nr_irqs !=1 );
So the new API doesn't support multi MSI, where we need more than a single contiguous MSI in a range? If this is the case then this change is breaking real use-cases that work today.
Regards,
Luvas
Re: [RFC 1/8] pci: adding new irq api to pci-designware
In reply to Joao PintoJoao,
You seem to have dropped a number of things I had mentioned on my previous review of this patch. See below:
Quoted 22 lines · Joao Pinto
This patch adds the new interrupt api to pecie-designware, keeping the old one. A define was added to toggle between the two apis (for testing purposes).
Signed-off-by Joao Pinto <[email protected]>--- drivers/pci/dwc/pcie-designware-host.c | 241 ++++++++++++++++++++++++++++++++- drivers/pci/dwc/pcie-designware.h | 5 + 2 files changed, 244 insertions(+), 2 deletions(-)drivers/pci/dwc/pcie-designware-host.c +1
-0@@ -11,6 +11,7 @@* published by the Free Software Foundation. */ +#include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/of_address.h> #include <linux/of_pci.h>
drivers/pci/dwc/pcie-designware-host.c line 24
Quoted 5 lines
drivers/pci/dwc/pcie-designware-host.c +2
-0@@ -19,6 +20,9 @@#include "pcie-designware.h" +/* Temporary: Activate to use new IRQ API */ +/*#define CONFIG_PCIEDW_NEW_IRQ_API*/
You should be able to support both APIs at the same time until the last patch, without relying on a kernel configuration (we still want to be able to boot a single kernel that works both with the old and new methods).
Quoted 66 lines
drivers/pci/dwc/pcie-designware-host.c +45
-0+static struct pci_ops dw_pcie_ops; static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,@@ -45,6 +49,7 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,return dw_pcie_write (pci->dbi_base + where, size, val); } +#ifndef CONFIG_PCIEDW_NEW_IRQ_API static struct irq_chip dw_msi_irq_chip = { .name ="PCI-MSI" , .irq_enable = pci_msi_unmask_irq,@@ -52,6 +57,29 @@ static struct irq_chip dw_msi_irq_chip = { .irq_mask = pci_msi_mask_irq, .irq_unmask = pci_msi_unmask_irq, }; +#else +static void dw_msi_mask_irq (struct irq_data *d) { +pci_msi_mask_irq (d); +irq_chip_mask_parent (d); +} + +static void dw_msi_unmask_irq (struct irq_data *d) { +pci_msi_unmask_irq (d); +irq_chip_unmask_parent (d); +} + +static struct irq_chip dw_msi_irq_chip = { + .name ="PCI-MSI" , + .irq_mask = dw_msi_mask_irq, + .irq_unmask = dw_msi_unmask_irq, +}; + +static struct msi_domain_info dw_pcie_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS |MSI_FLAG_USE_DEF_CHIP_OPS | +MSI_FLAG_PCI_MSIX ), + .chip = &dw_msi_irq_chip, +}; +#endif /* MSI int handler */ irqreturn_t dw_handle_msi_irq (struct pcie_port *pp)@@ -81,6 +109,190 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)return ret; } +#ifdef CONFIG_PCIEDW_NEW_IRQ_API +/* Chained MSI interrupt service routine */ +static void dw_chained_msi_isr (struct irq_desc *desc) +{ +struct irq_chip *chip =irq_desc_get_chip (desc); +struct pcie_port *pp; +struct dw_pcie *pci; + +chained_irq_enter (chip, desc); + pci =irq_desc_get_handler_data (desc); + pp = &pci->pp; + +dw_handle_msi_irq (pp); + +chained_irq_exit (chip, desc); +} + +static void dw_pci_setup_msi_msg (struct irq_data *data,struct msi_msg *msg) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data);
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 141
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+struct pcie_port *pp = &pci->pp; +u64 msi_target; + +if (pp->ops->get_msi_addr) + msi_target = pp->ops->get_msi_addr (pp); +else + msi_target =virt_to_phys ((void *)pp->msi_data); + + msg->address_lo = (u32)(msi_target &0xffffffff ); + msg->address_hi = (u32)(msi_target >>32 &0xffffffff );
Use lower_32_bit/upper_32_bit macros.
Quoted 13 lines
drivers/pci/dwc/pcie-designware-host.c +13
-0+ +if (pp->ops->get_msi_data) + msg->data = pp->ops->get_msi_data (pp, data->hwirq); +else + msg->data = data->hwirq; + +dev_dbg (pci->dev,"msi#%d address_hi %#x address_lo %#x\n" , + (int )data->hwirq, msg->address_hi, msg->address_lo); +} + +static int dw_pci_msi_set_affinity (struct irq_data *irq_data, +const struct cpumask *mask,bool force) +{
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 164
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+return -EINVAL ; +} + +static void dw_pci_bottom_mask (struct irq_data *data) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +unsigned int res, bit, val; + +mutex_lock (&pp->lock);
This is wrong. You can also end-up here from interrupt context, so you need an spin_lock_irqsave().
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 167
Quoted 3 lines
drivers/pci/dwc/pcie-designware-host.c +3
-0+ +if (pp->ops->msi_clear_irq) + pp->ops->msi_clear_irq (pp, data->hwirq);
Why do you need this? Can you have alternative implementations of mask/unmask?
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 172
Quoted 5 lines
drivers/pci/dwc/pcie-designware-host.c +5
-0+else { + res = (data->hwirq /32 ) *12 ; + bit = data->hwirq %32 ; + +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , &val);
No use reading back from the HW. Just maintain a cached version in your private structure and just use that.
Quoted 17 lines
drivers/pci/dwc/pcie-designware-host.c +17
-0+ val &= ~(1 << bit); +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , val); + } + +mutex_unlock (&pp->lock); +} + +static void dw_pci_bottom_unmask (struct irq_data *data) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +unsigned int res, bit, val; + +mutex_lock (&pp->lock); + +if (pp->ops->msi_set_irq) + pp->ops->msi_set_irq (pp, data->hwirq);
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 199
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+else { + res = (data->hwirq /32 ) *12 ; + bit = data->hwirq %32 ; + +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , &val); + val |=1 << bit; +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , val); + } + +mutex_unlock (&pp->lock);
Same comments.
Quoted 21 lines
drivers/pci/dwc/pcie-designware-host.c +21
-0+} + +static struct irq_chip dw_pci_msi_bottom_irq_chip = { + .name ="DWPCI-MSI" , + .irq_compose_msi_msg = dw_pci_setup_msi_msg, + .irq_set_affinity = dw_pci_msi_set_affinity, + .irq_mask = dw_pci_bottom_mask, + .irq_unmask = dw_pci_bottom_unmask, +}; + +static int dw_pcie_irq_domain_alloc (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs, +void *args) +{ +struct dw_pcie *pci = domain->host_data; +struct pcie_port *pp = &pci->pp; +unsigned long bit; + +mutex_lock (&pp->lock); + +WARN_ON (nr_irqs !=1 );
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 230
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+ + bit =find_first_zero_bit (pp->msi_irq_in_use, pp->num_vectors); +if (bit >= pp->num_vectors) { +mutex_unlock (&pp->lock); +return -ENOSPC ; + } + +set_bit (bit, pp->msi_irq_in_use); + +mutex_unlock (&pp->lock);
As mentioned by Lucas, you probably want to support Multi-MSI.
Quoted 14 lines
drivers/pci/dwc/pcie-designware-host.c +14
-0+ +irq_domain_set_info (domain, virq, bit, &dw_pci_msi_bottom_irq_chip, + domain->host_data, handle_simple_irq, +NULL ,NULL ); + +return 0 ; +} + +static void dw_pcie_irq_domain_free (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs) +{ +struct irq_data *data =irq_domain_get_irq_data (domain, virq); +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp;
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 254
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+ +mutex_lock (&pp->lock); + +if (!test_bit (data->hwirq, pp->msi_irq_in_use)) +dev_err (pci->dev,"trying to free unused MSI#%lu\n" , + data->hwirq); +else +__clear_bit (data->hwirq, pp->msi_irq_in_use); + +mutex_unlock (&pp->lock);
Same here.
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +4
-0+} + +static const struct irq_domain_ops dw_pcie_msi_domain_ops = { + .alloc = dw_pcie_irq_domain_alloc,
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 268
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+ .free = dw_pcie_irq_domain_free, +}; + +int dw_pcie_allocate_domains (struct dw_pcie *pci) +{ +struct pcie_port *pp = &pci->pp; +struct fwnode_handle *fwnode =of_node_to_fwnode (pci->dev->of_node); + + pp->irq_domain =irq_domain_add_linear (NULL , pp->num_vectors, + &dw_pcie_msi_domain_ops, pci);
Please use irq_domain_create_linear and pass the fwnode there as well.
Quoted 114 lines
drivers/pci/dwc/pcie-designware-host.c +54
-2+if (!pp->irq_domain) { +dev_err (pci->dev,"failed to create IRQ domain\n" ); +return -ENOMEM ; + } + + pp->msi_domain =pci_msi_create_irq_domain (fwnode, + &dw_pcie_msi_domain_info, + pp->irq_domain); +if (!pp->msi_domain) { +dev_err (pci->dev,"failed to create MSI domain\n" ); +irq_domain_remove (pp->irq_domain); +return -ENOMEM ; + } + + return 0; +} + +void dw_pcie_free_msi (struct pcie_port *pp) +{ +irq_set_chained_handler (pp->msi_irq,NULL ); +irq_set_handler_data (pp->msi_irq,NULL ); + +irq_domain_remove (pp->msi_domain); +irq_domain_remove (pp->irq_domain); +} +#endif +void dw_pcie_msi_init (struct pcie_port *pp) {u64 msi_target;@@ -279,11 +491,16 @@ int dw_pcie_host_init(struct pcie_port *pp)struct device *dev = pci->dev;struct device_node *np = dev->of_node;struct platform_device *pdev =to_platform_device (dev); +struct resource_entry *win, *tmp;struct pci_bus *bus, *child;struct resource *cfg_res; -int i, ret; +#ifndef CONFIG_PCIEDW_NEW_IRQ_API +int i; +#endif +int ret;LIST_HEAD (res); -struct resource_entry *win, *tmp; + +mutex_init (&pci->pp.lock); cfg_res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"config" );if (cfg_res) {@@ -378,6 +595,12 @@ int dw_pcie_host_init(struct pcie_port *pp)if (IS_ENABLED (CONFIG_PCI_MSI )) {if (!pp->ops->msi_host_init) { + ret =of_property_read_u32 (np,"num-vectors" , + &pp->num_vectors); +if (ret) + pp->num_vectors =1 ; + +#ifndef CONFIG_PCIEDW_NEW_IRQ_API pp->irq_domain =irq_domain_add_linear (dev->of_node,MAX_MSI_IRQS , &msi_domain_ops, &dw_pcie_msi_chip);@@ -389,6 +612,15 @@ int dw_pcie_host_init(struct pcie_port *pp)for (i =0 ; i <MAX_MSI_IRQS ; i++)irq_create_mapping (pp->irq_domain, i); +#else + ret =dw_pcie_allocate_domains (pci); +if (ret) + goto error; + +irq_set_chained_handler_and_data (pci->pp.msi_irq, + dw_chained_msi_isr, + pci); +#endif }else { ret = pp->ops->msi_host_init (pp, &dw_pcie_msi_chip);if (ret <0 )@@ -400,6 +632,7 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->ops->host_init (pp); pp->root_bus_nr = pp->busn->start; +#ifndef CONFIG_PCIEDW_NEW_IRQ_API if (IS_ENABLED (CONFIG_PCI_MSI )) { bus = pci_scan_root_bus_msi(dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res,@@ -408,6 +641,10 @@ int dw_pcie_host_init(struct pcie_port *pp) } else bus =pci_scan_root_bus (dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res); +#else + bus =pci_scan_root_bus (dev, pp->root_bus_nr, &dw_pcie_ops, + pp, &res); +#endif if (!bus) { ret = -ENOMEM ; goto error;drivers/pci/dwc/pcie-designware.h +3
-0@@ -165,7 +165,10 @@ struct pcie_port {struct dw_pcie_host_ops *ops;int msi_irq;struct irq_domain *irq_domain; +struct irq_domain *msi_domain;unsigned long msi_data; +u32 num_vectors; +struct mutex lock;DECLARE_BITMAP (msi_irq_in_use,MAX_MSI_IRQS ); };
drivers/pci/dwc/pcie-designware.h static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg) · line 294
Quoted 10 lines
drivers/pci/dwc/pcie-designware.h +2
-0@@ -282,8 +285,10 @@ static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)#ifdef CONFIG_PCIE_DW_HOST irqreturn_t dw_handle_msi_irq (struct pcie_port *pp);void dw_pcie_msi_init (struct pcie_port *pp); +void dw_pcie_free_msi (struct pcie_port *pp);void dw_pcie_setup_rc (struct pcie_port *pp);int dw_pcie_host_init (struct pcie_port *pp); +int dw_pcie_allocate_domains (struct dw_pcie *pci);#else static inline irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) {
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Re: [RFC 1/8] pci: adding new irq api to pci-designware
Hi Mark and Lucas,
Às 6:36 PM de 5/12/2017, Marc Zyngier escreveu:
Quoted 29 lines
Joao,
You seem to have dropped a number of things I had mentioned on my previous review of this patch. See below:
Quoted 23 lines · Joao Pinto
This patch adds the new interrupt api to pecie-designware, keeping the old one. A define was added to toggle between the two apis (for testing purposes).
Signed-off-by Joao Pinto <[email protected]>--- drivers/pci/dwc/pcie-designware-host.c | 241 ++++++++++++++++++++++++++++++++- drivers/pci/dwc/pcie-designware.h | 5 + 2 files changed, 244 insertions(+), 2 deletions(-)drivers/pci/dwc/pcie-designware-host.c +1
-0@@ -11,6 +11,7 @@* published by the Free Software Foundation. */ +#include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/of_address.h> #include <linux/of_pci.h> @@ -19,6 +20,9 @@
Quoted 8 lines
drivers/pci/dwc/pcie-designware-host.c line 24
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +2
-0#include "pcie-designware.h" +/* Temporary: Activate to use new IRQ API */ +/*#define CONFIG_PCIEDW_NEW_IRQ_API*/ You should be able to support both APIs at the same time until the last patch, without relying on a kernel configuration (we still want to be able to boot a single kernel that works both with the old and new methods).
I think that the APIs are mutual-exclusive. pcie-designware has to initialize of one of them. Your idea is to have the new and the old API functions, but only initialize pcie-designware with the old one until the last patch?
[...]
Quoted 5 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 141
Quoted 3 lines
drivers/pci/dwc/pcie-designware-host.c +3
-0+ + msg->address_lo = (u32)(msi_target &0xffffffff ); + msg->address_hi = (u32)(msi_target >>32 &0xffffffff );Use lower_32_bit/upper_32_bit macros.
Right, I am going to update this.
[...]
Quoted 11 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 164
Quoted 8 lines
drivers/pci/dwc/pcie-designware-host.c +8
-0+ +static void dw_pci_bottom_mask (struct irq_data *data) +{ +struct dw_pcie *pci =irq_data_get_irq_chip_data (data); +struct pcie_port *pp = &pci->pp; +unsigned int res, bit, val; + +mutex_lock (&pp->lock);This is wrong. You can also end-up here from interrupt context, so you need an
spin_lock_irqsave().
Right, I am going to update this.
[...]
Quoted 7 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 167
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +3
-0+ +if (pp->ops->msi_clear_irq) + pp->ops->msi_clear_irq (pp, data->hwirq);Why do you need this? Can you have alternative implementations of mask/unmask?
msi_clear_irq and msi_set_irq are specific SoC operations to set and clear bits in the interrupt register. In my opinion we should keep the current callbacks.
[...]
Quoted 9 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 172
Quoted 6 lines
drivers/pci/dwc/pcie-designware-host.c +5
-0+else { + res = (data->hwirq /32 ) *12 ; + bit = data->hwirq %32 ; + +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , &val);No use reading back from the HW. Just maintain a cached version in your private structure and just use that.
Ok, I can do that.
[...]
Quoted 4 lines
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +4
-0+ + bit =find_first_zero_bit (pp->msi_irq_in_use, pp->num_vectors); +if (bit >= pp->num_vectors) { +mutex_unlock (&pp->lock);
Quoted 9 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 230
Quoted 6 lines
drivers/pci/dwc/pcie-designware-host.c +6
-0+return -ENOSPC ; + } + +set_bit (bit, pp->msi_irq_in_use); + +mutex_unlock (&pp->lock);As mentioned by Lucas, you probably want to support Multi-MSI.
This could be achieved by declaring data for each virq, correct?
for (i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, bit + i, &dw_pci_msi_bottom_irq_chip,domain->host_data, handle_simple_irq, NULL, NULL);
}
[...]
Quoted 6 lines
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 268
Quoted 3 lines
drivers/pci/dwc/pcie-designware-host.c +3
-0+ + pp->irq_domain =irq_domain_add_linear (NULL , pp->num_vectors, + &dw_pcie_msi_domain_ops, pci);Please use
irq_domain_create_linearand pass the fwnode there as well.
Ok, I will do that.
[...]
Quoted 8 lines
Quoted 3 lines
static inline
irqreturn_tdw_handle_msi_irq(struct pcie_port *pp){Thanks,
M.
Thank you for you feeback!
Joao
RFC 2/8 pci: exynos SoC driver adapted to new irq API
In reply to Joao PintoThis patch adapts Exynos SoC specific driver to use the new interrupt api available in pcie-designware.
--- drivers/pci/dwc/pci-exynos.c | 18 ------------------ 1 file changed, 18 deletions(-)
drivers/pci/dwc/pci-exynos.c +0 -18
@@ -490,15 +490,6 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)return IRQ_HANDLED ; } -static irqreturn_t exynos_pcie_msi_irq_handler (int irq,void *arg) -{ -struct exynos_pcie *ep = arg; -struct dw_pcie *pci = ep->pci; -struct pcie_port *pp = &pci->pp; - -return dw_handle_msi_irq (pp); -} -static void exynos_pcie_msi_init (struct exynos_pcie *ep) {struct dw_pcie *pci = ep->pci;
@@ -622,15 +613,6 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,dev_err (dev,"failed to get msi irq\n" );return -ENODEV ; } - - ret =devm_request_irq (dev, pp->msi_irq, - exynos_pcie_msi_irq_handler, -IRQF_SHARED |IRQF_NO_THREAD , -"exynos-pcie" , ep); -if (ret) { -dev_err (dev,"failed to request msi irq\n" ); -return ret; - } } pp->root_bus_nr =-1 ;
Signature · 1 line
2.9.3
RFC 3/8 pci: imx6 SoC driver adapted to new irq API
In reply to Joao PintoThis patch adapts imx6 SoC specific driver to use the new interrupt api available in pcie-designware.
--- drivers/pci/dwc/pci-imx6.c | 18 ------------------ 1 file changed, 18 deletions(-)
drivers/pci/dwc/pci-imx6.c +0 -18
@@ -490,15 +490,6 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)return -EINVAL ; } -static irqreturn_t imx6_pcie_msi_handler (int irq,void *arg) -{ -struct imx6_pcie *imx6_pcie = arg; -struct dw_pcie *pci = imx6_pcie->pci; -struct pcie_port *pp = &pci->pp; - -return dw_handle_msi_irq (pp); -} -static int imx6_pcie_establish_link (struct imx6_pcie *imx6_pcie) {struct dw_pcie *pci = imx6_pcie->pci;
@@ -620,15 +611,6 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,dev_err (dev,"failed to get MSI irq\n" );return -ENODEV ; } - - ret =devm_request_irq (dev, pp->msi_irq, - imx6_pcie_msi_handler, -IRQF_SHARED |IRQF_NO_THREAD , -"mx6-pcie-msi" , imx6_pcie); -if (ret) { -dev_err (dev,"failed to request MSI irq\n" ); -return ret; - } } pp->root_bus_nr =-1 ;
Signature · 1 line
2.9.3
RFC 4/8 pci: artpec6 SoC driver adapted to new irq API
In reply to Joao PintoThis patch adapts artpec6 SoC specific driver to use the new interrupt api available in pcie-designware.
--- drivers/pci/dwc/pcie-artpec6.c | 18 ------------------ 1 file changed, 18 deletions(-)
drivers/pci/dwc/pcie-artpec6.c +0 -18
@@ -188,15 +188,6 @@ static struct dw_pcie_host_ops artpec6_pcie_host_ops = { .host_init = artpec6_pcie_host_init, }; -static irqreturn_t artpec6_pcie_msi_handler (int irq,void *arg) -{ -struct artpec6_pcie *artpec6_pcie = arg; -struct dw_pcie *pci = artpec6_pcie->pci; -struct pcie_port *pp = &pci->pp; - -return dw_handle_msi_irq (pp); -} -static int artpec6_add_pcie_port (struct artpec6_pcie *artpec6_pcie,struct platform_device *pdev) {
@@ -211,15 +202,6 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,dev_err (dev,"failed to get MSI irq\n" );return -ENODEV ; } - - ret =devm_request_irq (dev, pp->msi_irq, - artpec6_pcie_msi_handler, -IRQF_SHARED |IRQF_NO_THREAD , -"artpec6-pcie-msi" , artpec6_pcie); -if (ret) { -dev_err (dev,"failed to request MSI irq\n" ); -return ret; - } } pp->root_bus_nr =-1 ;
Signature · 1 line
2.9.3
RFC 5/8 pci: generic PCIe DW driver adapted to new irq API
In reply to Joao PintoThis patch adapts the generic PCIe DW driver to use the new interrupt api available in pcie-designware.
--- drivers/pci/dwc/pcie-designware-plat.c | 15 --------------- 1 file changed, 15 deletions(-)
drivers/pci/dwc/pcie-designware-plat.c +0 -15
@@ -28,13 +28,6 @@ struct dw_plat_pcie {struct dw_pcie *pci; }; -static irqreturn_t dw_plat_pcie_msi_irq_handler (int irq,void *arg) -{ -struct pcie_port *pp = arg; - -return dw_handle_msi_irq (pp); -} -static void dw_plat_pcie_host_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);
@@ -64,14 +57,6 @@ static int dw_plat_add_pcie_port(struct pcie_port *pp, pp->msi_irq =platform_get_irq (pdev,0 );if (pp->msi_irq <0 )return pp->msi_irq; - - ret =devm_request_irq (dev, pp->msi_irq, - dw_plat_pcie_msi_irq_handler, -IRQF_SHARED ,"dw-plat-pcie-msi" , pp); -if (ret) { -dev_err (dev,"failed to request MSI IRQ\n" ); -return ret; - } } pp->root_bus_nr =-1 ;
Signature · 1 line
2.9.3
RFC 6/8 pci: qcom SoC driver adapted to new irq API
In reply to Joao PintoThis patch adapts Qcom SoC specific driver to use the new interrupt api available in pcie-designware.
--- drivers/pci/dwc/pcie-qcom.c | 15 --------------- 1 file changed, 15 deletions(-)
drivers/pci/dwc/pcie-qcom.c +0 -15
@@ -126,13 +126,6 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)usleep_range (PERST_DELAY_US ,PERST_DELAY_US +500 ); } -static irqreturn_t qcom_pcie_msi_irq_handler (int irq,void *arg) -{ -struct pcie_port *pp = arg; - -return dw_handle_msi_irq (pp); -} -static void qcom_pcie_v0_v1_ltssm_enable (struct qcom_pcie *pcie) {u32 val;
@@ -724,14 +717,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) pp->msi_irq =platform_get_irq_byname (pdev,"msi" );if (pp->msi_irq <0 )return pp->msi_irq; - - ret =devm_request_irq (dev, pp->msi_irq, - qcom_pcie_msi_irq_handler, -IRQF_SHARED ,"qcom-pcie-msi" , pp); -if (ret) { -dev_err (dev,"cannot request msi irq\n" ); -return ret; - } } ret =phy_init (pcie->phy);
Signature · 1 line
2.9.3
RFC 7/8 pci: keystone SoC driver adapted to new irq API
In reply to Joao PintoThis patch adapts Keystone SoC specific driver to use the new interrupt api available in pcie-designware. A new callback was added to dw_pcie_host_ops to handle a specific Keystone function and msi_host_init callback is changed to simplify the access to pci data structure for keystone all SoC drivers that use the structure.
--- drivers/pci/dwc/pci-keystone-dw.c | 97 +++------------------------------- drivers/pci/dwc/pci-keystone.c | 1 + drivers/pci/dwc/pci-keystone.h | 4 +- drivers/pci/dwc/pci-layerscape.c | 3 +- drivers/pci/dwc/pcie-designware-host.c | 12 ++++- drivers/pci/dwc/pcie-designware.h | 3 +- 6 files changed, 23 insertions(+), 97 deletions(-)
drivers/pci/dwc/pci-keystone-dw.c +6 -91
@@ -124,19 +124,15 @@ void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset) } } -static void ks_dw_pcie_msi_irq_ack (struct irq_data *d) +void ks_dw_pcie_msi_irq_ack (int irq,struct pcie_port *pp) {u32 offset, reg_offset, bit_pos;struct keystone_pcie *ks_pcie; -struct msi_desc *msi; -struct pcie_port *pp;struct dw_pcie *pci; - msi =irq_data_get_msi_desc (d); - pp = (struct pcie_port *)msi_desc_to_pci_sysdata (msi); pci =to_dw_pcie_from_pp (pp); ks_pcie =to_keystone_pcie (pci); - offset = d->irq -irq_linear_revmap (pp->irq_domain,0 ); + offset = irq -irq_linear_revmap (pp->irq_domain,0 );update_reg_offset_bit_pos (offset, ®_offset, &bit_pos); ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
@@ -166,93 +162,12 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) BIT(bit_pos)); } -static void ks_dw_pcie_msi_irq_mask (struct irq_data *d) +int ks_dw_pcie_msi_host_init (struct dw_pcie *pci,struct msi_controller *chip) { -struct keystone_pcie *ks_pcie; -struct msi_desc *msi; -struct pcie_port *pp; -struct dw_pcie *pci; -u32 offset; - - msi =irq_data_get_msi_desc (d); - pp = (struct pcie_port *)msi_desc_to_pci_sysdata (msi); - pci =to_dw_pcie_from_pp (pp); - ks_pcie =to_keystone_pcie (pci); - offset = d->irq -irq_linear_revmap (pp->irq_domain,0 ); - -/* Mask the end point if PVM implemented */ -if (IS_ENABLED (CONFIG_PCI_MSI )) { -if (msi->msi_attrib.maskbit) -pci_msi_mask_irq (d); - } - -ks_dw_pcie_msi_clear_irq (pp, offset); -} - -static void ks_dw_pcie_msi_irq_unmask (struct irq_data *d) -{ -struct keystone_pcie *ks_pcie; -struct msi_desc *msi; -struct pcie_port *pp; -struct dw_pcie *pci; -u32 offset; - - msi =irq_data_get_msi_desc (d); - pp = (struct pcie_port *)msi_desc_to_pci_sysdata (msi); - pci =to_dw_pcie_from_pp (pp); - ks_pcie =to_keystone_pcie (pci); - offset = d->irq -irq_linear_revmap (pp->irq_domain,0 ); - -/* Mask the end point if PVM implemented */ -if (IS_ENABLED (CONFIG_PCI_MSI )) { -if (msi->msi_attrib.maskbit) -pci_msi_unmask_irq (d); - } - -ks_dw_pcie_msi_set_irq (pp, offset); -} +/* overide number of vectors and sent them to Keystone Max MSI IRQs */ + pci->pp.num_vectors =MAX_MSI_IRQS ; -static struct irq_chip ks_dw_pcie_msi_irq_chip = { - .name ="Keystone-PCIe-MSI-IRQ" , - .irq_ack = ks_dw_pcie_msi_irq_ack, - .irq_mask = ks_dw_pcie_msi_irq_mask, - .irq_unmask = ks_dw_pcie_msi_irq_unmask, -}; - -static int ks_dw_pcie_msi_map (struct irq_domain *domain,unsigned int irq, -irq_hw_number_t hwirq) -{ -irq_set_chip_and_handler (irq, &ks_dw_pcie_msi_irq_chip, - handle_level_irq); -irq_set_chip_data (irq, domain->host_data); - -return 0 ; -} - -static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { - .map = ks_dw_pcie_msi_map, -}; - -int ks_dw_pcie_msi_host_init (struct pcie_port *pp,struct msi_controller *chip) -{ -struct dw_pcie *pci =to_dw_pcie_from_pp (pp); -struct keystone_pcie *ks_pcie =to_keystone_pcie (pci); -struct device *dev = pci->dev; -int i; - - pp->irq_domain =irq_domain_add_linear (ks_pcie->msi_intc_np, -MAX_MSI_IRQS , - &ks_dw_pcie_msi_domain_ops, - chip); -if (!pp->irq_domain) { -dev_err (dev,"irq domain init failed\n" ); -return -ENXIO ; - } - -for (i =0 ; i <MAX_MSI_IRQS ; i++) -irq_create_mapping (pp->irq_domain, i); - -return 0 ; +return dw_pcie_allocate_domains (pci); }void ks_dw_pcie_enable_legacy_irqs (struct keystone_pcie *ks_pcie)
drivers/pci/dwc/pci-keystone.c +1 -0
@@ -299,6 +299,7 @@ static struct dw_pcie_host_ops keystone_pcie_host_ops = { .msi_clear_irq = ks_dw_pcie_msi_clear_irq, .get_msi_addr = ks_dw_pcie_get_msi_addr, .msi_host_init = ks_dw_pcie_msi_host_init, + .msi_irq_ack = ks_dw_pcie_msi_irq_ack, .scan_bus = ks_dw_pcie_v3_65_scan_bus, };
drivers/pci/dwc/pci-keystone.h +2 -2
@@ -55,9 +55,9 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);void ks_dw_pcie_setup_rc_app_regs (struct keystone_pcie *ks_pcie);void ks_dw_pcie_initiate_link_train (struct keystone_pcie *ks_pcie); +void ks_dw_pcie_msi_irq_ack (int i,struct pcie_port *pp);void ks_dw_pcie_msi_set_irq (struct pcie_port *pp,int irq);void ks_dw_pcie_msi_clear_irq (struct pcie_port *pp,int irq);void ks_dw_pcie_v3_65_scan_bus (struct pcie_port *pp); -int ks_dw_pcie_msi_host_init (struct pcie_port *pp, -struct msi_controller *chip); +int ks_dw_pcie_msi_host_init (struct dw_pcie *pci,struct msi_controller *chip);int ks_dw_pcie_link_up (struct dw_pcie *pci);
drivers/pci/dwc/pci-layerscape.c +1 -2
@@ -162,10 +162,9 @@ static void ls_pcie_host_init(struct pcie_port *pp)iowrite32 (0 , pci->dbi_base +PCIE_DBI_RO_WR_EN ); } -static int ls_pcie_msi_host_init (struct pcie_port *pp, +static int ls_pcie_msi_host_init (struct dw_pcie *pci,struct msi_controller *chip) { -struct dw_pcie *pci =to_dw_pcie_from_pp (pp);struct device *dev = pci->dev;struct device_node *np = dev->of_node;struct device_node *msi_node;
drivers/pci/dwc/pcie-designware-host.c +11 -1
@@ -199,8 +199,18 @@ static void dw_pci_bottom_unmask(struct irq_data *data)mutex_unlock (&pp->lock); } +static void dw_pci_bottom_ack (struct irq_data *d) +{ +struct msi_desc *msi =irq_data_get_msi_desc (d); +struct pcie_port *pp = (struct pcie_port *)msi_desc_to_pci_sysdata (msi); + +if (pp->ops->msi_irq_ack) + pp->ops->msi_irq_ack (d->irq, pp); +} +static struct irq_chip dw_pci_msi_bottom_irq_chip = { .name ="DWPCI-MSI" , + .irq_ack = dw_pci_bottom_ack, .irq_compose_msi_msg = dw_pci_setup_msi_msg, .irq_set_affinity = dw_pci_msi_set_affinity, .irq_mask = dw_pci_bottom_mask,
@@ -622,7 +632,7 @@ int dw_pcie_host_init(struct pcie_port *pp) pci);#endif }else { - ret = pp->ops->msi_host_init (pp, &dw_pcie_msi_chip); + ret = pp->ops->msi_host_init (pci, &dw_pcie_msi_chip);if (ret <0 ) goto error; }
drivers/pci/dwc/pcie-designware.h +2 -1
@@ -140,7 +140,8 @@ struct dw_pcie_host_ops {phys_addr_t (*get_msi_addr)(struct pcie_port *pp);u32 (*get_msi_data)(struct pcie_port *pp,int pos);void (*scan_bus)(struct pcie_port *pp); -int (*msi_host_init)(struct pcie_port *pp,struct msi_controller *chip); +int (*msi_host_init)(struct dw_pcie *pci,struct msi_controller *chip); +void (*msi_irq_ack)(int irq,struct pcie_port *pp); };struct pcie_port {
Signature · 1 line
2.9.3
RFC 8/8 pci: removing old irq api from pcie-designware
In reply to Joao PintoThis patch removes the old interrupt API.
--- drivers/pci/dwc/pci-keystone-dw.c | 2 +- drivers/pci/dwc/pci-keystone.h | 2 +- drivers/pci/dwc/pci-layerscape.c | 3 +- drivers/pci/dwc/pcie-designware-host.c | 224 +-------------------------------- drivers/pci/dwc/pcie-designware.h | 2 +- 5 files changed, 6 insertions(+), 227 deletions(-)
drivers/pci/dwc/pci-keystone-dw.c +1 -1
@@ -162,7 +162,7 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) BIT(bit_pos)); } -int ks_dw_pcie_msi_host_init (struct dw_pcie *pci,struct msi_controller *chip) +int ks_dw_pcie_msi_host_init (struct dw_pcie *pci) {/* overide number of vectors and sent them to Keystone Max MSI IRQs */ pci->pp.num_vectors =MAX_MSI_IRQS ;
drivers/pci/dwc/pci-keystone.h +1 -1
@@ -59,5 +59,5 @@ void ks_dw_pcie_msi_irq_ack(int i, struct pcie_port *pp);void ks_dw_pcie_msi_set_irq (struct pcie_port *pp,int irq);void ks_dw_pcie_msi_clear_irq (struct pcie_port *pp,int irq);void ks_dw_pcie_v3_65_scan_bus (struct pcie_port *pp); -int ks_dw_pcie_msi_host_init (struct dw_pcie *pci,struct msi_controller *chip); +int ks_dw_pcie_msi_host_init (struct dw_pcie *pci);int ks_dw_pcie_link_up (struct dw_pcie *pci);
drivers/pci/dwc/pci-layerscape.c +1 -2
@@ -162,8 +162,7 @@ static void ls_pcie_host_init(struct pcie_port *pp)iowrite32 (0 , pci->dbi_base +PCIE_DBI_RO_WR_EN ); } -static int ls_pcie_msi_host_init (struct dw_pcie *pci, -struct msi_controller *chip) +static int ls_pcie_msi_host_init (struct dw_pcie *pci) {struct device *dev = pci->dev;struct device_node *np = dev->of_node;
drivers/pci/dwc/pcie-designware-host.c +2 -222
287 lines not on this page · raw message
drivers/pci/dwc/pcie-designware.h +1 -1
@@ -140,7 +140,7 @@ struct dw_pcie_host_ops {phys_addr_t (*get_msi_addr)(struct pcie_port *pp);u32 (*get_msi_data)(struct pcie_port *pp,int pos);void (*scan_bus)(struct pcie_port *pp); -int (*msi_host_init)(struct dw_pcie *pci,struct msi_controller *chip); +int (*msi_host_init)(struct dw_pcie *pci);void (*msi_irq_ack)(int irq,struct pcie_port *pp); };
Signature · 1 line
2.9.3