36 lines
993 B
Diff
36 lines
993 B
Diff
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
|
|
--- a/mm/pgtable-generic.c
|
|
+++ b/mm/pgtable-generic.c
|
|
@@ -438,12 +438,30 @@ static void kernel_pgtable_work_func(struct work_struct *work)
|
|
__pagetable_free(pt);
|
|
}
|
|
|
|
+static void schedule_kernel_pgtable_free(void)
|
|
+{
|
|
+ schedule_work(&kernel_pgtable_work.work);
|
|
+}
|
|
+
|
|
void pagetable_free_kernel(struct ptdesc *pt)
|
|
{
|
|
spin_lock(&kernel_pgtable_work.lock);
|
|
list_add(&pt->pt_list, &kernel_pgtable_work.list);
|
|
spin_unlock(&kernel_pgtable_work.lock);
|
|
|
|
- schedule_work(&kernel_pgtable_work.work);
|
|
+ /*
|
|
+ * The workqueue may not exist yet while the system is booting.
|
|
+ * kernel_pgtable_drain_early() schedules the work once it does.
|
|
+ */
|
|
+ if (system_state != SYSTEM_BOOTING)
|
|
+ schedule_kernel_pgtable_free();
|
|
}
|
|
+
|
|
+static int __init kernel_pgtable_drain_early(void)
|
|
+{
|
|
+ /* Free the kernel page tables queued while booting. */
|
|
+ schedule_kernel_pgtable_free();
|
|
+ return 0;
|
|
+}
|
|
+core_initcall(kernel_pgtable_drain_early);
|
|
#endif
|