diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 39 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 3 |
2 files changed, 42 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"); |
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 1313abbc5200..b5d25ba51311 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #ifndef _POWERPC_SYSDEV_FSL_MSI_H | 13 | #ifndef _POWERPC_SYSDEV_FSL_MSI_H |
14 | #define _POWERPC_SYSDEV_FSL_MSI_H | 14 | #define _POWERPC_SYSDEV_FSL_MSI_H |
15 | 15 | ||
16 | #include <linux/of.h> | ||
16 | #include <asm/msi_bitmap.h> | 17 | #include <asm/msi_bitmap.h> |
17 | 18 | ||
18 | #define NR_MSI_REG 8 | 19 | #define NR_MSI_REG 8 |
@@ -36,6 +37,8 @@ struct fsl_msi { | |||
36 | struct msi_bitmap bitmap; | 37 | struct msi_bitmap bitmap; |
37 | 38 | ||
38 | struct list_head list; /* support multiple MSI banks */ | 39 | struct list_head list; /* support multiple MSI banks */ |
40 | |||
41 | phandle phandle; | ||
39 | }; | 42 | }; |
40 | 43 | ||
41 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ | 44 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ |