aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2008-08-05 19:10:02 -0400
committerPaul Mackerras <paulus@samba.org>2008-08-20 02:34:58 -0400
commit7e7ab3677502a0f798f38bfa1a7d53dd22faa0bc (patch)
tree7bb1d6b2f7f45907033d2db517d1c804a1e5e1ed /arch/powerpc/sysdev
parent7e302869e0c5261aba779e059cddcd2fbf7aedbe (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.c103
-rw-r--r--arch/powerpc/sysdev/fsl_msi.h5
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
70static 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
89static 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
102static 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
136static int fsl_msi_init_allocator(struct fsl_msi *msi_data) 69static 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;
154out_free:
155 kfree(msi_data->fsl_msi_bitmap);
156
157 msi_data->fsl_msi_bitmap = NULL;
158 return rc;
159
160} 85}
161 86
162static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) 87static 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
199static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 125static 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 */