diff options
| author | Michael Ellerman <michael@ellerman.id.au> | 2008-08-05 19:10:02 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2008-08-20 02:34:58 -0400 |
| commit | 7e7ab3677502a0f798f38bfa1a7d53dd22faa0bc (patch) | |
| tree | 7bb1d6b2f7f45907033d2db517d1c804a1e5e1ed /arch/powerpc/sysdev | |
| parent | 7e302869e0c5261aba779e059cddcd2fbf7aedbe (diff) | |
powerpc: Convert the FSL MSI code to use msi_bitmap
This is 90% straight forward, although we have to change a few
printk format strings as well because of the change in type of hwirq.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 103 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 5 |
2 files changed, 17 insertions, 91 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index d49fa9904d53..f25ce818d40a 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | */ | 14 | */ |
| 15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
| 16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
| 17 | #include <linux/bitmap.h> | ||
| 18 | #include <linux/msi.h> | 17 | #include <linux/msi.h> |
| 19 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
| 20 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
| @@ -67,96 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = { | |||
| 67 | .map = fsl_msi_host_map, | 66 | .map = fsl_msi_host_map, |
| 68 | }; | 67 | }; |
| 69 | 68 | ||
| 70 | static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num) | ||
| 71 | { | ||
| 72 | unsigned long flags; | ||
| 73 | int order = get_count_order(num); | ||
| 74 | int offset; | ||
| 75 | |||
| 76 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
| 77 | |||
| 78 | offset = bitmap_find_free_region(msi->fsl_msi_bitmap, | ||
| 79 | NR_MSI_IRQS, order); | ||
| 80 | |||
| 81 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
| 82 | |||
| 83 | pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n", | ||
| 84 | __func__, num, order, offset); | ||
| 85 | |||
| 86 | return offset; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num) | ||
| 90 | { | ||
| 91 | unsigned long flags; | ||
| 92 | int order = get_count_order(num); | ||
| 93 | |||
| 94 | pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n", | ||
| 95 | __func__, num, order, offset); | ||
| 96 | |||
| 97 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
| 98 | bitmap_release_region(msi->fsl_msi_bitmap, offset, order); | ||
| 99 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
| 100 | } | ||
| 101 | |||
| 102 | static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi) | ||
| 103 | { | ||
| 104 | int i; | ||
| 105 | int len; | ||
| 106 | const u32 *p; | ||
| 107 | |||
| 108 | bitmap_allocate_region(msi->fsl_msi_bitmap, 0, | ||
| 109 | get_count_order(NR_MSI_IRQS)); | ||
| 110 | |||
| 111 | p = of_get_property(msi->irqhost->of_node, "msi-available-ranges", | ||
| 112 | &len); | ||
| 113 | |||
| 114 | if (!p) { | ||
| 115 | /* No msi-available-ranges property, | ||
| 116 | * All the 256 MSI interrupts can be used | ||
| 117 | */ | ||
| 118 | fsl_msi_free_hwirqs(msi, 0, 0x100); | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | if ((len % (2 * sizeof(u32))) != 0) { | ||
| 123 | printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges " | ||
| 124 | "property on %s\n", msi->irqhost->of_node->full_name); | ||
| 125 | return -EINVAL; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* Format is: (<u32 start> <u32 count>)+ */ | ||
| 129 | len /= 2 * sizeof(u32); | ||
| 130 | for (i = 0; i < len; i++, p += 2) | ||
| 131 | fsl_msi_free_hwirqs(msi, *p, *(p + 1)); | ||
| 132 | |||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int fsl_msi_init_allocator(struct fsl_msi *msi_data) | 69 | static int fsl_msi_init_allocator(struct fsl_msi *msi_data) |
| 137 | { | 70 | { |
| 138 | int rc; | 71 | int rc; |
| 139 | int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32); | ||
| 140 | 72 | ||
| 141 | msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL); | 73 | rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, |
| 74 | msi_data->irqhost->of_node); | ||
| 75 | if (rc) | ||
| 76 | return rc; | ||
| 142 | 77 | ||
| 143 | if (msi_data->fsl_msi_bitmap == NULL) { | 78 | rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); |
| 144 | pr_debug("%s: ENOMEM allocating allocator bitmap!\n", | 79 | if (rc < 0) { |
| 145 | __func__); | 80 | msi_bitmap_free(&msi_data->bitmap); |
| 146 | return -ENOMEM; | 81 | return rc; |
| 147 | } | 82 | } |
| 148 | 83 | ||
| 149 | rc = fsl_msi_free_dt_hwirqs(msi_data); | ||
| 150 | if (rc) | ||
| 151 | goto out_free; | ||
| 152 | |||
| 153 | return 0; | 84 | return 0; |
| 154 | out_free: | ||
| 155 | kfree(msi_data->fsl_msi_bitmap); | ||
| 156 | |||
| 157 | msi_data->fsl_msi_bitmap = NULL; | ||
| 158 | return rc; | ||
| 159 | |||
| 160 | } | 85 | } |
| 161 | 86 | ||
| 162 | static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 87 | static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
| @@ -176,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) | |||
| 176 | if (entry->irq == NO_IRQ) | 101 | if (entry->irq == NO_IRQ) |
| 177 | continue; | 102 | continue; |
| 178 | set_irq_msi(entry->irq, NULL); | 103 | set_irq_msi(entry->irq, NULL); |
| 179 | fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); | 104 | msi_bitmap_free_hwirqs(&msi_data->bitmap, |
| 105 | virq_to_hw(entry->irq), 1); | ||
| 180 | irq_dispose_mapping(entry->irq); | 106 | irq_dispose_mapping(entry->irq); |
| 181 | } | 107 | } |
| 182 | 108 | ||
| @@ -198,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
| 198 | 124 | ||
| 199 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 125 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
| 200 | { | 126 | { |
| 201 | irq_hw_number_t hwirq; | 127 | int rc, hwirq; |
| 202 | int rc; | ||
| 203 | unsigned int virq; | 128 | unsigned int virq; |
| 204 | struct msi_desc *entry; | 129 | struct msi_desc *entry; |
| 205 | struct msi_msg msg; | 130 | struct msi_msg msg; |
| 206 | struct fsl_msi *msi_data = fsl_msi; | 131 | struct fsl_msi *msi_data = fsl_msi; |
| 207 | 132 | ||
| 208 | list_for_each_entry(entry, &pdev->msi_list, list) { | 133 | list_for_each_entry(entry, &pdev->msi_list, list) { |
| 209 | hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); | 134 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); |
| 210 | if (hwirq < 0) { | 135 | if (hwirq < 0) { |
| 211 | rc = hwirq; | 136 | rc = hwirq; |
| 212 | pr_debug("%s: fail allocating msi interrupt\n", | 137 | pr_debug("%s: fail allocating msi interrupt\n", |
| @@ -217,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 217 | virq = irq_create_mapping(msi_data->irqhost, hwirq); | 142 | virq = irq_create_mapping(msi_data->irqhost, hwirq); |
| 218 | 143 | ||
| 219 | if (virq == NO_IRQ) { | 144 | if (virq == NO_IRQ) { |
| 220 | pr_debug("%s: fail mapping hwirq 0x%lx\n", | 145 | pr_debug("%s: fail mapping hwirq 0x%x\n", |
| 221 | __func__, hwirq); | 146 | __func__, hwirq); |
| 222 | fsl_msi_free_hwirqs(msi_data, hwirq, 1); | 147 | msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); |
| 223 | rc = -ENOSPC; | 148 | rc = -ENOSPC; |
| 224 | goto out_free; | 149 | goto out_free; |
| 225 | } | 150 | } |
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 6574550c00a5..331c7e7025b7 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
| @@ -13,6 +13,8 @@ | |||
| 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 <asm/msi_bitmap.h> | ||
| 17 | |||
| 16 | #define NR_MSI_REG 8 | 18 | #define NR_MSI_REG 8 |
| 17 | #define IRQS_PER_MSI_REG 32 | 19 | #define IRQS_PER_MSI_REG 32 |
| 18 | #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) | 20 | #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) |
| @@ -31,8 +33,7 @@ struct fsl_msi { | |||
| 31 | void __iomem *msi_regs; | 33 | void __iomem *msi_regs; |
| 32 | u32 feature; | 34 | u32 feature; |
| 33 | 35 | ||
| 34 | unsigned long *fsl_msi_bitmap; | 36 | struct msi_bitmap bitmap; |
| 35 | spinlock_t bitmap_lock; | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ | 39 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ |
