diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 109 |
1 files changed, 16 insertions, 93 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 2c5187c..f25ce81 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -14,7 +14,6 @@ */ #include <linux/irq.h> #include <linux/bootmem.h> -#include <linux/bitmap.h> #include <linux/msi.h> #include <linux/pci.h> #include <linux/of_platform.h> @@ -67,95 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = { .map = fsl_msi_host_map, }; -static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num) -{ - unsigned long flags; - int order = get_count_order(num); - int offset; - - spin_lock_irqsave(&msi->bitmap_lock, flags); - - offset = bitmap_find_free_region(msi->fsl_msi_bitmap, - NR_MSI_IRQS, order); - - spin_unlock_irqrestore(&msi->bitmap_lock, flags); - - pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n", - __func__, num, order, offset); - - return offset; -} - -static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num) -{ - unsigned long flags; - int order = get_count_order(num); - - pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n", - __func__, num, order, offset); - - spin_lock_irqsave(&msi->bitmap_lock, flags); - bitmap_release_region(msi->fsl_msi_bitmap, offset, order); - spin_unlock_irqrestore(&msi->bitmap_lock, flags); -} - -static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi) -{ - int i; - int len; - const u32 *p; - - bitmap_allocate_region(msi->fsl_msi_bitmap, 0, - get_count_order(NR_MSI_IRQS)); - - p = of_get_property(msi->of_node, "msi-available-ranges", &len); - - if (!p) { - /* No msi-available-ranges property, - * All the 256 MSI interrupts can be used - */ - fsl_msi_free_hwirqs(msi, 0, 0x100); - return 0; - } - - if ((len % (2 * sizeof(u32))) != 0) { - printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges " - "property on %s\n", msi->of_node->full_name); - return -EINVAL; - } - - /* Format is: (<u32 start> <u32 count>)+ */ - len /= 2 * sizeof(u32); - for (i = 0; i < len; i++, p += 2) - fsl_msi_free_hwirqs(msi, *p, *(p + 1)); - - return 0; -} - static int fsl_msi_init_allocator(struct fsl_msi *msi_data) { int rc; - int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32); - msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL); + rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, + msi_data->irqhost->of_node); + if (rc) + return rc; - if (msi_data->fsl_msi_bitmap == NULL) { - pr_debug("%s: ENOMEM allocating allocator bitmap!\n", - __func__); - return -ENOMEM; + rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); + if (rc < 0) { + msi_bitmap_free(&msi_data->bitmap); + return rc; } - rc = fsl_msi_free_dt_hwirqs(msi_data); - if (rc) - goto out_free; - return 0; -out_free: - kfree(msi_data->fsl_msi_bitmap); - - msi_data->fsl_msi_bitmap = NULL; - return rc; - } static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) @@ -175,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) if (entry->irq == NO_IRQ) continue; set_irq_msi(entry->irq, NULL); - fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); + msi_bitmap_free_hwirqs(&msi_data->bitmap, + virq_to_hw(entry->irq), 1); irq_dispose_mapping(entry->irq); } @@ -197,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) { - irq_hw_number_t hwirq; - int rc; + int rc, hwirq; unsigned int virq; struct msi_desc *entry; struct msi_msg msg; struct fsl_msi *msi_data = fsl_msi; list_for_each_entry(entry, &pdev->msi_list, list) { - hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); + hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); if (hwirq < 0) { rc = hwirq; pr_debug("%s: fail allocating msi interrupt\n", @@ -216,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) virq = irq_create_mapping(msi_data->irqhost, hwirq); if (virq == NO_IRQ) { - pr_debug("%s: fail mapping hwirq 0x%lx\n", + pr_debug("%s: fail mapping hwirq 0x%x\n", __func__, hwirq); - fsl_msi_free_hwirqs(msi_data, hwirq, 1); + msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); rc = -ENOSPC; goto out_free; } @@ -317,14 +243,11 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, goto error_out; } - msi->of_node = of_node_get(dev->node); + msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR, + NR_MSI_IRQS, &fsl_msi_host_ops, 0); - msi->irqhost = irq_alloc_host(of_node_get(dev->node), - IRQ_HOST_MAP_LINEAR, - NR_MSI_IRQS, &fsl_msi_host_ops, 0); if (msi->irqhost == NULL) { dev_err(&dev->dev, "No memory for MSI irqhost\n"); - of_node_put(dev->node); err = -ENOMEM; goto error_out; } |