Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

char: misc: Increase the maximum number of dynamic misc devices to 1048448

On AmpereOne, 128 dynamic misc devices is not enough for the per-cpu
coresight_tmc devices. Switch the dynamic minors allocator to an ida and
add logic to allocate in the ranges [0..127] and [256..1048575], leaving
[128..255] for static misc devices. Dynamic allocations start from 127
growing downwards and then increasing from 256, so device numbering for the
first 128 devices remain the same as before.

Signed-off-by: D Scott Phillips <scott@os.amperecomputing.com>
Link: https://lore.kernel.org/r/20221114212212.9279-1-scott@os.amperecomputing.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

D Scott Phillips and committed by
Greg Kroah-Hartman
ab760791 7b511616

+28 -13
+28 -13
drivers/char/misc.c
··· 61 61 * Assigned numbers, used for dynamic minors 62 62 */ 63 63 #define DYNAMIC_MINORS 128 /* like dynamic majors */ 64 - static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS); 64 + static DEFINE_IDA(misc_minors_ida); 65 + 66 + static int misc_minor_alloc(void) 67 + { 68 + int ret; 69 + 70 + ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL); 71 + if (ret >= 0) { 72 + ret = DYNAMIC_MINORS - ret - 1; 73 + } else { 74 + ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1, 75 + MINORMASK, GFP_KERNEL); 76 + } 77 + return ret; 78 + } 79 + 80 + static void misc_minor_free(int minor) 81 + { 82 + if (minor < DYNAMIC_MINORS) 83 + ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1); 84 + else if (minor > MISC_DYNAMIC_MINOR) 85 + ida_free(&misc_minors_ida, minor); 86 + } 65 87 66 88 #ifdef CONFIG_PROC_FS 67 89 static void *misc_seq_start(struct seq_file *seq, loff_t *pos) ··· 205 183 mutex_lock(&misc_mtx); 206 184 207 185 if (is_dynamic) { 208 - int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); 186 + int i = misc_minor_alloc(); 209 187 210 - if (i >= DYNAMIC_MINORS) { 188 + if (i < 0) { 211 189 err = -EBUSY; 212 190 goto out; 213 191 } 214 - misc->minor = DYNAMIC_MINORS - i - 1; 215 - set_bit(i, misc_minors); 192 + misc->minor = i; 216 193 } else { 217 194 struct miscdevice *c; 218 195 ··· 230 209 misc, misc->groups, "%s", misc->name); 231 210 if (IS_ERR(misc->this_device)) { 232 211 if (is_dynamic) { 233 - int i = DYNAMIC_MINORS - misc->minor - 1; 234 - 235 - if (i < DYNAMIC_MINORS && i >= 0) 236 - clear_bit(i, misc_minors); 212 + misc_minor_free(misc->minor); 237 213 misc->minor = MISC_DYNAMIC_MINOR; 238 214 } 239 215 err = PTR_ERR(misc->this_device); ··· 258 240 259 241 void misc_deregister(struct miscdevice *misc) 260 242 { 261 - int i = DYNAMIC_MINORS - misc->minor - 1; 262 - 263 243 if (WARN_ON(list_empty(&misc->list))) 264 244 return; 265 245 266 246 mutex_lock(&misc_mtx); 267 247 list_del(&misc->list); 268 248 device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); 269 - if (i < DYNAMIC_MINORS && i >= 0) 270 - clear_bit(i, misc_minors); 249 + misc_minor_free(misc->minor); 271 250 mutex_unlock(&misc_mtx); 272 251 } 273 252 EXPORT_SYMBOL(misc_deregister);