On 20.06.19 20:31, David Hildenbrand wrote: > Let's move walk_memory_blocks() to the place where memory block logic > resides and simplify it. While at it, add a type for the callback function. > > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > Cc: "Rafael J. Wysocki" <rafael@xxxxxxxxxx> > Cc: David Hildenbrand <david@xxxxxxxxxx> > Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > Cc: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx> > Cc: Pavel Tatashin <pasha.tatashin@xxxxxxxxxx> > Cc: Andrew Banman <andrew.banman@xxxxxxx> > Cc: "mike.travis@xxxxxxx" <mike.travis@xxxxxxx> > Cc: Oscar Salvador <osalvador@xxxxxxxx> > Cc: Michal Hocko <mhocko@xxxxxxxx> > Cc: Wei Yang <richard.weiyang@xxxxxxxxx> > Cc: Arun KS <arunks@xxxxxxxxxxxxxx> > Cc: Qian Cai <cai@xxxxxx> > Signed-off-by: David Hildenbrand <david@xxxxxxxxxx> > --- > drivers/base/memory.c | 42 ++++++++++++++++++++++++++ > include/linux/memory.h | 3 ++ > include/linux/memory_hotplug.h | 2 -- > mm/memory_hotplug.c | 55 ---------------------------------- > 4 files changed, 45 insertions(+), 57 deletions(-) > > diff --git a/drivers/base/memory.c b/drivers/base/memory.c > index c54e80fd25a8..0204384b4d1d 100644 > --- a/drivers/base/memory.c > +++ b/drivers/base/memory.c > @@ -44,6 +44,11 @@ static inline unsigned long pfn_to_block_id(unsigned long pfn) > return base_memory_block_id(pfn_to_section_nr(pfn)); > } > > +static inline unsigned long phys_to_block_id(unsigned long phys) > +{ > + return pfn_to_block_id(PFN_DOWN(phys)); > +} > + > static int memory_subsys_online(struct device *dev); > static int memory_subsys_offline(struct device *dev); > > @@ -851,3 +856,40 @@ int __init memory_dev_init(void) > printk(KERN_ERR "%s() failed: %d\n", __func__, ret); > return ret; > } > + > +/** > + * walk_memory_blocks - walk through all present memory blocks overlapped > + * by the range [start, start + size) > + * > + * @start: start address of the memory range > + * @size: size of the memory range > + * @arg: argument passed to func > + * @func: callback for each memory section walked > + * > + * This function walks through all present memory blocks overlapped by the > + * range [start, start + size), calling func on each memory block. > + * > + * In case func() returns an error, walking is aborted and the error is > + * returned. > + */ > +int walk_memory_blocks(unsigned long start, unsigned long size, > + void *arg, walk_memory_blocks_func_t func) > +{ > + const unsigned long start_block_id = phys_to_block_id(start); > + const unsigned long end_block_id = phys_to_block_id(start + size - 1); > + struct memory_block *mem; > + unsigned long block_id; > + int ret = 0; I *guess* the stall we are seeing is when size = 0. (via ACPI, if info->length is 0) if (!size) return 0; ... but that is just a wild guess. Will have a look after my vacation. -- Thanks, David / dhildenb