cdd76eed1ca4bf84b0757d8ba6d2cd96e94ec04b
[openwrt/staging/jogo.git] /
1 From 7f353accca6e4a3222991c65b1a6801503973bd3 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
3 Date: Fri, 2 Jul 2021 16:44:10 +0200
4 Subject: [PATCH] PCI: aardvark: Add support for masking MSI interrupts
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 We should not unmask MSIs at setup, but only when kernel asks for them
10 to be unmasked.
11
12 At setup, mask all MSIs, and implement IRQ chip callbacks for masking
13 and unmasking particular MSIs.
14
15 Signed-off-by: Pali Rohár <pali@kernel.org>
16 Signed-off-by: Marek Behún <kabel@kernel.org>
17 ---
18 drivers/pci/controller/pci-aardvark.c | 54 ++++++++++++++++++++++++---
19 1 file changed, 49 insertions(+), 5 deletions(-)
20
21 diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
22 index 5c887772fa97..43db884c81a1 100644
23 --- a/drivers/pci/controller/pci-aardvark.c
24 +++ b/drivers/pci/controller/pci-aardvark.c
25 @@ -281,6 +281,7 @@ struct advk_pcie {
26 raw_spinlock_t irq_lock;
27 struct irq_domain *msi_domain;
28 struct irq_domain *msi_inner_domain;
29 + raw_spinlock_t msi_irq_lock;
30 DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
31 struct mutex msi_used_lock;
32 u16 msi_msg;
33 @@ -577,12 +578,10 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
34 advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
35 advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
36
37 - /* Disable All ISR0/1 Sources */
38 + /* Disable All ISR0/1 and MSI Sources */
39 advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG);
40 advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
41 -
42 - /* Unmask all MSIs */
43 - advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
44 + advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
45
46 /* Unmask summary MSI interrupt */
47 reg = advk_readl(pcie, PCIE_ISR0_MASK_REG);
48 @@ -1196,10 +1195,52 @@ static int advk_msi_set_affinity(struct irq_data *irq_data,
49 return -EINVAL;
50 }
51
52 +static void advk_msi_irq_mask(struct irq_data *d)
53 +{
54 + struct advk_pcie *pcie = d->domain->host_data;
55 + irq_hw_number_t hwirq = irqd_to_hwirq(d);
56 + unsigned long flags;
57 + u32 mask;
58 +
59 + raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
60 + mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
61 + mask |= BIT(hwirq);
62 + advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
63 + raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
64 +}
65 +
66 +static void advk_msi_irq_unmask(struct irq_data *d)
67 +{
68 + struct advk_pcie *pcie = d->domain->host_data;
69 + irq_hw_number_t hwirq = irqd_to_hwirq(d);
70 + unsigned long flags;
71 + u32 mask;
72 +
73 + raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags);
74 + mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
75 + mask &= ~BIT(hwirq);
76 + advk_writel(pcie, mask, PCIE_MSI_MASK_REG);
77 + raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags);
78 +}
79 +
80 +static void advk_msi_top_irq_mask(struct irq_data *d)
81 +{
82 + pci_msi_mask_irq(d);
83 + irq_chip_mask_parent(d);
84 +}
85 +
86 +static void advk_msi_top_irq_unmask(struct irq_data *d)
87 +{
88 + pci_msi_unmask_irq(d);
89 + irq_chip_unmask_parent(d);
90 +}
91 +
92 static struct irq_chip advk_msi_bottom_irq_chip = {
93 .name = "MSI",
94 .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg,
95 .irq_set_affinity = advk_msi_set_affinity,
96 + .irq_mask = advk_msi_irq_mask,
97 + .irq_unmask = advk_msi_irq_unmask,
98 };
99
100 static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
101 @@ -1289,7 +1330,9 @@ static const struct irq_domain_ops advk_pcie_irq_domain_ops = {
102 };
103
104 static struct irq_chip advk_msi_irq_chip = {
105 - .name = "advk-MSI",
106 + .name = "advk-MSI",
107 + .irq_mask = advk_msi_top_irq_mask,
108 + .irq_unmask = advk_msi_top_irq_unmask,
109 };
110
111 static struct msi_domain_info advk_msi_domain_info = {
112 @@ -1303,6 +1346,7 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
113 struct device *dev = &pcie->pdev->dev;
114 phys_addr_t msi_msg_phys;
115
116 + raw_spin_lock_init(&pcie->msi_irq_lock);
117 mutex_init(&pcie->msi_used_lock);
118
119 msi_msg_phys = virt_to_phys(&pcie->msi_msg);
120 --
121 2.34.1
122