Refactor __e820__range_update with the introduction of e820_type_updater_data, indented to be used as the void pointer in the e820_entry_updater callbacks, and the implementation of the callbacks to perform the update of the type in a range of a e820_table. Signed-off-by: Martin Fernandez <martin.fernandez@xxxxxxxxxxxxx> --- arch/x86/kernel/e820.c | 146 +++++++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 57 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 923585ab8377..763b8b20a1fd 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -607,80 +607,112 @@ __e820__handle_range_update(struct e820_table *table, return updated_size; } -static u64 __init -__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) -{ - u64 end; - unsigned int i; - u64 real_updated_size = 0; - - BUG_ON(old_type == new_type); - - if (size > (ULLONG_MAX - start)) - size = ULLONG_MAX - start; +/** + * struct e820_type_updater_data - Helper type for + * __e820__range_update(). + * @old_type: old_type parameter of __e820__range_update(). + * @new_type: new_type parameter of __e820__range_update(). + * + * This is intended to be used as the @data argument for the + * e820_entry_updater callbacks. + */ +struct e820_type_updater_data { + enum e820_type old_type; + enum e820_type new_type; +}; - end = start + size; - printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1); - e820_print_type(old_type); - pr_cont(" ==> "); - e820_print_type(new_type); - pr_cont("\n"); +static bool __init type_updater__should_update(const struct e820_entry *entry, + const void *data) +{ + const struct e820_type_updater_data *type_updater_data = + (const struct e820_type_updater_data *)data; - for (i = 0; i < table->nr_entries; i++) { - struct e820_entry *entry = &table->entries[i]; - u64 final_start, final_end; - u64 entry_end; + return entry->type == type_updater_data->old_type; +} - if (entry->type != old_type) - continue; +static void __init type_updater__update(struct e820_entry *entry, + const void *data) +{ + const struct e820_type_updater_data *type_updater_data = + (const struct e820_type_updater_data *)data; - entry_end = entry->addr + entry->size; + entry->type = type_updater_data->new_type; +} - /* Completely covered by new range? */ - if (entry->addr >= start && entry_end <= end) { - entry->type = new_type; - real_updated_size += entry->size; - continue; - } +static void __init type_updater__new(struct e820_table *table, u64 new_start, + u64 new_size, + const struct e820_entry *original, + const void *data) +{ + const struct e820_type_updater_data *type_updater_data = + (const struct e820_type_updater_data *)data; - /* New range is completely covered? */ - if (entry->addr < start && entry_end > end) { - __e820__range_add(table, start, size, new_type); - __e820__range_add(table, end, entry_end - end, entry->type); - entry->size = start - entry->addr; - real_updated_size += size; - continue; - } + __e820__range_add(table, new_start, new_size, + type_updater_data->new_type, original->crypto_capable); +} - /* Partially covered: */ - final_start = max(start, entry->addr); - final_end = min(end, entry_end); - if (final_start >= final_end) - continue; +static u64 __init __e820__range_update(struct e820_table *table, u64 start, + u64 size, enum e820_type old_type, + enum e820_type new_type) +{ + struct e820_entry_updater updater = { + .should_update = type_updater__should_update, + .update = type_updater__update, + .new = type_updater__new + }; - __e820__range_add(table, final_start, final_end - final_start, new_type); + struct e820_type_updater_data data = { + .old_type = old_type, + .new_type = new_type + }; - real_updated_size += final_end - final_start; + BUG_ON(old_type == new_type); - /* - * Left range could be head or tail, so need to update - * its size first: - */ - entry->size -= final_end - final_start; - if (entry->addr < final_start) - continue; + printk(KERN_DEBUG "e820: update [mem %#018Lx-%#018Lx] ", start, + start + size - 1); + e820_print_type(old_type); + pr_cont(" ==> "); + e820_print_type(new_type); + pr_cont("\n"); - entry->addr = final_end; - } - return real_updated_size; + return __e820__handle_range_update(table, start, size, &updater, &data); } -u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) +/** + * e820__range_update() - Update the type of a given address range in + * e820_table. + * @start: Start of the range. + * @size: Size of the range. + * @old_type: Type that we want to change. + * @new_type: New type to replace @old_type. + * + * Update type of addresses in [@start, @start + @size) from @old_type + * to @new_type in e820_table. + * + * Return: The size updated. + */ +u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, + enum e820_type new_type) { return __e820__range_update(e820_table, start, size, old_type, new_type); } -static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type) +/** + * e820__range_update_kexec() - Update the type of a given address + * range in e820_table_kexec. + * @start: Start of the range. + * @size: Size of the range. + * @old_type: Type that we want to change. + * @new_type: New type to replace @old_type. + * + * Update type of addresses in [@start, @start + @size) from @old_type + * to @new_type in e820_table_kexec. + * + * Return: The size updated. + */ +static u64 __init e820__range_update_kexec(u64 start, u64 size, + enum e820_type old_type, + enum e820_type new_type) { return __e820__range_update(e820_table_kexec, start, size, old_type, new_type); } -- 2.30.2