1 /* 2 * Copyright 2006-2008, Michael Ellerman, IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; version 2 of the 7 * License. 8 * 9 */ 10 11 #include <linux/slab.h> 12 #include <linux/kernel.h> 13 #include <linux/kmemleak.h> 14 #include <linux/bitmap.h> 15 #include <linux/memblock.h> 16 #include <asm/msi_bitmap.h> 17 #include <asm/setup.h> 18 19 int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num) 20 { 21 unsigned long flags; 22 int offset, order = get_count_order(num); 23 24 spin_lock_irqsave(&bmp->lock, flags); 25 26 offset = bitmap_find_next_zero_area(bmp->bitmap, bmp->irq_count, 0, 27 num, (1 << order) - 1); 28 if (offset > bmp->irq_count) 29 goto err; 30 31 bitmap_set(bmp->bitmap, offset, num); 32 spin_unlock_irqrestore(&bmp->lock, flags); 33 34 pr_debug("msi_bitmap: allocated 0x%x at offset 0x%x\n", num, offset); 35 36 return offset; 37 err: 38 spin_unlock_irqrestore(&bmp->lock, flags); 39 return -ENOMEM; 40 } 41 EXPORT_SYMBOL(msi_bitmap_alloc_hwirqs); 42 43 void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset, 44 unsigned int num) 45 { 46 unsigned long flags; 47 48 pr_debug("msi_bitmap: freeing 0x%x at offset 0x%x\n", 49 num, offset); 50 51 spin_lock_irqsave(&bmp->lock, flags); 52 bitmap_clear(bmp->bitmap, offset, num); 53 spin_unlock_irqrestore(&bmp->lock, flags); 54 } 55 EXPORT_SYMBOL(msi_bitmap_free_hwirqs); 56 57 void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq) 58 { 59 unsigned long flags; 60 61 pr_debug("msi_bitmap: reserving hwirq 0x%x\n", hwirq); 62 63 spin_lock_irqsave(&bmp->lock, flags); 64 bitmap_allocate_region(bmp->bitmap, hwirq, 0); 65 spin_unlock_irqrestore(&bmp->lock, flags); 66 } 67 68 /** 69 * msi_bitmap_reserve_dt_hwirqs - Reserve irqs specified in the device tree. 70 * @bmp: pointer to the MSI bitmap. 71 * 72 * Looks in the device tree to see if there is a property specifying which 73 * irqs can be used for MSI. If found those irqs reserved in the device tree 74 * are reserved in the bitmap. 75 * 76 * Returns 0 for success, < 0 if there was an error, and > 0 if no property 77 * was found in the device tree. 78 **/ 79 int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp) 80 { 81 int i, j, len; 82 const u32 *p; 83 84 if (!bmp->of_node) 85 return 1; 86 87 p = of_get_property(bmp->of_node, "msi-available-ranges", &len); 88 if (!p) { 89 pr_debug("msi_bitmap: no msi-available-ranges property " \ 90 "found on %pOF\n", bmp->of_node); 91 return 1; 92 } 93 94 if (len % (2 * sizeof(u32)) != 0) { 95 printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges" 96 " property on %pOF\n", bmp->of_node); 97 return -EINVAL; 98 } 99 100 bitmap_allocate_region(bmp->bitmap, 0, get_count_order(bmp->irq_count)); 101 102 spin_lock(&bmp->lock); 103 104 /* Format is: (<u32 start> <u32 count>)+ */ 105 len /= 2 * sizeof(u32); 106 for (i = 0; i < len; i++, p += 2) { 107 for (j = 0; j < *(p + 1); j++) 108 bitmap_release_region(bmp->bitmap, *p + j, 0); 109 } 110 111 spin_unlock(&bmp->lock); 112 113 return 0; 114 } 115 116 int __ref msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count, 117 struct device_node *of_node) 118 { 119 int size; 120 121 if (!irq_count) 122 return -EINVAL; 123 124 size = BITS_TO_LONGS(irq_count) * sizeof(long); 125 pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size); 126 127 bmp->bitmap_from_slab = slab_is_available(); 128 if (bmp->bitmap_from_slab) 129 bmp->bitmap = kzalloc(size, GFP_KERNEL); 130 else { 131 bmp->bitmap = memblock_alloc(size, SMP_CACHE_BYTES); 132 if (!bmp->bitmap) 133 panic("%s: Failed to allocate %u bytes\n", __func__, 134 size); 135 /* the bitmap won't be freed from memblock allocator */ 136 kmemleak_not_leak(bmp->bitmap); 137 } 138 139 if (!bmp->bitmap) { 140 pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n"); 141 return -ENOMEM; 142 } 143 144 /* We zalloc'ed the bitmap, so all irqs are free by default */ 145 spin_lock_init(&bmp->lock); 146 bmp->of_node = of_node_get(of_node); 147 bmp->irq_count = irq_count; 148 149 return 0; 150 } 151 152 void msi_bitmap_free(struct msi_bitmap *bmp) 153 { 154 if (bmp->bitmap_from_slab) 155 kfree(bmp->bitmap); 156 of_node_put(bmp->of_node); 157 bmp->bitmap = NULL; 158 } 159 160 #ifdef CONFIG_MSI_BITMAP_SELFTEST 161 162 static void __init test_basics(void) 163 { 164 struct msi_bitmap bmp; 165 int rc, i, size = 512; 166 167 /* Can't allocate a bitmap of 0 irqs */ 168 WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0); 169 170 /* of_node may be NULL */ 171 WARN_ON(msi_bitmap_alloc(&bmp, size, NULL)); 172 173 /* Should all be free by default */ 174 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size))); 175 bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); 176 177 /* With no node, there's no msi-available-ranges, so expect > 0 */ 178 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0); 179 180 /* Should all still be free */ 181 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size))); 182 bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); 183 184 /* Check we can fill it up and then no more */ 185 for (i = 0; i < size; i++) 186 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0); 187 188 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0); 189 190 /* Should all be allocated */ 191 WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0); 192 193 /* And if we free one we can then allocate another */ 194 msi_bitmap_free_hwirqs(&bmp, size / 2, 1); 195 WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2); 196 197 /* Free most of them for the alignment tests */ 198 msi_bitmap_free_hwirqs(&bmp, 3, size - 3); 199 200 /* Check we get a naturally aligned offset */ 201 rc = msi_bitmap_alloc_hwirqs(&bmp, 2); 202 WARN_ON(rc < 0 && rc % 2 != 0); 203 rc = msi_bitmap_alloc_hwirqs(&bmp, 4); 204 WARN_ON(rc < 0 && rc % 4 != 0); 205 rc = msi_bitmap_alloc_hwirqs(&bmp, 8); 206 WARN_ON(rc < 0 && rc % 8 != 0); 207 rc = msi_bitmap_alloc_hwirqs(&bmp, 9); 208 WARN_ON(rc < 0 && rc % 16 != 0); 209 rc = msi_bitmap_alloc_hwirqs(&bmp, 3); 210 WARN_ON(rc < 0 && rc % 4 != 0); 211 rc = msi_bitmap_alloc_hwirqs(&bmp, 7); 212 WARN_ON(rc < 0 && rc % 8 != 0); 213 rc = msi_bitmap_alloc_hwirqs(&bmp, 121); 214 WARN_ON(rc < 0 && rc % 128 != 0); 215 216 msi_bitmap_free(&bmp); 217 218 /* Clients may WARN_ON bitmap == NULL for "not-allocated" */ 219 WARN_ON(bmp.bitmap != NULL); 220 } 221 222 static void __init test_of_node(void) 223 { 224 u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 }; 225 const char *expected_str = "0-9,20-24,28-39,41-99,220-255"; 226 char *prop_name = "msi-available-ranges"; 227 char *node_name = "/fakenode"; 228 struct device_node of_node; 229 struct property prop; 230 struct msi_bitmap bmp; 231 #define SIZE_EXPECTED 256 232 DECLARE_BITMAP(expected, SIZE_EXPECTED); 233 234 /* There should really be a struct device_node allocator */ 235 memset(&of_node, 0, sizeof(of_node)); 236 of_node_init(&of_node); 237 of_node.full_name = node_name; 238 239 WARN_ON(msi_bitmap_alloc(&bmp, SIZE_EXPECTED, &of_node)); 240 241 /* No msi-available-ranges, so expect > 0 */ 242 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0); 243 244 /* Should all still be free */ 245 WARN_ON(bitmap_find_free_region(bmp.bitmap, SIZE_EXPECTED, 246 get_count_order(SIZE_EXPECTED))); 247 bitmap_release_region(bmp.bitmap, 0, get_count_order(SIZE_EXPECTED)); 248 249 /* Now create a fake msi-available-ranges property */ 250 251 /* There should really .. oh whatever */ 252 memset(&prop, 0, sizeof(prop)); 253 prop.name = prop_name; 254 prop.value = &prop_data; 255 prop.length = sizeof(prop_data); 256 257 of_node.properties = ∝ 258 259 /* msi-available-ranges, so expect == 0 */ 260 WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp)); 261 262 /* Check we got the expected result */ 263 WARN_ON(bitmap_parselist(expected_str, expected, SIZE_EXPECTED)); 264 WARN_ON(!bitmap_equal(expected, bmp.bitmap, SIZE_EXPECTED)); 265 266 msi_bitmap_free(&bmp); 267 kfree(bmp.bitmap); 268 } 269 270 static int __init msi_bitmap_selftest(void) 271 { 272 printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n"); 273 274 test_basics(); 275 test_of_node(); 276 277 return 0; 278 } 279 late_initcall(msi_bitmap_selftest); 280 #endif /* CONFIG_MSI_BITMAP_SELFTEST */ 281