Skip to content

Commit ab76079

Browse files
D Scott Phillipsgregkh
authored andcommitted
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>
1 parent 7b51161 commit ab76079

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

drivers/char/misc.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,29 @@ static DEFINE_MUTEX(misc_mtx);
6161
* Assigned numbers, used for dynamic minors
6262
*/
6363
#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+
}
6587

6688
#ifdef CONFIG_PROC_FS
6789
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -183,14 +205,13 @@ int misc_register(struct miscdevice *misc)
183205
mutex_lock(&misc_mtx);
184206

185207
if (is_dynamic) {
186-
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
208+
int i = misc_minor_alloc();
187209

188-
if (i >= DYNAMIC_MINORS) {
210+
if (i < 0) {
189211
err = -EBUSY;
190212
goto out;
191213
}
192-
misc->minor = DYNAMIC_MINORS - i - 1;
193-
set_bit(i, misc_minors);
214+
misc->minor = i;
194215
} else {
195216
struct miscdevice *c;
196217

@@ -209,10 +230,7 @@ int misc_register(struct miscdevice *misc)
209230
misc, misc->groups, "%s", misc->name);
210231
if (IS_ERR(misc->this_device)) {
211232
if (is_dynamic) {
212-
int i = DYNAMIC_MINORS - misc->minor - 1;
213-
214-
if (i < DYNAMIC_MINORS && i >= 0)
215-
clear_bit(i, misc_minors);
233+
misc_minor_free(misc->minor);
216234
misc->minor = MISC_DYNAMIC_MINOR;
217235
}
218236
err = PTR_ERR(misc->this_device);
@@ -240,16 +258,13 @@ EXPORT_SYMBOL(misc_register);
240258

241259
void misc_deregister(struct miscdevice *misc)
242260
{
243-
int i = DYNAMIC_MINORS - misc->minor - 1;
244-
245261
if (WARN_ON(list_empty(&misc->list)))
246262
return;
247263

248264
mutex_lock(&misc_mtx);
249265
list_del(&misc->list);
250266
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
251-
if (i < DYNAMIC_MINORS && i >= 0)
252-
clear_bit(i, misc_minors);
267+
misc_minor_free(misc->minor);
253268
mutex_unlock(&misc_mtx);
254269
}
255270
EXPORT_SYMBOL(misc_deregister);

0 commit comments

Comments
 (0)