aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 3482e3fd89c0..c84fbb1c1b42 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. 2 * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
3 * 3 *
4 * Author: Tony Li <tony.li@freescale.com> 4 * Author: Tony Li <tony.li@freescale.com>
5 * Jason Jin <Jason.jin@freescale.com> 5 * Jason Jin <Jason.jin@freescale.com>
@@ -29,7 +29,6 @@ struct fsl_msi_feature {
29 u32 msiir_offset; 29 u32 msiir_offset;
30}; 30};
31 31
32static struct fsl_msi *fsl_msi;
33 32
34static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) 33static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
35{ 34{
@@ -54,10 +53,12 @@ static struct irq_chip fsl_msi_chip = {
54static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, 53static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
55 irq_hw_number_t hw) 54 irq_hw_number_t hw)
56{ 55{
56 struct fsl_msi *msi_data = h->host_data;
57 struct irq_chip *chip = &fsl_msi_chip; 57 struct irq_chip *chip = &fsl_msi_chip;
58 58
59 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; 59 irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
60 60
61 set_irq_chip_data(virq, msi_data);
61 set_irq_chip_and_handler(virq, chip, handle_edge_irq); 62 set_irq_chip_and_handler(virq, chip, handle_edge_irq);
62 63
63 return 0; 64 return 0;
@@ -96,11 +97,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
96static void fsl_teardown_msi_irqs(struct pci_dev *pdev) 97static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
97{ 98{
98 struct msi_desc *entry; 99 struct msi_desc *entry;
99 struct fsl_msi *msi_data = fsl_msi; 100 struct fsl_msi *msi_data;
100 101
101 list_for_each_entry(entry, &pdev->msi_list, list) { 102 list_for_each_entry(entry, &pdev->msi_list, list) {
102 if (entry->irq == NO_IRQ) 103 if (entry->irq == NO_IRQ)
103 continue; 104 continue;
105 msi_data = get_irq_chip_data(entry->irq);
104 set_irq_msi(entry->irq, NULL); 106 set_irq_msi(entry->irq, NULL);
105 msi_bitmap_free_hwirqs(&msi_data->bitmap, 107 msi_bitmap_free_hwirqs(&msi_data->bitmap,
106 virq_to_hw(entry->irq), 1); 108 virq_to_hw(entry->irq), 1);
@@ -111,9 +113,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
111} 113}
112 114
113static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, 115static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
114 struct msi_msg *msg) 116 struct msi_msg *msg,
117 struct fsl_msi *fsl_msi_data)
115{ 118{
116 struct fsl_msi *msi_data = fsl_msi; 119 struct fsl_msi *msi_data = fsl_msi_data;
117 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 120 struct pci_controller *hose = pci_bus_to_host(pdev->bus);
118 u32 base = 0; 121 u32 base = 0;
119 122
@@ -134,9 +137,11 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
134 unsigned int virq; 137 unsigned int virq;
135 struct msi_desc *entry; 138 struct msi_desc *entry;
136 struct msi_msg msg; 139 struct msi_msg msg;
137 struct fsl_msi *msi_data = fsl_msi; 140 struct fsl_msi *msi_data;
138 141
139 list_for_each_entry(entry, &pdev->msi_list, list) { 142 list_for_each_entry(entry, &pdev->msi_list, list) {
143 msi_data = get_irq_chip_data(entry->irq);
144
140 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 145 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
141 if (hwirq < 0) { 146 if (hwirq < 0) {
142 rc = hwirq; 147 rc = hwirq;
@@ -156,7 +161,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
156 } 161 }
157 set_irq_msi(virq, entry); 162 set_irq_msi(virq, entry);
158 163
159 fsl_compose_msi_msg(pdev, hwirq, &msg); 164 fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
160 write_msi_msg(virq, &msg); 165 write_msi_msg(virq, &msg);
161 } 166 }
162 return 0; 167 return 0;
@@ -168,7 +173,7 @@ out_free:
168static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) 173static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
169{ 174{
170 unsigned int cascade_irq; 175 unsigned int cascade_irq;
171 struct fsl_msi *msi_data = fsl_msi; 176 struct fsl_msi *msi_data = get_irq_chip_data(irq);
172 int msir_index = -1; 177 int msir_index = -1;
173 u32 msir_value = 0; 178 u32 msir_value = 0;
174 u32 intr_index; 179 u32 intr_index;
@@ -193,7 +198,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
193 cascade_irq = NO_IRQ; 198 cascade_irq = NO_IRQ;
194 199
195 desc->status |= IRQ_INPROGRESS; 200 desc->status |= IRQ_INPROGRESS;
196 switch (fsl_msi->feature & FSL_PIC_IP_MASK) { 201 switch (msi_data->feature & FSL_PIC_IP_MASK) {
197 case FSL_PIC_IP_MPIC: 202 case FSL_PIC_IP_MPIC:
198 msir_value = fsl_msi_read(msi_data->msi_regs, 203 msir_value = fsl_msi_read(msi_data->msi_regs,
199 msir_index * 0x10); 204 msir_index * 0x10);
@@ -307,15 +312,20 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
307 if (virt_msir != NO_IRQ) { 312 if (virt_msir != NO_IRQ) {
308 set_irq_data(virt_msir, (void *)i); 313 set_irq_data(virt_msir, (void *)i);
309 set_irq_chained_handler(virt_msir, fsl_msi_cascade); 314 set_irq_chained_handler(virt_msir, fsl_msi_cascade);
315 set_irq_chip_data(virt_msir, msi);
310 } 316 }
311 } 317 }
312 318
313 fsl_msi = msi; 319 /* The multiple setting ppc_md.setup_msi_irqs will not harm things */
314 320 if (!ppc_md.setup_msi_irqs) {
315 WARN_ON(ppc_md.setup_msi_irqs); 321 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
316 ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; 322 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
317 ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; 323 ppc_md.msi_check_device = fsl_msi_check_device;
318 ppc_md.msi_check_device = fsl_msi_check_device; 324 } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
325 dev_err(&dev->dev, "Different MSI driver already installed!\n");
326 err = -ENODEV;
327 goto error_out;
328 }
319 return 0; 329 return 0;
320error_out: 330error_out:
321 kfree(msi); 331 kfree(msi);