diff options
author | Li Yang <leoli@freescale.com> | 2010-04-22 04:31:35 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2010-05-24 22:26:31 -0400 |
commit | 02adac6051b0ff8df3877ae3d94e0e68063c6a30 (patch) | |
tree | a765f0123b46e3fe0989a0808e37abe50d180f7c /arch/powerpc/sysdev | |
parent | 8081881327d4791f26ebf56cf304992673503ad4 (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.c | 33 |
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 | ||
27 | struct fsl_msi_feature { | 28 | struct fsl_msi_feature { |
@@ -29,6 +30,10 @@ struct fsl_msi_feature { | |||
29 | u32 msiir_offset; | 30 | u32 msiir_offset; |
30 | }; | 31 | }; |
31 | 32 | ||
33 | struct fsl_msi_cascade_data { | ||
34 | struct fsl_msi *msi_data; | ||
35 | int index; | ||
36 | }; | ||
32 | 37 | ||
33 | static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) | 38 | static 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 | ||
134 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 139 | static 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: | |||
173 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | 179 | static 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 | ||