diff options
| -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 | ||
