aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c39
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
149static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 149static 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");