Skip to content

Commit

Permalink
char: misc: Increase the maximum number of dynamic misc devices to 10…
Browse files Browse the repository at this point in the history
…48448

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>
  • Loading branch information
D Scott Phillips authored and Greg Kroah-Hartman committed Nov 23, 2022
1 parent 7b51161 commit ab76079
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions drivers/char/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,29 @@ static DEFINE_MUTEX(misc_mtx);
* Assigned numbers, used for dynamic minors
*/
#define DYNAMIC_MINORS 128 /* like dynamic majors */
static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
static DEFINE_IDA(misc_minors_ida);

static int misc_minor_alloc(void)
{
int ret;

ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
if (ret >= 0) {
ret = DYNAMIC_MINORS - ret - 1;
} else {
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
MINORMASK, GFP_KERNEL);
}
return ret;
}

static void misc_minor_free(int minor)
{
if (minor < DYNAMIC_MINORS)
ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
else if (minor > MISC_DYNAMIC_MINOR)
ida_free(&misc_minors_ida, minor);
}

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

if (is_dynamic) {
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
int i = misc_minor_alloc();

if (i >= DYNAMIC_MINORS) {
if (i < 0) {
err = -EBUSY;
goto out;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
misc->minor = i;
} else {
struct miscdevice *c;

Expand All @@ -209,10 +230,7 @@ int misc_register(struct miscdevice *misc)
misc, misc->groups, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
if (is_dynamic) {
int i = DYNAMIC_MINORS - misc->minor - 1;

if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
misc_minor_free(misc->minor);
misc->minor = MISC_DYNAMIC_MINOR;
}
err = PTR_ERR(misc->this_device);
Expand Down Expand Up @@ -240,16 +258,13 @@ EXPORT_SYMBOL(misc_register);

void misc_deregister(struct miscdevice *misc)
{
int i = DYNAMIC_MINORS - misc->minor - 1;

if (WARN_ON(list_empty(&misc->list)))
return;

mutex_lock(&misc_mtx);
list_del(&misc->list);
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
misc_minor_free(misc->minor);
mutex_unlock(&misc_mtx);
}
EXPORT_SYMBOL(misc_deregister);
Expand Down

0 comments on commit ab76079

Please sign in to comment.