diff options
Diffstat (limited to 'mm/bootmem.c')
| -rw-r--r-- | mm/bootmem.c | 24 | 
1 files changed, 18 insertions, 6 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 1324cd74fae..b93376c39b6 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -185,10 +185,23 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)  	while (start < end) {  		unsigned long *map, idx, vec; +		unsigned shift;  		map = bdata->node_bootmem_map;  		idx = start - bdata->node_min_pfn; +		shift = idx & (BITS_PER_LONG - 1); +		/* +		 * vec holds at most BITS_PER_LONG map bits, +		 * bit 0 corresponds to start. +		 */  		vec = ~map[idx / BITS_PER_LONG]; + +		if (shift) { +			vec >>= shift; +			if (end - start >= BITS_PER_LONG) +				vec |= ~map[idx / BITS_PER_LONG + 1] << +					(BITS_PER_LONG - shift); +		}  		/*  		 * If we have a properly aligned and fully unreserved  		 * BITS_PER_LONG block of pages in front of us, free @@ -201,19 +214,18 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)  			count += BITS_PER_LONG;  			start += BITS_PER_LONG;  		} else { -			unsigned long off = 0; +			unsigned long cur = start; -			vec >>= start & (BITS_PER_LONG - 1); -			while (vec) { +			start = ALIGN(start + 1, BITS_PER_LONG); +			while (vec && cur != start) {  				if (vec & 1) { -					page = pfn_to_page(start + off); +					page = pfn_to_page(cur);  					__free_pages_bootmem(page, 0);  					count++;  				}  				vec >>= 1; -				off++; +				++cur;  			} -			start = ALIGN(start + 1, BITS_PER_LONG);  		}  	}  |