Loading drivers/pci/host/pci-msm-msi.c +57 −19 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/msi.h> #include <linux/msm_pcie.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_pci.h> Loading Loading @@ -56,7 +57,6 @@ struct msm_msi_grp { void __iomem *int_mask_reg; void __iomem *int_status_reg; u32 mask; /* tracks masked/unmasked MSI */ spinlock_t cfg_lock; /* lock for configuring Synopsys MSI registers */ struct msm_msi_irq irqs[MSI_IRQ_PER_GRP]; }; Loading @@ -75,6 +75,8 @@ struct msm_msi { struct irq_domain *msi_domain; /* child domain; pci related */ phys_addr_t msi_addr; enum msi_type type; spinlock_t cfg_lock; /* lock for configuring Synopsys MSI registers */ bool cfg_access; /* control access to Synopsys MSI registers */ void __iomem *pcie_cfg; void (*mask_irq)(struct irq_data *data); Loading @@ -94,9 +96,6 @@ static void msm_msi_snps_handler(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct msm_msi *msi; struct msm_msi_grp *msi_grp; unsigned long val = 0; u32 index; int i; chained_irq_enter(chip, desc); Loading @@ -104,12 +103,25 @@ static void msm_msi_snps_handler(struct irq_desc *desc) msi = irq_desc_get_handler_data(desc); for (i = 0; i < msi->nr_grps; i++) { msi_grp = &msi->grps[i]; val = readl_relaxed(msi_grp->int_status_reg); writel_relaxed(val, msi_grp->int_status_reg); struct msm_msi_grp *msi_grp = &msi->grps[i]; u32 mask = msi_grp->mask; u32 status; u32 index; status = readl_relaxed(msi_grp->int_status_reg); if (!status) continue; for (index = 0; val; index++, val >>= 1) if (val & 0x1) /* always update the mask set in msm_msi_snps_mask_irq */ mask = msi_grp->mask; writel_relaxed(mask, msi_grp->int_mask_reg); /* process only interrupts which are not masked */ status ^= (status & mask); writel_relaxed(status, msi_grp->int_status_reg); for (index = 0; status; index++, status >>= 1) if (status & 0x1) generic_handle_irq(msi_grp->irqs[index].virq); } Loading @@ -136,12 +148,12 @@ static void msm_msi_snps_mask_irq(struct irq_data *data) { struct msm_msi_irq *msi_irq = irq_data_get_irq_chip_data(data); struct msm_msi_grp *msi_grp = msi_irq->grp; struct msm_msi *msi = msi_irq->client->msi; unsigned long flags; spin_lock_irqsave(&msi_grp->cfg_lock, flags); spin_lock_irqsave(&msi->cfg_lock, flags); msi_grp->mask |= BIT(msi_irq->grp_index); writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); spin_unlock_irqrestore(&msi_grp->cfg_lock, flags); spin_unlock_irqrestore(&msi->cfg_lock, flags); } static void msm_msi_qgic_mask_irq(struct irq_data *data) Loading Loading @@ -176,12 +188,16 @@ static void msm_msi_snps_unmask_irq(struct irq_data *data) { struct msm_msi_irq *msi_irq = irq_data_get_irq_chip_data(data); struct msm_msi_grp *msi_grp = msi_irq->grp; struct msm_msi *msi = msi_irq->client->msi; unsigned long flags; spin_lock_irqsave(&msi_grp->cfg_lock, flags); spin_lock_irqsave(&msi->cfg_lock, flags); msi_grp->mask &= ~BIT(msi_irq->grp_index); if (msi->cfg_access) writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); spin_unlock_irqrestore(&msi_grp->cfg_lock, flags); spin_unlock_irqrestore(&msi->cfg_lock, flags); } static void msm_msi_qgic_unmask_irq(struct irq_data *data) Loading Loading @@ -457,6 +473,21 @@ static int msm_msi_alloc_domains(struct msm_msi *msi) return 0; } /* control access to Synopsys PCIe MSI registers */ void msm_msi_config_access(struct irq_domain *domain, bool allow) { struct msm_msi *msi = domain->parent->host_data; unsigned long flags; if (msi->type == MSM_MSI_TYPE_QCOM) return; spin_lock_irqsave(&msi->cfg_lock, flags); msi->cfg_access = allow; spin_unlock_irqrestore(&msi->cfg_lock, flags); } EXPORT_SYMBOL(msm_msi_config_access); /* configure Synopsys PCIe MSI registers */ void msm_msi_config(struct irq_domain *domain) { Loading @@ -467,13 +498,20 @@ void msm_msi_config(struct irq_domain *domain) if (msi->type == MSM_MSI_TYPE_QCOM) return; /* PCIe core driver sets to false during LPM */ msm_msi_config_access(domain, true); /* program MSI termination address */ writel_relaxed(msi->msi_addr, msi->pcie_cfg + PCIE_MSI_CTRL_ADDR_OFFS); writel_relaxed(0, msi->pcie_cfg + PCIE_MSI_CTRL_UPPER_ADDR_OFFS); /* enable all interrupts for each group */ for (i = 0; i < msi->nr_grps; i++) writel_relaxed(~0, msi->grps[i].int_en_reg); /* restore mask and enable all interrupts for each group */ for (i = 0; i < msi->nr_grps; i++) { struct msm_msi_grp *msi_grp = &msi->grps[i]; writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); writel_relaxed(~0, msi_grp->int_en_reg); } } EXPORT_SYMBOL(msm_msi_config); Loading Loading @@ -514,6 +552,7 @@ int msm_msi_init(struct device *dev) msi->dev = dev; msi->of_node = of_node; mutex_init(&msi->mutex); spin_lock_init(&msi->cfg_lock); INIT_LIST_HEAD(&msi->clients); prop_val = of_get_address(msi->of_node, 0, NULL, NULL); Loading Loading @@ -613,7 +652,6 @@ int msm_msi_init(struct device *dev) for (i = 0; i < msi->nr_grps; i++) { msi_grp = &msi->grps[i]; spin_lock_init(&msi_grp->cfg_lock); msi_grp->int_en_reg = msi->pcie_cfg + PCIE_MSI_CTRL_INT_N_EN_OFFS(i); msi_grp->int_mask_reg = msi->pcie_cfg + Loading drivers/pci/host/pci-msm.c +3 −0 Original line number Diff line number Diff line Loading @@ -4180,6 +4180,9 @@ static void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) return; } /* suspend access to MSI register. resume access in msm_msi_config */ msm_msi_config_access(dev_get_msi_domain(&dev->dev->dev), false); dev->link_status = MSM_PCIE_LINK_DISABLED; dev->power_on = false; dev->link_turned_off_counter++; Loading include/linux/msm_pcie.h +5 −0 Original line number Diff line number Diff line Loading @@ -61,9 +61,14 @@ struct msm_pcie_register_event { }; #ifdef CONFIG_PCI_MSM_MSI void msm_msi_config_access(struct irq_domain *domain, bool allow); void msm_msi_config(struct irq_domain *domain); int msm_msi_init(struct device *dev); #else static inline void msm_msi_config_access(struct irq_domain *domain, bool allow) { } static inline void msm_msi_config(struct irq_domain *domain) { } Loading Loading
drivers/pci/host/pci-msm-msi.c +57 −19 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/msi.h> #include <linux/msm_pcie.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_pci.h> Loading Loading @@ -56,7 +57,6 @@ struct msm_msi_grp { void __iomem *int_mask_reg; void __iomem *int_status_reg; u32 mask; /* tracks masked/unmasked MSI */ spinlock_t cfg_lock; /* lock for configuring Synopsys MSI registers */ struct msm_msi_irq irqs[MSI_IRQ_PER_GRP]; }; Loading @@ -75,6 +75,8 @@ struct msm_msi { struct irq_domain *msi_domain; /* child domain; pci related */ phys_addr_t msi_addr; enum msi_type type; spinlock_t cfg_lock; /* lock for configuring Synopsys MSI registers */ bool cfg_access; /* control access to Synopsys MSI registers */ void __iomem *pcie_cfg; void (*mask_irq)(struct irq_data *data); Loading @@ -94,9 +96,6 @@ static void msm_msi_snps_handler(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct msm_msi *msi; struct msm_msi_grp *msi_grp; unsigned long val = 0; u32 index; int i; chained_irq_enter(chip, desc); Loading @@ -104,12 +103,25 @@ static void msm_msi_snps_handler(struct irq_desc *desc) msi = irq_desc_get_handler_data(desc); for (i = 0; i < msi->nr_grps; i++) { msi_grp = &msi->grps[i]; val = readl_relaxed(msi_grp->int_status_reg); writel_relaxed(val, msi_grp->int_status_reg); struct msm_msi_grp *msi_grp = &msi->grps[i]; u32 mask = msi_grp->mask; u32 status; u32 index; status = readl_relaxed(msi_grp->int_status_reg); if (!status) continue; for (index = 0; val; index++, val >>= 1) if (val & 0x1) /* always update the mask set in msm_msi_snps_mask_irq */ mask = msi_grp->mask; writel_relaxed(mask, msi_grp->int_mask_reg); /* process only interrupts which are not masked */ status ^= (status & mask); writel_relaxed(status, msi_grp->int_status_reg); for (index = 0; status; index++, status >>= 1) if (status & 0x1) generic_handle_irq(msi_grp->irqs[index].virq); } Loading @@ -136,12 +148,12 @@ static void msm_msi_snps_mask_irq(struct irq_data *data) { struct msm_msi_irq *msi_irq = irq_data_get_irq_chip_data(data); struct msm_msi_grp *msi_grp = msi_irq->grp; struct msm_msi *msi = msi_irq->client->msi; unsigned long flags; spin_lock_irqsave(&msi_grp->cfg_lock, flags); spin_lock_irqsave(&msi->cfg_lock, flags); msi_grp->mask |= BIT(msi_irq->grp_index); writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); spin_unlock_irqrestore(&msi_grp->cfg_lock, flags); spin_unlock_irqrestore(&msi->cfg_lock, flags); } static void msm_msi_qgic_mask_irq(struct irq_data *data) Loading Loading @@ -176,12 +188,16 @@ static void msm_msi_snps_unmask_irq(struct irq_data *data) { struct msm_msi_irq *msi_irq = irq_data_get_irq_chip_data(data); struct msm_msi_grp *msi_grp = msi_irq->grp; struct msm_msi *msi = msi_irq->client->msi; unsigned long flags; spin_lock_irqsave(&msi_grp->cfg_lock, flags); spin_lock_irqsave(&msi->cfg_lock, flags); msi_grp->mask &= ~BIT(msi_irq->grp_index); if (msi->cfg_access) writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); spin_unlock_irqrestore(&msi_grp->cfg_lock, flags); spin_unlock_irqrestore(&msi->cfg_lock, flags); } static void msm_msi_qgic_unmask_irq(struct irq_data *data) Loading Loading @@ -457,6 +473,21 @@ static int msm_msi_alloc_domains(struct msm_msi *msi) return 0; } /* control access to Synopsys PCIe MSI registers */ void msm_msi_config_access(struct irq_domain *domain, bool allow) { struct msm_msi *msi = domain->parent->host_data; unsigned long flags; if (msi->type == MSM_MSI_TYPE_QCOM) return; spin_lock_irqsave(&msi->cfg_lock, flags); msi->cfg_access = allow; spin_unlock_irqrestore(&msi->cfg_lock, flags); } EXPORT_SYMBOL(msm_msi_config_access); /* configure Synopsys PCIe MSI registers */ void msm_msi_config(struct irq_domain *domain) { Loading @@ -467,13 +498,20 @@ void msm_msi_config(struct irq_domain *domain) if (msi->type == MSM_MSI_TYPE_QCOM) return; /* PCIe core driver sets to false during LPM */ msm_msi_config_access(domain, true); /* program MSI termination address */ writel_relaxed(msi->msi_addr, msi->pcie_cfg + PCIE_MSI_CTRL_ADDR_OFFS); writel_relaxed(0, msi->pcie_cfg + PCIE_MSI_CTRL_UPPER_ADDR_OFFS); /* enable all interrupts for each group */ for (i = 0; i < msi->nr_grps; i++) writel_relaxed(~0, msi->grps[i].int_en_reg); /* restore mask and enable all interrupts for each group */ for (i = 0; i < msi->nr_grps; i++) { struct msm_msi_grp *msi_grp = &msi->grps[i]; writel_relaxed(msi_grp->mask, msi_grp->int_mask_reg); writel_relaxed(~0, msi_grp->int_en_reg); } } EXPORT_SYMBOL(msm_msi_config); Loading Loading @@ -514,6 +552,7 @@ int msm_msi_init(struct device *dev) msi->dev = dev; msi->of_node = of_node; mutex_init(&msi->mutex); spin_lock_init(&msi->cfg_lock); INIT_LIST_HEAD(&msi->clients); prop_val = of_get_address(msi->of_node, 0, NULL, NULL); Loading Loading @@ -613,7 +652,6 @@ int msm_msi_init(struct device *dev) for (i = 0; i < msi->nr_grps; i++) { msi_grp = &msi->grps[i]; spin_lock_init(&msi_grp->cfg_lock); msi_grp->int_en_reg = msi->pcie_cfg + PCIE_MSI_CTRL_INT_N_EN_OFFS(i); msi_grp->int_mask_reg = msi->pcie_cfg + Loading
drivers/pci/host/pci-msm.c +3 −0 Original line number Diff line number Diff line Loading @@ -4180,6 +4180,9 @@ static void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) return; } /* suspend access to MSI register. resume access in msm_msi_config */ msm_msi_config_access(dev_get_msi_domain(&dev->dev->dev), false); dev->link_status = MSM_PCIE_LINK_DISABLED; dev->power_on = false; dev->link_turned_off_counter++; Loading
include/linux/msm_pcie.h +5 −0 Original line number Diff line number Diff line Loading @@ -61,9 +61,14 @@ struct msm_pcie_register_event { }; #ifdef CONFIG_PCI_MSM_MSI void msm_msi_config_access(struct irq_domain *domain, bool allow); void msm_msi_config(struct irq_domain *domain); int msm_msi_init(struct device *dev); #else static inline void msm_msi_config_access(struct irq_domain *domain, bool allow) { } static inline void msm_msi_config(struct irq_domain *domain) { } Loading