diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index e5c344d336ea..89548e07ddeb 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -148,14 +148,47 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
148 | 148 | ||
149 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 149 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
150 | { | 150 | { |
151 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
152 | struct device_node *np; | ||
153 | phandle phandle = 0; | ||
151 | int rc, hwirq = -ENOMEM; | 154 | int rc, hwirq = -ENOMEM; |
152 | unsigned int virq; | 155 | unsigned int virq; |
153 | struct msi_desc *entry; | 156 | struct msi_desc *entry; |
154 | struct msi_msg msg; | 157 | struct msi_msg msg; |
155 | struct fsl_msi *msi_data; | 158 | struct fsl_msi *msi_data; |
156 | 159 | ||
160 | /* | ||
161 | * If the PCI node has an fsl,msi property, then we need to use it | ||
162 | * to find the specific MSI. | ||
163 | */ | ||
164 | np = of_parse_phandle(hose->dn, "fsl,msi", 0); | ||
165 | if (np) { | ||
166 | if (of_device_is_compatible(np, "fsl,mpic-msi")) | ||
167 | phandle = np->phandle; | ||
168 | else { | ||
169 | dev_err(&pdev->dev, "node %s has an invalid fsl,msi" | ||
170 | " phandle\n", hose->dn->full_name); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | } | ||
174 | |||
157 | list_for_each_entry(entry, &pdev->msi_list, list) { | 175 | list_for_each_entry(entry, &pdev->msi_list, list) { |
176 | /* | ||
177 | * Loop over all the MSI devices until we find one that has an | ||
178 | * available interrupt. | ||
179 | */ | ||
158 | list_for_each_entry(msi_data, &msi_head, list) { | 180 | list_for_each_entry(msi_data, &msi_head, list) { |
181 | /* | ||
182 | * If the PCI node has an fsl,msi property, then we | ||
183 | * restrict our search to the corresponding MSI node. | ||
184 | * The simplest way is to skip over MSI nodes with the | ||
185 | * wrong phandle. Under the Freescale hypervisor, this | ||
186 | * has the additional benefit of skipping over MSI | ||
187 | * nodes that are not mapped in the PAMU. | ||
188 | */ | ||
189 | if (phandle && (phandle != msi_data->phandle)) | ||
190 | continue; | ||
191 | |||
159 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); | 192 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); |
160 | if (hwirq >= 0) | 193 | if (hwirq >= 0) |
161 | break; | 194 | break; |
@@ -370,6 +403,12 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
370 | 403 | ||
371 | msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); | 404 | msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); |
372 | 405 | ||
406 | /* | ||
407 | * Remember the phandle, so that we can match with any PCI nodes | ||
408 | * that have an "fsl,msi" property. | ||
409 | */ | ||
410 | msi->phandle = dev->dev.of_node->phandle; | ||
411 | |||
373 | rc = fsl_msi_init_allocator(msi); | 412 | rc = fsl_msi_init_allocator(msi); |
374 | if (rc) { | 413 | if (rc) { |
375 | dev_err(&dev->dev, "Error allocating MSI bitmap\n"); | 414 | dev_err(&dev->dev, "Error allocating MSI bitmap\n"); |