PCI: dwc: Enables MSI-X driver support
Subsystems (3)
v9 cover PCI: dwc: Enables MSI-X driver support
Changes into a new IRQ handler mechanism (multiplexed IRQ domain hierarchy) more suitable and appropriate to use on pcie-designware and on each SoC specific driver in order to allow new and more complex features like MSI-X.
Adds Synopsys Root Complex driver support for MSI-X feature.
Expands the maximum number of IRQs from 32 to 256 distributed by a maximum of 8 controller registers.
The patch set was made against the Bjorn's master branch (v4.16-rc1).
Gustavo Pimentel (3):
PCI: dwc: Add new IRQ API
PCI: dwc: Remove old IRQ API
PCI: dwc: Expand maximum number of IRQs from 32 to 256
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 91 +------- 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-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 398 +++++++++++++++++++-------------- drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 30 ++- drivers/pci/dwc/pcie-qcom.c | 16 -- 11 files changed, 258 insertions(+), 355 deletions(-)
Signature · 1 line
2.7.4
PATCH v9 1/3 PCI: dwc: Add new IRQ API
Adds a multiplexed IRQ domain hierarchy API to pcie-designware that funnels all MSIs into a single parent interrupt. Moving away from the msi controller API.
Although the old implementation API is still available, pcie-designware will use now the multiplexed IRQ domain hierarchy API.
---
Change v1->v2:
- num_vectors is now not configurable by the Device Tree. Now it is 32 by default and can be overridden by any specific SoC driver. Change v2->v3:
- Nothing changed, just to follow the patch set version.
Change v3->v4:
- Moved Kishon's fixes (PCI end point error and a dra7xx warning) from v3-0007 patch file to here.
- Undo the change of the function signature to be more coherent with the host mode specific functions (Thanks Kishon).
- Refactor the added functions in order to used host_data so that getting pp again back from pci could be avoided. (Thanks Kishon)
- Changed summary line to match the drivers/PCI convention and changelog to maintain the consistency (thanks Bjorn).
Change v4->v5:
- Implemented Kishon MSI multiple messages fix (thanks Kishon). Change v5->v6:
- Fixed rebase problem detected by Niklas (thanks Niklas). Change v6->v7:
- Implemented Marc review suggestions (thanks Marc).
Change v7->v8:
- Rebased against v4.16-rc1.
Change v8->v9:
- Squashed all patches [2-7] into this, following Lorenzo sugestion (thanks Lorenzo).
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 89 +--------- drivers/pci/dwc/pci-keystone.c | 1 + drivers/pci/dwc/pci-keystone.h | 1 + drivers/pci/dwc/pcie-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 296 +++++++++++++++++++++++++++++---- drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 18 ++ drivers/pci/dwc/pcie-qcom.c | 16 -- 10 files changed, 292 insertions(+), 199 deletions(-)
drivers/pci/dwc/pci-exynos.c +0 -18
@@ -294,15 +294,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;
@@ -428,15 +419,6 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,dev_err (dev,"failed to get msi irq\n" );return pp->msi_irq; } - - 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 ;
drivers/pci/dwc/pci-imx6.c +0 -18
@@ -542,15 +542,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;
@@ -674,15 +665,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 ;
drivers/pci/dwc/pci-keystone-dw.c +4 -85
109 lines not on this page · raw message
drivers/pci/dwc/pci-keystone.c +1 -0
@@ -297,6 +297,7 @@ static const 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 +1 -0
@@ -49,6 +49,7 @@ 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);
drivers/pci/dwc/pcie-artpec6.c +0 -18
@@ -383,15 +383,6 @@ static const 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) {
@@ -406,15 +397,6 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,dev_err (dev,"failed to get MSI irq\n" );return pp->msi_irq; } - - 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 ;
drivers/pci/dwc/pcie-designware-host.c +268 -28
369 lines not on this page · raw message
drivers/pci/dwc/pcie-designware-plat.c +0 -16
@@ -25,13 +25,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 int dw_plat_pcie_host_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);
@@ -63,15 +56,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 |IRQF_NO_THREAD , -"dw-plat-pcie-msi" , pp); -if (ret) { -dev_err (dev,"failed to request MSI IRQ\n" ); -return ret; - } } pp->root_bus_nr =-1 ;
drivers/pci/dwc/pcie-designware.h +18 -0
@@ -114,6 +114,7 @@*/ #define MAX_MSI_IRQS 32#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) +#define MSI_DEF_NUM_VECTORS 32/* Maximum number of inbound/outbound iATUs */ #define MAX_IATU_IN 256
@@ -149,7 +150,9 @@ 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); +void (*set_num_vectors)(struct pcie_port *pp);int (*msi_host_init)(struct pcie_port *pp,struct msi_controller *chip); +void (*msi_irq_ack)(int irq,struct pcie_port *pp); };struct pcie_port {
@@ -174,7 +177,11 @@ struct pcie_port {const struct dw_pcie_host_ops *ops;int msi_irq;struct irq_domain *irq_domain; +struct irq_domain *msi_domain;dma_addr_t msi_data; +u32 num_vectors; +u32 irq_status[MAX_MSI_CTRLS ]; +spinlock_t lock;DECLARE_BITMAP (msi_irq_in_use,MAX_MSI_IRQS ); };
@@ -316,8 +323,10 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)#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 pcie_port *pp);#else static inline irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) {
@@ -328,6 +337,10 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp) { } +static inline void dw_pcie_free_msi (struct pcie_port *pp) +{ +} +static inline void dw_pcie_setup_rc (struct pcie_port *pp) { }
@@ -336,6 +349,11 @@ static inline int dw_pcie_host_init(struct pcie_port *pp) {return 0 ; } + +static inline int dw_pcie_allocate_domains (struct pcie_port *pp) +{ +return 0 ; +}#endif #ifdef CONFIG_PCIE_DW_EP
drivers/pci/dwc/pcie-qcom.c +0 -16
@@ -180,13 +180,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 int qcom_pcie_establish_link (struct qcom_pcie *pcie) {struct dw_pcie *pci = pcie->pci;
@@ -1262,15 +1255,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 |IRQF_NO_THREAD , -"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.7.4
Re: [PATCH v9 1/3] PCI: dwc: Add new IRQ API
On Wed, Feb 28, 2018 at 04:10:23PM +0000, Gustavo Pimentel wrote:
[...]
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +0
-0
[...]
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+static int dw_pcie_irq_domain_alloc (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs, +void *args) +{ +struct pcie_port *pp = domain->host_data; +unsigned long flags; +unsigned long bit; +u32 i; + +raw_spin_lock_irqsave (&pp->lock, flags);
drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 240
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+ + bit =bitmap_find_free_region (pp->msi_irq_in_use, pp->num_vectors, +order_base_2 (nr_irqs)); + +if (bit <0 ) { +raw_spin_unlock_irqrestore (&pp->lock, flags); +return -ENOSPC ; + } + +raw_spin_unlock_irqrestore (&pp->lock, flags);
I've rewritten this as:
raw_spin_unlock_irqrestore(&pp->lock, flags);
if (bit < 0)
return -ENOSPC;
Since the unlock path is ugly and there is no need to protect the bit variable, we should just protect the bitmap.
Have a look at my pci/dwc-msi branch to check if that's what you expect.
Everything else is OK to me, patches queued in my pci/dwc-msi branch for v4.17, please have a look.
Thanks !
Lorenzo
Quoted 340 lines
drivers/pci/dwc/pcie-designware-host.c +108
-28+ +for (i =0 ; i < nr_irqs; i++) +irq_domain_set_info (domain, virq + i, bit + i, + &dw_pci_msi_bottom_irq_chip, + pp, handle_edge_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 pcie_port *pp =irq_data_get_irq_chip_data (data); +unsigned long flags; + +raw_spin_lock_irqsave (&pp->lock, flags); +bitmap_release_region (pp->msi_irq_in_use, data->hwirq, +order_base_2 (nr_irqs)); +raw_spin_unlock_irqrestore (&pp->lock, flags); +} + +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 pcie_port *pp) +{ +struct dw_pcie *pci =to_dw_pcie_from_pp (pp); +struct fwnode_handle *fwnode =of_node_to_fwnode (pci->dev->of_node); + + pp->irq_domain =irq_domain_create_linear (fwnode, pp->num_vectors, + &dw_pcie_msi_domain_ops, pp); +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); +} +void dw_pcie_msi_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);@@ -96,20 +317,21 @@ void dw_pcie_msi_init(struct pcie_port *pp)/* program the msi_data */ dw_pcie_wr_own_conf (pp,PCIE_MSI_ADDR_LO ,4 , - (u32)(msi_target &0xffffffff )); +lower_32_bits (msi_target));dw_pcie_wr_own_conf (pp,PCIE_MSI_ADDR_HI ,4 , - (u32)(msi_target >>32 &0xffffffff )); +upper_32_bits (msi_target)); }static void dw_pcie_msi_clear_irq (struct pcie_port *pp,int irq) { -unsigned int res, bit, val; +unsigned int res, bit, ctrl; - res = (irq /32 ) *12 ; + ctrl = irq /32 ; + res = ctrl *12 ; bit = irq %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); + pp->irq_status[ctrl] &= ~(1 << bit); +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , + pp->irq_status[ctrl]); } static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,@@ -131,13 +353,14 @@ static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,static void dw_pcie_msi_set_irq (struct pcie_port *pp,int irq) { -unsigned int res, bit, val; +unsigned int res, bit, ctrl; - res = (irq /32 ) *12 ; + ctrl = irq /32 ; + res = ctrl *12 ; bit = irq %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); + pp->irq_status[ctrl] |=1 << bit; +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , + pp->irq_status[ctrl]); }static int assign_irq (int no_irqs,struct msi_desc *desc,int *pos)@@ -285,11 +508,13 @@ 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 pci_host_bridge *bridge;struct resource *cfg_res; -int i, ret; -struct resource_entry *win, *tmp; +int ret; + +spin_lock_init (&pci->pp.lock); cfg_res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"config" );if (cfg_res) {@@ -388,18 +613,33 @@ int dw_pcie_host_init(struct pcie_port *pp) pci->num_viewport =2 ;if (IS_ENABLED (CONFIG_PCI_MSI )) { -if (!pp->ops->msi_host_init) { - pp->irq_domain =irq_domain_add_linear (dev->of_node, -MAX_MSI_IRQS , &msi_domain_ops, - &dw_pcie_msi_chip); -if (!pp->irq_domain) { -dev_err (dev,"irq domain init failed\n" ); - ret = -ENXIO ; +/* +* If a specific SoC driver needs to change the +* default number of vectors, it needs to implement +* the set_num_vectors callback. +*/ +if (!pp->ops->set_num_vectors) { + pp->num_vectors =MSI_DEF_NUM_VECTORS ; + }else { + pp->ops->set_num_vectors (pp); + +if (pp->num_vectors >MAX_MSI_IRQS || + pp->num_vectors ==0 ) { +dev_err (dev, +"Invalid number of vectors\n" ); goto error; } + } -for (i =0 ; i <MAX_MSI_IRQS ; i++) -irq_create_mapping (pp->irq_domain, i); +if (!pp->ops->msi_host_init) { + ret =dw_pcie_allocate_domains (pp); +if (ret) + goto error; + +if (pp->msi_irq) +irq_set_chained_handler_and_data (pp->msi_irq, + dw_chained_msi_isr, + pp); }else { ret = pp->ops->msi_host_init (pp, &dw_pcie_msi_chip);if (ret <0 )@@ -421,10 +661,6 @@ int dw_pcie_host_init(struct pcie_port *pp) bridge->ops = &dw_pcie_ops; bridge->map_irq = of_irq_parse_and_map_pci; bridge->swizzle_irq = pci_common_swizzle; -if (IS_ENABLED (CONFIG_PCI_MSI )) { - bridge->msi = &dw_pcie_msi_chip; - dw_pcie_msi_chip.dev = dev; - } ret =pci_scan_root_bus_bridge (bridge);if (ret)@@ -593,11 +829,15 @@ static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)void dw_pcie_setup_rc (struct pcie_port *pp) { -u32 val; +u32 val, ctrl;struct dw_pcie *pci =to_dw_pcie_from_pp (pp);dw_pcie_setup (pci); +/* Initialize IRQ Status array */ +for (ctrl =0 ; ctrl <MAX_MSI_CTRLS ; ctrl++) +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + (ctrl *12 ),4 , + &pp->irq_status[ctrl]);/* setup RC BARs */ dw_pcie_writel_dbi (pci,PCI_BASE_ADDRESS_0 ,0x00000004 );dw_pcie_writel_dbi (pci,PCI_BASE_ADDRESS_1 ,0x00000000 );drivers/pci/dwc/pcie-designware-plat.c +0
-16@@ -25,13 +25,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 int dw_plat_pcie_host_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);@@ -63,15 +56,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 |IRQF_NO_THREAD , -"dw-plat-pcie-msi" , pp); -if (ret) { -dev_err (dev,"failed to request MSI IRQ\n" ); -return ret; - } } pp->root_bus_nr =-1 ;drivers/pci/dwc/pcie-designware.h +18
-0@@ -114,6 +114,7 @@*/ #define MAX_MSI_IRQS 32#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) +#define MSI_DEF_NUM_VECTORS 32/* Maximum number of inbound/outbound iATUs */ #define MAX_IATU_IN 256@@ -149,7 +150,9 @@ 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); +void (*set_num_vectors)(struct pcie_port *pp);int (*msi_host_init)(struct pcie_port *pp,struct msi_controller *chip); +void (*msi_irq_ack)(int irq,struct pcie_port *pp); };struct pcie_port {@@ -174,7 +177,11 @@ struct pcie_port {const struct dw_pcie_host_ops *ops;int msi_irq;struct irq_domain *irq_domain; +struct irq_domain *msi_domain;dma_addr_t msi_data; +u32 num_vectors; +u32 irq_status[MAX_MSI_CTRLS ]; +spinlock_t lock;DECLARE_BITMAP (msi_irq_in_use,MAX_MSI_IRQS ); };@@ -316,8 +323,10 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)#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 pcie_port *pp);#else static inline irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) {@@ -328,6 +337,10 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp) { } +static inline void dw_pcie_free_msi (struct pcie_port *pp) +{ +} +static inline void dw_pcie_setup_rc (struct pcie_port *pp) { }@@ -336,6 +349,11 @@ static inline int dw_pcie_host_init(struct pcie_port *pp) {return 0 ; } + +static inline int dw_pcie_allocate_domains (struct pcie_port *pp) +{ +return 0 ; +}#endif #ifdef CONFIG_PCIE_DW_EP drivers/pci/dwc/pcie-qcom.c +0
-16@@ -180,13 +180,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 int qcom_pcie_establish_link (struct qcom_pcie *pcie) {struct dw_pcie *pci = pcie->pci;@@ -1262,15 +1255,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 |IRQF_NO_THREAD , -"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.7.4
Re: [PATCH v9 1/3] PCI: dwc: Add new IRQ API
Hi Lorenzo,
Quoted 34 lines · Lorenzo Pieralisi
On Wed, Feb 28, 2018 at 04:10:23PM +0000, Gustavo Pimentel wrote:
[...]
Quoted 4 lines
drivers/pci/dwc/pcie-designware-host.c +0
-0[...]
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+static int dw_pcie_irq_domain_alloc (struct irq_domain *domain, +unsigned int virq,unsigned int nr_irqs, +void *args) +{ +struct pcie_port *pp = domain->host_data; +unsigned long flags; +unsigned long bit; +u32 i; + +raw_spin_lock_irqsave (&pp->lock, flags);drivers/pci/dwc/pcie-designware-host.c irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) · line 240
Quoted 10 lines
drivers/pci/dwc/pcie-designware-host.c +10
-0+ + bit =bitmap_find_free_region (pp->msi_irq_in_use, pp->num_vectors, +order_base_2 (nr_irqs)); + +if (bit <0 ) { +raw_spin_unlock_irqrestore (&pp->lock, flags); +return -ENOSPC ; + } + +raw_spin_unlock_irqrestore (&pp->lock, flags);I've rewritten this as:
Quoted 7 lines
raw_spin_unlock_irqrestore(&pp->lock, flags);if (bit < 0)
return -ENOSPC;Since the unlock path is ugly and there is no need to protect the bit variable, we should just protect the bitmap.
Agree. Very well spotted!
Quoted 6 lines
Have a look at my pci/dwc-msi branch to check if that's what you expect.
Everything else is OK to me, patches queued in my pci/dwc-msi branch for v4.17, please have a look.
All seems to be OK to me. Once again thanks.
Quoted 339 lines
Thanks !
LorenzoQuoted 335 lines
drivers/pci/dwc/pcie-designware-host.c +108
-28+ +for (i =0 ; i < nr_irqs; i++) +irq_domain_set_info (domain, virq + i, bit + i, + &dw_pci_msi_bottom_irq_chip, + pp, handle_edge_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 pcie_port *pp =irq_data_get_irq_chip_data (data); +unsigned long flags; + +raw_spin_lock_irqsave (&pp->lock, flags); +bitmap_release_region (pp->msi_irq_in_use, data->hwirq, +order_base_2 (nr_irqs)); +raw_spin_unlock_irqrestore (&pp->lock, flags); +} + +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 pcie_port *pp) +{ +struct dw_pcie *pci =to_dw_pcie_from_pp (pp); +struct fwnode_handle *fwnode =of_node_to_fwnode (pci->dev->of_node); + + pp->irq_domain =irq_domain_create_linear (fwnode, pp->num_vectors, + &dw_pcie_msi_domain_ops, pp); +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); +} +void dw_pcie_msi_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);@@ -96,20 +317,21 @@ void dw_pcie_msi_init(struct pcie_port *pp)/* program the msi_data */ dw_pcie_wr_own_conf (pp,PCIE_MSI_ADDR_LO ,4 , - (u32)(msi_target &0xffffffff )); +lower_32_bits (msi_target));dw_pcie_wr_own_conf (pp,PCIE_MSI_ADDR_HI ,4 , - (u32)(msi_target >>32 &0xffffffff )); +upper_32_bits (msi_target)); }static void dw_pcie_msi_clear_irq (struct pcie_port *pp,int irq) { -unsigned int res, bit, val; +unsigned int res, bit, ctrl; - res = (irq /32 ) *12 ; + ctrl = irq /32 ; + res = ctrl *12 ; bit = irq %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); + pp->irq_status[ctrl] &= ~(1 << bit); +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , + pp->irq_status[ctrl]); } static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,@@ -131,13 +353,14 @@ static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,static void dw_pcie_msi_set_irq (struct pcie_port *pp,int irq) { -unsigned int res, bit, val; +unsigned int res, bit, ctrl; - res = (irq /32 ) *12 ; + ctrl = irq /32 ; + res = ctrl *12 ; bit = irq %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); + pp->irq_status[ctrl] |=1 << bit; +dw_pcie_wr_own_conf (pp,PCIE_MSI_INTR0_ENABLE + res,4 , + pp->irq_status[ctrl]); }static int assign_irq (int no_irqs,struct msi_desc *desc,int *pos)@@ -285,11 +508,13 @@ 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 pci_host_bridge *bridge;struct resource *cfg_res; -int i, ret; -struct resource_entry *win, *tmp; +int ret; + +spin_lock_init (&pci->pp.lock); cfg_res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"config" );if (cfg_res) {@@ -388,18 +613,33 @@ int dw_pcie_host_init(struct pcie_port *pp) pci->num_viewport =2 ;if (IS_ENABLED (CONFIG_PCI_MSI )) { -if (!pp->ops->msi_host_init) { - pp->irq_domain =irq_domain_add_linear (dev->of_node, -MAX_MSI_IRQS , &msi_domain_ops, - &dw_pcie_msi_chip); -if (!pp->irq_domain) { -dev_err (dev,"irq domain init failed\n" ); - ret = -ENXIO ; +/* +* If a specific SoC driver needs to change the +* default number of vectors, it needs to implement +* the set_num_vectors callback. +*/ +if (!pp->ops->set_num_vectors) { + pp->num_vectors =MSI_DEF_NUM_VECTORS ; + }else { + pp->ops->set_num_vectors (pp); + +if (pp->num_vectors >MAX_MSI_IRQS || + pp->num_vectors ==0 ) { +dev_err (dev, +"Invalid number of vectors\n" ); goto error; } + } -for (i =0 ; i <MAX_MSI_IRQS ; i++) -irq_create_mapping (pp->irq_domain, i); +if (!pp->ops->msi_host_init) { + ret =dw_pcie_allocate_domains (pp); +if (ret) + goto error; + +if (pp->msi_irq) +irq_set_chained_handler_and_data (pp->msi_irq, + dw_chained_msi_isr, + pp); }else { ret = pp->ops->msi_host_init (pp, &dw_pcie_msi_chip);if (ret <0 )@@ -421,10 +661,6 @@ int dw_pcie_host_init(struct pcie_port *pp) bridge->ops = &dw_pcie_ops; bridge->map_irq = of_irq_parse_and_map_pci; bridge->swizzle_irq = pci_common_swizzle; -if (IS_ENABLED (CONFIG_PCI_MSI )) { - bridge->msi = &dw_pcie_msi_chip; - dw_pcie_msi_chip.dev = dev; - } ret =pci_scan_root_bus_bridge (bridge);if (ret)@@ -593,11 +829,15 @@ static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)void dw_pcie_setup_rc (struct pcie_port *pp) { -u32 val; +u32 val, ctrl;struct dw_pcie *pci =to_dw_pcie_from_pp (pp);dw_pcie_setup (pci); +/* Initialize IRQ Status array */ +for (ctrl =0 ; ctrl <MAX_MSI_CTRLS ; ctrl++) +dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + (ctrl *12 ),4 , + &pp->irq_status[ctrl]);/* setup RC BARs */ dw_pcie_writel_dbi (pci,PCI_BASE_ADDRESS_0 ,0x00000004 );dw_pcie_writel_dbi (pci,PCI_BASE_ADDRESS_1 ,0x00000000 );drivers/pci/dwc/pcie-designware-plat.c +0
-16@@ -25,13 +25,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 int dw_plat_pcie_host_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);@@ -63,15 +56,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 |IRQF_NO_THREAD , -"dw-plat-pcie-msi" , pp); -if (ret) { -dev_err (dev,"failed to request MSI IRQ\n" ); -return ret; - } } pp->root_bus_nr =-1 ;drivers/pci/dwc/pcie-designware.h +18
-0@@ -114,6 +114,7 @@*/ #define MAX_MSI_IRQS 32#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) +#define MSI_DEF_NUM_VECTORS 32/* Maximum number of inbound/outbound iATUs */ #define MAX_IATU_IN 256@@ -149,7 +150,9 @@ 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); +void (*set_num_vectors)(struct pcie_port *pp);int (*msi_host_init)(struct pcie_port *pp,struct msi_controller *chip); +void (*msi_irq_ack)(int irq,struct pcie_port *pp); };struct pcie_port {@@ -174,7 +177,11 @@ struct pcie_port {const struct dw_pcie_host_ops *ops;int msi_irq;struct irq_domain *irq_domain; +struct irq_domain *msi_domain;dma_addr_t msi_data; +u32 num_vectors; +u32 irq_status[MAX_MSI_CTRLS ]; +spinlock_t lock;DECLARE_BITMAP (msi_irq_in_use,MAX_MSI_IRQS ); };@@ -316,8 +323,10 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)#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 pcie_port *pp);#else static inline irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) {@@ -328,6 +337,10 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp) { } +static inline void dw_pcie_free_msi (struct pcie_port *pp) +{ +} +static inline void dw_pcie_setup_rc (struct pcie_port *pp) { }@@ -336,6 +349,11 @@ static inline int dw_pcie_host_init(struct pcie_port *pp) {return 0 ; } + +static inline int dw_pcie_allocate_domains (struct pcie_port *pp) +{ +return 0 ; +}#endif #ifdef CONFIG_PCIE_DW_EP drivers/pci/dwc/pcie-qcom.c +0
-16@@ -180,13 +180,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 int qcom_pcie_establish_link (struct qcom_pcie *pcie) {struct dw_pcie *pci = pcie->pci;@@ -1262,15 +1255,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 |IRQF_NO_THREAD , -"qcom-pcie-msi" , pp); -if (ret) { -dev_err (dev,"cannot request msi irq\n" ); -return ret; - } }
Quoted 5 lines
Quoted 5 lines
drivers/pci/dwc/pcie-qcom.c +0
-0ret =phy_init (pcie->phy);Signature · 1 line
2.7.4
Regards,
Gustavo
PATCH v9 2/3 PCI: dwc: Remove old IRQ API
In reply to Gustavo PimentelRemoves the unused old IRQ API from pcie-designware.
---
Change v1->v2:
- Nothing changed, just to follow the patch set version.
Change v2->v3:
- Nothing changed, just to follow the patch set version.
Change v3->v4:
- Patch renamed from v3-0008 to v4-0009.
- Changed summary line to match the drivers/PCI convention and changelog to maintain the consistency (thanks Bjorn).
Change v4->v5:
- Nothing changed, just to follow the patch set version.
Change v5->v6:
- Nothing changed, just to follow the patch set version.
Change v6->v7:
- Nothing changed, just to follow the patch set version.
Change v7->v8:
- Rebased against v4.16-rc1.
Change v8->v9:
- Changed patch indexation, due patch series squash.
drivers/pci/dwc/pci-keystone-dw.c | 2 +- drivers/pci/dwc/pci-keystone.h | 3 +- drivers/pci/dwc/pci-layerscape.c | 3 +- drivers/pci/dwc/pcie-designware-host.c | 190 +-------------------------------- drivers/pci/dwc/pcie-designware.h | 2 +- 5 files changed, 5 insertions(+), 195 deletions(-)
drivers/pci/dwc/pci-keystone-dw.c +1 -1
@@ -157,7 +157,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 pcie_port *pp,struct msi_controller *chip) +int ks_dw_pcie_msi_host_init (struct pcie_port *pp) {return dw_pcie_allocate_domains (pp); }
drivers/pci/dwc/pci-keystone.h +1 -2
@@ -53,6 +53,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 pcie_port *pp, -struct msi_controller *chip); +int ks_dw_pcie_msi_host_init (struct pcie_port *pp);int ks_dw_pcie_link_up (struct dw_pcie *pci);
drivers/pci/dwc/pci-layerscape.c +1 -2
@@ -182,8 +182,7 @@ static int ls1021_pcie_host_init(struct pcie_port *pp)return ls_pcie_host_init (pp); } -static int ls_pcie_msi_host_init (struct pcie_port *pp, -struct msi_controller *chip) +static int ls_pcie_msi_host_init (struct pcie_port *pp) {struct dw_pcie *pci =to_dw_pcie_from_pp (pp);struct device *dev = pci->dev;
drivers/pci/dwc/pcie-designware-host.c +1 -189
208 lines not on this page · raw message
drivers/pci/dwc/pcie-designware.h +1 -1
@@ -151,7 +151,7 @@ struct dw_pcie_host_ops {u32 (*get_msi_data)(struct pcie_port *pp,int pos);void (*scan_bus)(struct pcie_port *pp);void (*set_num_vectors)(struct pcie_port *pp); -int (*msi_host_init)(struct pcie_port *pp,struct msi_controller *chip); +int (*msi_host_init)(struct pcie_port *pp);void (*msi_irq_ack)(int irq,struct pcie_port *pp); };
Signature · 1 line
2.7.4
PATCH v9 3/3 PCI: dwc: Expand maximum number of IRQs from 32 to 256
In reply to Gustavo PimentelThe Synopsys PCIe Root Complex supports up to 256 IRQs distributed by 8 controller registers.
Having this in mind, the number of the maximum number of IRQs was changed to 256 and now the number of controllers is calculated based on the number of vectors used by the specific SoC driver.
---
Change v1->v2:
- New patch file.
Change v2->v3:
- Nothing changed, just to follow the patch set version.
Change v3->v4:
- Patch renamed from v3-0009 to v4-0010.
- Changed summary line to match the drivers/PCI convention and changelog to maintain the consistency (thanks Bjorn).
Change v4->v5:
- Nothing changed, just to follow the patch set version.
Change v5->v6:
- Nothing changed, just to follow the patch set version.
Change v6->v7:
- Nothing changed, just to follow the patch set version.
Change v7->v8:
- Rebased against v4.16-rc1.
Change v8->v9:
- Changed patch indexation, due patch series squash.
drivers/pci/dwc/pcie-designware-host.c | 12 ++++++++---- drivers/pci/dwc/pcie-designware.h | 10 +++------- 2 files changed, 11 insertions(+), 11 deletions(-)
drivers/pci/dwc/pcie-designware-host.c +8 -4
@@ -76,11 +76,13 @@ static struct msi_domain_info dw_pcie_msi_domain_info = {/* MSI int handler */ irqreturn_t dw_handle_msi_irq (struct pcie_port *pp) { -u32 val;int i, pos, irq; +u32 val, num_ctrls;irqreturn_t ret =IRQ_NONE ; -for (i =0 ; i <MAX_MSI_CTRLS ; i++) { + num_ctrls = pp->num_vectors /MAX_MSI_IRQS_PER_CTRL ; + +for (i =0 ; i < num_ctrls; i++) {dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_STATUS + i *12 ,4 , &val);if (!val)
@@ -641,13 +643,15 @@ static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)void dw_pcie_setup_rc (struct pcie_port *pp) { -u32 val, ctrl; +u32 val, ctrl, num_ctrls;struct dw_pcie *pci =to_dw_pcie_from_pp (pp);dw_pcie_setup (pci); + num_ctrls = pp->num_vectors /MAX_MSI_IRQS_PER_CTRL ; +/* Initialize IRQ Status array */ -for (ctrl =0 ; ctrl <MAX_MSI_CTRLS ; ctrl++) +for (ctrl =0 ; ctrl < num_ctrls; ctrl++)dw_pcie_rd_own_conf (pp,PCIE_MSI_INTR0_ENABLE + (ctrl *12 ),4 , &pp->irq_status[ctrl]);/* setup RC BARs */
drivers/pci/dwc/pcie-designware.h +3 -7
@@ -107,13 +107,9 @@#define MSI_MESSAGE_DATA_32 0x58#define MSI_MESSAGE_DATA_64 0x5C -/* -* Maximum number of MSI IRQs can be 256 per controller. But keep -* it 32 as of now. Probably we will never need more than 32. If needed, -* then increment it in multiple of 32. -*/ -#define MAX_MSI_IRQS 32 -#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) +#define MAX_MSI_IRQS 256 +#define MAX_MSI_IRQS_PER_CTRL 32 +#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL)#define MSI_DEF_NUM_VECTORS 32/* Maximum number of inbound/outbound iATUs */
Signature · 1 line
2.7.4
Quoted 16 lines · Gustavo Pimentel
Changes into a new IRQ handler mechanism (multiplexed IRQ domain hierarchy) more suitable and appropriate to use on pcie-designware and on each SoC specific driver in order to allow new and more complex features like MSI-X.
Adds Synopsys Root Complex driver support for MSI-X feature.
Expands the maximum number of IRQs from 32 to 256 distributed by a maximum of 8 controller registers.
The patch set was made against the Bjorn's master branch (v4.16-rc1).
Gustavo Pimentel (3):
PCI: dwc: Add new IRQ API
PCI: dwc: Remove old IRQ API
PCI: dwc: Expand maximum number of IRQs from 32 to 256
Quoted 13 lines
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 91 +------- 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-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 398 +++++++++++++++++++-------------- drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 30 ++- drivers/pci/dwc/pcie-qcom.c | 16 -- 11 files changed, 258 insertions(+), 355 deletions(-)
For the whole series:
There is certainly some more cleanups to be done, but that's a huge step in the right direction. Many thanks Gustavo and Joao for having stuck with it.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Quoted 16 lines · Gustavo Pimentel
Changes into a new IRQ handler mechanism (multiplexed IRQ domain hierarchy) more suitable and appropriate to use on pcie-designware and on each SoC specific driver in order to allow new and more complex features like MSI-X.
Adds Synopsys Root Complex driver support for MSI-X feature.
Expands the maximum number of IRQs from 32 to 256 distributed by a maximum of 8 controller registers.
The patch set was made against the Bjorn's master branch (v4.16-rc1).
Gustavo Pimentel (3):
PCI: dwc: Add new IRQ API
PCI: dwc: Remove old IRQ API
PCI: dwc: Expand maximum number of IRQs from 32 to 256
Quoted 12 lines
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 91 +------- 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-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 398 +++++++++++++++++++-------------- drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 30 ++- drivers/pci/dwc/pcie-qcom.c | 16 -- 11 files changed, 258 insertions(+), 355 deletions(-)
Patches queued with Marc's ACK in pci/dwc-msi for v4.17, please have a look to check everything is in order.
Thank you very much for putting it together, it is a nice stepping stone towards getting rid of struct msi_controller.
Thanks !
Lorenzo
[+cc Shawn, Vignesh, Pratyush]
Quoted 16 lines · Gustavo Pimentel
Changes into a new IRQ handler mechanism (multiplexed IRQ domain hierarchy) more suitable and appropriate to use on pcie-designware and on each SoC specific driver in order to allow new and more complex features like MSI-X.
Adds Synopsys Root Complex driver support for MSI-X feature.
Expands the maximum number of IRQs from 32 to 256 distributed by a maximum of 8 controller registers.
The patch set was made against the Bjorn's master branch (v4.16-rc1).
Gustavo Pimentel (3):
PCI: dwc: Add new IRQ API
PCI: dwc: Remove old IRQ API
PCI: dwc: Expand maximum number of IRQs from 32 to 256
Quoted 8 lines
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 91 +------- 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-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 398 +++++++++++++++++++--------------
Hi Gustavo,
I was reviewing a patch and this raised a question:
- why pcie-histb.c is not in the list of converted drivers above, given that it uses dw_handle_msi_irq() the same way as others you converted ?
Is it correct to leave pcie-histb.c as-is ? I do not think it is.
I also would like to get this tested on DRA7 and SPEAR13XX which are the other host drivers using dw_handle_msi_irq() (even though in a different way than pcie-histb.c).
The difference here seems to be struct pcie_port->msi_irq usage, that's extremely confusing how it is used (or not used) in the drivers I mentioned above.
I have CC'ed the related maintainers I need feedback and this needs testing; this series code is in my branch:
pci/dwc-msi
Thanks,
Lorenzo
Quoted 9 lines
drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 30 ++- drivers/pci/dwc/pcie-qcom.c | 16 -- 11 files changed, 258 insertions(+), 355 deletions(-)Signature · 1 line
2.7.4
Hi Lorenzo,
Quoted 29 lines · Lorenzo Pieralisi
[+cc Shawn, Vignesh, Pratyush]
Quoted 16 lines · Gustavo Pimentel
Changes into a new IRQ handler mechanism (multiplexed IRQ domain hierarchy) more suitable and appropriate to use on pcie-designware and on each SoC specific driver in order to allow new and more complex features like MSI-X.
Adds Synopsys Root Complex driver support for MSI-X feature.
Expands the maximum number of IRQs from 32 to 256 distributed by a maximum of 8 controller registers.
The patch set was made against the Bjorn's master branch (v4.16-rc1).
Gustavo Pimentel (3):
PCI: dwc: Add new IRQ API
PCI: dwc: Remove old IRQ API
PCI: dwc: Expand maximum number of IRQs from 32 to 256Quoted 8 lines
drivers/pci/dwc/pci-exynos.c | 18 -- drivers/pci/dwc/pci-imx6.c | 18 -- drivers/pci/dwc/pci-keystone-dw.c | 91 +------- 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-artpec6.c | 18 -- drivers/pci/dwc/pcie-designware-host.c | 398 +++++++++++++++++++--------------Hi Gustavo,
Quoted 7 lines
I was reviewing a patch and this raised a question:
- why
pcie-histb.cis not in the list of converted drivers above, given that it usesdw_handle_msi_irq()the same way as others you converted ?Is it correct to leave
pcie-histb.cas-is ? I do not think it is.
At the time the first series of this patch came out there wasn't such driver and I just start working on this topic on December... Nevertheless, you are right it should follow the same procedure that others.
drivers/pci/dwc/pcie-histb.c +0 -15
@@ -207,13 +207,6 @@ static struct dw_pcie_host_ops histb_pcie_host_ops = { .host_init = histb_pcie_host_init, }; -static irqreturn_t histb_pcie_msi_irq_handler (int irq,void *arg) -{ -struct pcie_port *pp = arg; - -return dw_handle_msi_irq (pp); -} -static void histb_pcie_host_disable (struct histb_pcie *hipcie) {reset_control_assert (hipcie->soft_reset);
@@ -393,14 +386,6 @@ static int histb_pcie_probe(struct platform_device *pdev)dev_err (dev,"Failed to get MSI IRQ\n" );return pp->msi_irq; } - - ret =devm_request_irq (dev, pp->msi_irq, - histb_pcie_msi_irq_handler, -IRQF_SHARED ,"histb-pcie-msi" , pp); -if (ret) { -dev_err (dev,"cannot request MSI IRQ\n" ); -return ret; - } } hipcie->phy =devm_phy_get (dev,"phy" );
Signature · 1 line
2.7.4
Quoted 4 lines
I also would like to get this tested on DRA7 and SPEAR13XX which are the other host drivers using
dw_handle_msi_irq()(even though in a different way thanpcie-histb.c).
I think Kishon has already tested, however he never added the tested-by.
Quoted 5 lines
The difference here seems to be struct
pcie_port->msi_irqusage, that's extremely confusing how it is used (or not used) in the drivers I mentioned above.
Quoted 17 lines
I have CC'ed the related maintainers I need feedback and this needs testing; this series code is in my branch:
pci/dwc-msi
Thanks,
LorenzoQuoted 9 lines
drivers/pci/dwc/pcie-designware-plat.c | 16 -- drivers/pci/dwc/pcie-designware.h | 30 ++- drivers/pci/dwc/pcie-qcom.c | 16 -- 11 files changed, 258 insertions(+), 355 deletions(-)Signature · 1 line
2.7.4
Thanks,
Gustavo
Shawn Guo
Tested-byQuoted 2 lines · Gustavo Pimentel
Quoted 1 line · Lorenzo Pieralisi
[+cc Shawn, Vignesh, Pratyush]
...
Quoted 29 lines
Quoted 1 line
Is it correct to leave
pcie-histb.cas-is ? I do not think it is.At the time the first series of this patch came out there wasn't such driver and I just start working on this topic on December... Nevertheless, you are right it should follow the same procedure that others.
drivers/pci/dwc/pcie-histb.c +0
-8@@ -207,13 +207,6 @@ static struct dw_pcie_host_ops histb_pcie_host_ops = { .host_init = histb_pcie_host_init, }; -static irqreturn_t histb_pcie_msi_irq_handler (int irq,void *arg) -{ -struct pcie_port *pp = arg; - -return dw_handle_msi_irq (pp); -} -static void histb_pcie_host_disable (struct histb_pcie *hipcie) {reset_control_assert (hipcie->soft_reset);@@ -393,14 +386,6 @@ static int histb_pcie_probe(struct platform_device *pdev)dev_err (dev,"Failed to get MSI IRQ\n" );return pp->msi_irq; } -
drivers/pci/dwc/pcie-histb.c static int histb_pcie_probe(struct platform_device *pdev) · line 391
Quoted 10 lines
drivers/pci/dwc/pcie-histb.c +0
-7- ret =devm_request_irq (dev, pp->msi_irq, - histb_pcie_msi_irq_handler, -IRQF_SHARED ,"histb-pcie-msi" , pp); -if (ret) { -dev_err (dev,"cannot request MSI IRQ\n" ); -return ret; - } } hipcie->phy =devm_phy_get (dev,"phy" );
I manually applied the changes on top of Lorenzo's pci/dwc-msi branch, and pcie-histb driver still works fine.