aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2010-04-22 04:31:35 -0400
committerKumar Gala <galak@kernel.crashing.org>2010-05-24 22:26:31 -0400
commit02adac6051b0ff8df3877ae3d94e0e68063c6a30 (patch)
treea765f0123b46e3fe0989a0808e37abe50d180f7c /arch/powerpc/sysdev
parent8081881327d4791f26ebf56cf304992673503ad4 (diff)
powerpc/fsl_msi: fix the conflict of virt_msir's chip_data
In fsl_of_msi_probe(), the virt_msir's chip_data have been stored the pointer to struct mpic. We add a struct fsl_msi_cascade_data to store the pointer to struct fsl_msi and msir_index in hanler_data. Otherwise, the pointer to struct mpic will be over-written, and will cause problem when calling eoi() of the irq. Signed-off-by: Zhao Chenhui <b26998@freescale.com> Signed-off-by: Li Yang <leoli@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index c84fbb1c1b42..b769982612a0 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -22,6 +22,7 @@
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/hw_irq.h> 23#include <asm/hw_irq.h>
24#include <asm/ppc-pci.h> 24#include <asm/ppc-pci.h>
25#include <asm/mpic.h>
25#include "fsl_msi.h" 26#include "fsl_msi.h"
26 27
27struct fsl_msi_feature { 28struct fsl_msi_feature {
@@ -29,6 +30,10 @@ struct fsl_msi_feature {
29 u32 msiir_offset; 30 u32 msiir_offset;
30}; 31};
31 32
33struct fsl_msi_cascade_data {
34 struct fsl_msi *msi_data;
35 int index;
36};
32 37
33static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) 38static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
34{ 39{
@@ -102,7 +107,7 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
102 list_for_each_entry(entry, &pdev->msi_list, list) { 107 list_for_each_entry(entry, &pdev->msi_list, list) {
103 if (entry->irq == NO_IRQ) 108 if (entry->irq == NO_IRQ)
104 continue; 109 continue;
105 msi_data = get_irq_chip_data(entry->irq); 110 msi_data = get_irq_data(entry->irq);
106 set_irq_msi(entry->irq, NULL); 111 set_irq_msi(entry->irq, NULL);
107 msi_bitmap_free_hwirqs(&msi_data->bitmap, 112 msi_bitmap_free_hwirqs(&msi_data->bitmap,
108 virq_to_hw(entry->irq), 1); 113 virq_to_hw(entry->irq), 1);
@@ -133,7 +138,7 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
133 138
134static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 139static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
135{ 140{
136 int rc, hwirq; 141 int rc, hwirq = NO_IRQ;
137 unsigned int virq; 142 unsigned int virq;
138 struct msi_desc *entry; 143 struct msi_desc *entry;
139 struct msi_msg msg; 144 struct msi_msg msg;
@@ -159,6 +164,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
159 rc = -ENOSPC; 164 rc = -ENOSPC;
160 goto out_free; 165 goto out_free;
161 } 166 }
167 set_irq_data(virq, msi_data);
162 set_irq_msi(virq, entry); 168 set_irq_msi(virq, entry);
163 169
164 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data); 170 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
@@ -173,11 +179,15 @@ out_free:
173static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 179static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
174{ 180{
175 unsigned int cascade_irq; 181 unsigned int cascade_irq;
176 struct fsl_msi *msi_data = get_irq_chip_data(irq); 182 struct fsl_msi *msi_data;
177 int msir_index = -1; 183 int msir_index = -1;
178 u32 msir_value = 0; 184 u32 msir_value = 0;
179 u32 intr_index; 185 u32 intr_index;
180 u32 have_shift = 0; 186 u32 have_shift = 0;
187 struct fsl_msi_cascade_data *cascade_data;
188
189 cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
190 msi_data = cascade_data->msi_data;
181 191
182 raw_spin_lock(&desc->lock); 192 raw_spin_lock(&desc->lock);
183 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { 193 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
@@ -192,7 +202,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
192 if (unlikely(desc->status & IRQ_INPROGRESS)) 202 if (unlikely(desc->status & IRQ_INPROGRESS))
193 goto unlock; 203 goto unlock;
194 204
195 msir_index = (int)desc->handler_data; 205 msir_index = cascade_data->index;
196 206
197 if (msir_index >= NR_MSI_REG) 207 if (msir_index >= NR_MSI_REG)
198 cascade_irq = NO_IRQ; 208 cascade_irq = NO_IRQ;
@@ -244,6 +254,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
244 int virt_msir; 254 int virt_msir;
245 const u32 *p; 255 const u32 *p;
246 struct fsl_msi_feature *features = match->data; 256 struct fsl_msi_feature *features = match->data;
257 struct fsl_msi_cascade_data *cascade_data = NULL;
247 258
248 printk(KERN_DEBUG "Setting up Freescale MSI support\n"); 259 printk(KERN_DEBUG "Setting up Freescale MSI support\n");
249 260
@@ -310,9 +321,19 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
310 break; 321 break;
311 virt_msir = irq_of_parse_and_map(dev->node, i); 322 virt_msir = irq_of_parse_and_map(dev->node, i);
312 if (virt_msir != NO_IRQ) { 323 if (virt_msir != NO_IRQ) {
313 set_irq_data(virt_msir, (void *)i); 324 cascade_data = kzalloc(
325 sizeof(struct fsl_msi_cascade_data),
326 GFP_KERNEL);
327 if (!cascade_data) {
328 dev_err(&dev->dev,
329 "No memory for MSI cascade data\n");
330 err = -ENOMEM;
331 goto error_out;
332 }
333 cascade_data->index = i;
334 cascade_data->msi_data = msi;
335 set_irq_data(virt_msir, (void *)cascade_data);
314 set_irq_chained_handler(virt_msir, fsl_msi_cascade); 336 set_irq_chained_handler(virt_msir, fsl_msi_cascade);
315 set_irq_chip_data(virt_msir, msi);
316 } 337 }
317 } 338 }
318 339