return;
        }
 
-       if (f->new_tlb_gen <= local_tlb_gen) {
+       if (unlikely(f->new_tlb_gen != TLB_GENERATION_INVALID &&
+                    f->new_tlb_gen <= local_tlb_gen)) {
                /*
                 * The TLB is already up to date in respect to f->new_tlb_gen.
                 * While the core might be still behind mm_tlb_gen, checking
                /* Partial flush */
                unsigned long addr = f->start;
 
+               /* Partial flush cannot have invalid generations */
+               VM_WARN_ON(f->new_tlb_gen == TLB_GENERATION_INVALID);
+
+               /* Partial flush must have valid mm */
+               VM_WARN_ON(f->mm == NULL);
+
                nr_invalidate = (f->end - f->start) >> f->stride_shift;
 
                while (addr < f->end) {
                struct flush_tlb_info *info;
 
                preempt_disable();
-               info = get_flush_tlb_info(NULL, start, end, 0, false, 0);
+               info = get_flush_tlb_info(NULL, start, end, 0, false,
+                                         TLB_GENERATION_INVALID);
 
                on_each_cpu(do_kernel_range_flush, info, 1);
 
 
        int cpu = get_cpu();
 
-       info = get_flush_tlb_info(NULL, 0, TLB_FLUSH_ALL, 0, false, 0);
+       info = get_flush_tlb_info(NULL, 0, TLB_FLUSH_ALL, 0, false,
+                                 TLB_GENERATION_INVALID);
        /*
         * flush_tlb_multi() is not optimized for the common case in which only
         * a local TLB flush is needed. Optimize this use-case by calling