mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 01:59:51 +02:00 
			
		
		
		
	memremap: fix softlockup reports at teardown
The cond_resched() currently in the setup path needs to be duplicated in
the teardown path. Rather than require each instance of
for_each_device_pfn() to open code the same sequence, embed it in the
helper.
Link: https://github.com/intel/ixpdimm_sw/issues/11
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: <stable@vger.kernel.org>
Fixes: 7138970383 ("mm, zone_device: Replace {get, put}_zone_device_page()...")
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
			
			
This commit is contained in:
		
							parent
							
								
									5fdf8e5ba5
								
							
						
					
					
						commit
						949b93250a
					
				
					 1 changed files with 10 additions and 5 deletions
				
			
		| 
						 | 
					@ -275,8 +275,15 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap)
 | 
				
			||||||
	return (res->start + resource_size(res)) >> PAGE_SHIFT;
 | 
						return (res->start + resource_size(res)) >> PAGE_SHIFT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned long pfn_next(unsigned long pfn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (pfn % 1024 == 0)
 | 
				
			||||||
 | 
							cond_resched();
 | 
				
			||||||
 | 
						return pfn + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define for_each_device_pfn(pfn, map) \
 | 
					#define for_each_device_pfn(pfn, map) \
 | 
				
			||||||
	for (pfn = pfn_first(map); pfn < pfn_end(map); pfn++)
 | 
						for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void devm_memremap_pages_release(void *data)
 | 
					static void devm_memremap_pages_release(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -337,10 +344,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
 | 
				
			||||||
	resource_size_t align_start, align_size, align_end;
 | 
						resource_size_t align_start, align_size, align_end;
 | 
				
			||||||
	struct vmem_altmap *altmap = pgmap->altmap_valid ?
 | 
						struct vmem_altmap *altmap = pgmap->altmap_valid ?
 | 
				
			||||||
			&pgmap->altmap : NULL;
 | 
								&pgmap->altmap : NULL;
 | 
				
			||||||
 | 
						struct resource *res = &pgmap->res;
 | 
				
			||||||
	unsigned long pfn, pgoff, order;
 | 
						unsigned long pfn, pgoff, order;
 | 
				
			||||||
	pgprot_t pgprot = PAGE_KERNEL;
 | 
						pgprot_t pgprot = PAGE_KERNEL;
 | 
				
			||||||
	int error, nid, is_ram, i = 0;
 | 
						int error, nid, is_ram;
 | 
				
			||||||
	struct resource *res = &pgmap->res;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	align_start = res->start & ~(SECTION_SIZE - 1);
 | 
						align_start = res->start & ~(SECTION_SIZE - 1);
 | 
				
			||||||
	align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
 | 
						align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
 | 
				
			||||||
| 
						 | 
					@ -409,8 +416,6 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
 | 
				
			||||||
		list_del(&page->lru);
 | 
							list_del(&page->lru);
 | 
				
			||||||
		page->pgmap = pgmap;
 | 
							page->pgmap = pgmap;
 | 
				
			||||||
		percpu_ref_get(pgmap->ref);
 | 
							percpu_ref_get(pgmap->ref);
 | 
				
			||||||
		if (!(++i % 1024))
 | 
					 | 
				
			||||||
			cond_resched();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devm_add_action(dev, devm_memremap_pages_release, pgmap);
 | 
						devm_add_action(dev, devm_memremap_pages_release, pgmap);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue