mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
Merge c4386bd8ee ("mm/memremap: add ZONE_DEVICE support for compound pages") into android-mainline
Steps on the way to 5.17-rc1 Resolves merge conflicts with: mm/memremap.c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I506780b8aa65e17a84fd9adb748e16825a3f4833
This commit is contained in:
@@ -88,6 +88,11 @@ struct dev_pagemap_ops {
|
||||
* @done: completion for @ref
|
||||
* @type: memory type: see MEMORY_* in memory_hotplug.h
|
||||
* @flags: PGMAP_* flags to specify defailed behavior
|
||||
* @vmemmap_shift: structural definition of how the vmemmap page metadata
|
||||
* is populated, specifically the metadata page order.
|
||||
* A zero value (default) uses base pages as the vmemmap metadata
|
||||
* representation. A bigger value will set up compound struct pages
|
||||
* of the requested order value.
|
||||
* @ops: method table
|
||||
* @owner: an opaque pointer identifying the entity that manages this
|
||||
* instance. Used by various helpers to make sure that no
|
||||
@@ -102,6 +107,7 @@ struct dev_pagemap {
|
||||
struct completion done;
|
||||
enum memory_type type;
|
||||
unsigned int flags;
|
||||
unsigned long vmemmap_shift;
|
||||
const struct dev_pagemap_ops *ops;
|
||||
void *owner;
|
||||
int nr_range;
|
||||
@@ -118,6 +124,11 @@ static inline struct vmem_altmap *pgmap_altmap(struct dev_pagemap *pgmap)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned long pgmap_vmemmap_nr(struct dev_pagemap *pgmap)
|
||||
{
|
||||
return 1 << pgmap->vmemmap_shift;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ZONE_DEVICE
|
||||
void *memremap_pages(struct dev_pagemap *pgmap, int nid);
|
||||
void memunmap_pages(struct dev_pagemap *pgmap);
|
||||
|
||||
@@ -102,15 +102,22 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap, int range_id)
|
||||
return (range->start + range_len(range)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned long pfn_next(unsigned long pfn)
|
||||
static unsigned long pfn_next(struct dev_pagemap *pgmap, unsigned long pfn)
|
||||
{
|
||||
if (pfn % 1024 == 0)
|
||||
if (pfn % (1024 << pgmap->vmemmap_shift))
|
||||
cond_resched();
|
||||
return pfn + 1;
|
||||
return pfn + pgmap_vmemmap_nr(pgmap);
|
||||
}
|
||||
|
||||
static unsigned long pfn_len(struct dev_pagemap *pgmap, unsigned long range_id)
|
||||
{
|
||||
return (pfn_end(pgmap, range_id) -
|
||||
pfn_first(pgmap, range_id)) >> pgmap->vmemmap_shift;
|
||||
}
|
||||
|
||||
#define for_each_device_pfn(pfn, map, i) \
|
||||
for (pfn = pfn_first(map, i); pfn < pfn_end(map, i); pfn = pfn_next(pfn))
|
||||
for (pfn = pfn_first(map, i); pfn < pfn_end(map, i); \
|
||||
pfn = pfn_next(map, pfn))
|
||||
|
||||
static void pageunmap_range(struct dev_pagemap *pgmap, int range_id)
|
||||
{
|
||||
@@ -271,8 +278,7 @@ static int pagemap_range(struct dev_pagemap *pgmap, struct mhp_params *params,
|
||||
memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
|
||||
PHYS_PFN(range->start),
|
||||
PHYS_PFN(range_len(range)), pgmap);
|
||||
percpu_ref_get_many(&pgmap->ref,
|
||||
pfn_end(pgmap, range_id) - pfn_first(pgmap, range_id));
|
||||
percpu_ref_get_many(&pgmap->ref, pfn_len(pgmap, range_id));
|
||||
return 0;
|
||||
|
||||
err_add_memory:
|
||||
|
||||
@@ -6612,6 +6612,35 @@ static void __ref __init_zone_device_page(struct page *page, unsigned long pfn,
|
||||
}
|
||||
}
|
||||
|
||||
static void __ref memmap_init_compound(struct page *head,
|
||||
unsigned long head_pfn,
|
||||
unsigned long zone_idx, int nid,
|
||||
struct dev_pagemap *pgmap,
|
||||
unsigned long nr_pages)
|
||||
{
|
||||
unsigned long pfn, end_pfn = head_pfn + nr_pages;
|
||||
unsigned int order = pgmap->vmemmap_shift;
|
||||
|
||||
__SetPageHead(head);
|
||||
for (pfn = head_pfn + 1; pfn < end_pfn; pfn++) {
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
|
||||
__init_zone_device_page(page, pfn, zone_idx, nid, pgmap);
|
||||
prep_compound_tail(head, pfn - head_pfn);
|
||||
set_page_count(page, 0);
|
||||
|
||||
/*
|
||||
* The first tail page stores compound_mapcount_ptr() and
|
||||
* compound_order() and the second tail page stores
|
||||
* compound_pincount_ptr(). Call prep_compound_head() after
|
||||
* the first and second tail pages have been initialized to
|
||||
* not have the data overwritten.
|
||||
*/
|
||||
if (pfn == head_pfn + 2)
|
||||
prep_compound_head(head, order);
|
||||
}
|
||||
}
|
||||
|
||||
void __ref memmap_init_zone_device(struct zone *zone,
|
||||
unsigned long start_pfn,
|
||||
unsigned long nr_pages,
|
||||
@@ -6620,6 +6649,7 @@ void __ref memmap_init_zone_device(struct zone *zone,
|
||||
unsigned long pfn, end_pfn = start_pfn + nr_pages;
|
||||
struct pglist_data *pgdat = zone->zone_pgdat;
|
||||
struct vmem_altmap *altmap = pgmap_altmap(pgmap);
|
||||
unsigned int pfns_per_compound = pgmap_vmemmap_nr(pgmap);
|
||||
unsigned long zone_idx = zone_idx(zone);
|
||||
unsigned long start = jiffies;
|
||||
int nid = pgdat->node_id;
|
||||
@@ -6637,10 +6667,16 @@ void __ref memmap_init_zone_device(struct zone *zone,
|
||||
nr_pages = end_pfn - start_pfn;
|
||||
}
|
||||
|
||||
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
|
||||
for (pfn = start_pfn; pfn < end_pfn; pfn += pfns_per_compound) {
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
|
||||
__init_zone_device_page(page, pfn, zone_idx, nid, pgmap);
|
||||
|
||||
if (pfns_per_compound == 1)
|
||||
continue;
|
||||
|
||||
memmap_init_compound(page, pfn, zone_idx, nid, pgmap,
|
||||
pfns_per_compound);
|
||||
}
|
||||
|
||||
pr_info("%s initialised %lu pages in %ums\n", __func__,
|
||||
|
||||
Reference in New Issue
Block a user