static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
                                  unsigned long end, unsigned long pfn,
                                  pgprot_t prot,
-                                 phys_addr_t (*pgtable_alloc)(void))
+                                 phys_addr_t (*pgtable_alloc)(void),
+                                 bool page_mappings_only)
 {
+       pgprot_t __prot = prot;
        pte_t *pte;
 
        BUG_ON(pmd_sect(*pmd));
        do {
                pte_t old_pte = *pte;
 
-               set_pte(pte, pfn_pte(pfn, prot));
+               /*
+                * Set the contiguous bit for the subsequent group of PTEs if
+                * its size and alignment are appropriate.
+                */
+               if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) {
+                       if (end - addr >= CONT_PTE_SIZE && !page_mappings_only)
+                               __prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+                       else
+                               __prot = prot;
+               }
+
+               set_pte(pte, pfn_pte(pfn, __prot));
                pfn++;
 
                /*
                                  phys_addr_t (*pgtable_alloc)(void),
                                  bool page_mappings_only)
 {
+       pgprot_t __prot = prot;
        pmd_t *pmd;
        unsigned long next;
 
                /* try section mapping first */
                if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
                      !page_mappings_only) {
-                       pmd_set_huge(pmd, phys, prot);
+                       /*
+                        * Set the contiguous bit for the subsequent group of
+                        * PMDs if its size and alignment are appropriate.
+                        */
+                       if (((addr | phys) & ~CONT_PMD_MASK) == 0) {
+                               if (end - addr >= CONT_PMD_SIZE)
+                                       __prot = __pgprot(pgprot_val(prot) |
+                                                         PTE_CONT);
+                               else
+                                       __prot = prot;
+                       }
+                       pmd_set_huge(pmd, phys, __prot);
 
                        /*
                         * After the PMD entry has been populated once, we
                                                      pmd_val(*pmd)));
                } else {
                        alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
-                                      prot, pgtable_alloc);
+                                      prot, pgtable_alloc,
+                                      page_mappings_only);
 
                        BUG_ON(pmd_val(old_pmd) != 0 &&
                               pmd_val(old_pmd) != pmd_val(*pmd));