0001
0002
0003
0004
0005
0006 #include <linux/slab.h>
0007 #include <linux/kernel.h>
0008 #include <linux/kmemleak.h>
0009 #include <linux/bitmap.h>
0010 #include <linux/memblock.h>
0011 #include <linux/of.h>
0012 #include <asm/msi_bitmap.h>
0013 #include <asm/setup.h>
0014
0015 int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num)
0016 {
0017 unsigned long flags;
0018 int offset, order = get_count_order(num);
0019
0020 spin_lock_irqsave(&bmp->lock, flags);
0021
0022 offset = bitmap_find_next_zero_area(bmp->bitmap, bmp->irq_count, 0,
0023 num, (1 << order) - 1);
0024 if (offset > bmp->irq_count)
0025 goto err;
0026
0027 bitmap_set(bmp->bitmap, offset, num);
0028 spin_unlock_irqrestore(&bmp->lock, flags);
0029
0030 pr_debug("msi_bitmap: allocated 0x%x at offset 0x%x\n", num, offset);
0031
0032 return offset;
0033 err:
0034 spin_unlock_irqrestore(&bmp->lock, flags);
0035 return -ENOMEM;
0036 }
0037 EXPORT_SYMBOL(msi_bitmap_alloc_hwirqs);
0038
0039 void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset,
0040 unsigned int num)
0041 {
0042 unsigned long flags;
0043
0044 pr_debug("msi_bitmap: freeing 0x%x at offset 0x%x\n",
0045 num, offset);
0046
0047 spin_lock_irqsave(&bmp->lock, flags);
0048 bitmap_clear(bmp->bitmap, offset, num);
0049 spin_unlock_irqrestore(&bmp->lock, flags);
0050 }
0051 EXPORT_SYMBOL(msi_bitmap_free_hwirqs);
0052
0053 void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq)
0054 {
0055 unsigned long flags;
0056
0057 pr_debug("msi_bitmap: reserving hwirq 0x%x\n", hwirq);
0058
0059 spin_lock_irqsave(&bmp->lock, flags);
0060 bitmap_allocate_region(bmp->bitmap, hwirq, 0);
0061 spin_unlock_irqrestore(&bmp->lock, flags);
0062 }
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp)
0076 {
0077 int i, j, len;
0078 const u32 *p;
0079
0080 if (!bmp->of_node)
0081 return 1;
0082
0083 p = of_get_property(bmp->of_node, "msi-available-ranges", &len);
0084 if (!p) {
0085 pr_debug("msi_bitmap: no msi-available-ranges property " \
0086 "found on %pOF\n", bmp->of_node);
0087 return 1;
0088 }
0089
0090 if (len % (2 * sizeof(u32)) != 0) {
0091 printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges"
0092 " property on %pOF\n", bmp->of_node);
0093 return -EINVAL;
0094 }
0095
0096 bitmap_allocate_region(bmp->bitmap, 0, get_count_order(bmp->irq_count));
0097
0098 spin_lock(&bmp->lock);
0099
0100
0101 len /= 2 * sizeof(u32);
0102 for (i = 0; i < len; i++, p += 2) {
0103 for (j = 0; j < *(p + 1); j++)
0104 bitmap_release_region(bmp->bitmap, *p + j, 0);
0105 }
0106
0107 spin_unlock(&bmp->lock);
0108
0109 return 0;
0110 }
0111
0112 int __ref msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count,
0113 struct device_node *of_node)
0114 {
0115 int size;
0116
0117 if (!irq_count)
0118 return -EINVAL;
0119
0120 size = BITS_TO_LONGS(irq_count) * sizeof(long);
0121 pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size);
0122
0123 bmp->bitmap_from_slab = slab_is_available();
0124 if (bmp->bitmap_from_slab)
0125 bmp->bitmap = kzalloc(size, GFP_KERNEL);
0126 else {
0127 bmp->bitmap = memblock_alloc(size, SMP_CACHE_BYTES);
0128 if (!bmp->bitmap)
0129 panic("%s: Failed to allocate %u bytes\n", __func__,
0130 size);
0131
0132 kmemleak_not_leak(bmp->bitmap);
0133 }
0134
0135 if (!bmp->bitmap) {
0136 pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n");
0137 return -ENOMEM;
0138 }
0139
0140
0141 spin_lock_init(&bmp->lock);
0142 bmp->of_node = of_node_get(of_node);
0143 bmp->irq_count = irq_count;
0144
0145 return 0;
0146 }
0147
0148 void msi_bitmap_free(struct msi_bitmap *bmp)
0149 {
0150 if (bmp->bitmap_from_slab)
0151 kfree(bmp->bitmap);
0152 of_node_put(bmp->of_node);
0153 bmp->bitmap = NULL;
0154 }
0155
0156 #ifdef CONFIG_MSI_BITMAP_SELFTEST
0157
0158 static void __init test_basics(void)
0159 {
0160 struct msi_bitmap bmp;
0161 int rc, i, size = 512;
0162
0163
0164 WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0);
0165
0166
0167 WARN_ON(msi_bitmap_alloc(&bmp, size, NULL));
0168
0169
0170 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
0171 bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
0172
0173
0174 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
0175
0176
0177 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
0178 bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
0179
0180
0181 for (i = 0; i < size; i++)
0182 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
0183
0184 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
0185
0186
0187 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0);
0188
0189
0190 msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
0191 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2);
0192
0193
0194 msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
0195
0196
0197 rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
0198 WARN_ON(rc < 0 && rc % 2 != 0);
0199 rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
0200 WARN_ON(rc < 0 && rc % 4 != 0);
0201 rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
0202 WARN_ON(rc < 0 && rc % 8 != 0);
0203 rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
0204 WARN_ON(rc < 0 && rc % 16 != 0);
0205 rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
0206 WARN_ON(rc < 0 && rc % 4 != 0);
0207 rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
0208 WARN_ON(rc < 0 && rc % 8 != 0);
0209 rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
0210 WARN_ON(rc < 0 && rc % 128 != 0);
0211
0212 msi_bitmap_free(&bmp);
0213
0214
0215 WARN_ON(bmp.bitmap != NULL);
0216 }
0217
0218 static void __init test_of_node(void)
0219 {
0220 u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 };
0221 const char *expected_str = "0-9,20-24,28-39,41-99,220-255";
0222 char *prop_name = "msi-available-ranges";
0223 char *node_name = "/fakenode";
0224 struct device_node of_node;
0225 struct property prop;
0226 struct msi_bitmap bmp;
0227 #define SIZE_EXPECTED 256
0228 DECLARE_BITMAP(expected, SIZE_EXPECTED);
0229
0230
0231 memset(&of_node, 0, sizeof(of_node));
0232 of_node_init(&of_node);
0233 of_node.full_name = node_name;
0234
0235 WARN_ON(msi_bitmap_alloc(&bmp, SIZE_EXPECTED, &of_node));
0236
0237
0238 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
0239
0240
0241 WARN_ON(bitmap_find_free_region(bmp.bitmap, SIZE_EXPECTED,
0242 get_count_order(SIZE_EXPECTED)));
0243 bitmap_release_region(bmp.bitmap, 0, get_count_order(SIZE_EXPECTED));
0244
0245
0246
0247
0248 memset(&prop, 0, sizeof(prop));
0249 prop.name = prop_name;
0250 prop.value = &prop_data;
0251 prop.length = sizeof(prop_data);
0252
0253 of_node.properties = ∝
0254
0255
0256 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
0257
0258
0259 WARN_ON(bitmap_parselist(expected_str, expected, SIZE_EXPECTED));
0260 WARN_ON(!bitmap_equal(expected, bmp.bitmap, SIZE_EXPECTED));
0261
0262 msi_bitmap_free(&bmp);
0263 kfree(bmp.bitmap);
0264 }
0265
0266 static int __init msi_bitmap_selftest(void)
0267 {
0268 printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n");
0269
0270 test_basics();
0271 test_of_node();
0272
0273 return 0;
0274 }
0275 late_initcall(msi_bitmap_selftest);
0276 #endif