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 | |
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>
-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 */ |