|
@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
|
|
int page_start, int page_end)
|
|
int page_start, int page_end)
|
|
{
|
|
{
|
|
const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
|
|
const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
|
|
- unsigned int cpu;
|
|
|
|
|
|
+ unsigned int cpu, tcpu;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
for_each_possible_cpu(cpu) {
|
|
@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
|
|
struct page **pagep = &pages[pcpu_page_idx(cpu, i)];
|
|
struct page **pagep = &pages[pcpu_page_idx(cpu, i)];
|
|
|
|
|
|
*pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0);
|
|
*pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0);
|
|
- if (!*pagep) {
|
|
|
|
- pcpu_free_pages(chunk, pages, populated,
|
|
|
|
- page_start, page_end);
|
|
|
|
- return -ENOMEM;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!*pagep)
|
|
|
|
+ goto err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+err:
|
|
|
|
+ while (--i >= page_start)
|
|
|
|
+ __free_page(pages[pcpu_page_idx(cpu, i)]);
|
|
|
|
+
|
|
|
|
+ for_each_possible_cpu(tcpu) {
|
|
|
|
+ if (tcpu == cpu)
|
|
|
|
+ break;
|
|
|
|
+ for (i = page_start; i < page_end; i++)
|
|
|
|
+ __free_page(pages[pcpu_page_idx(tcpu, i)]);
|
|
|
|
+ }
|
|
|
|
+ return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -263,6 +272,7 @@ err:
|
|
__pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
|
|
__pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
|
|
page_end - page_start);
|
|
page_end - page_start);
|
|
}
|
|
}
|
|
|
|
+ pcpu_post_unmap_tlb_flush(chunk, page_start, page_end);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|