> Thanks for feedback. I will take a look at these and see if I can
> simplify it further.

Here's part of the solution ... a combination of your gather and trim
functions.  I bypassed the problem of allocating the space for the
kern_memdesc structures for this example ... so you'll have to
integrate this with your code to allocate space.

I think it is a significant improvement in readability, but I'm biased.

Oh, it doesn't print out all the:

efi.trim_top: ignoring 4KB of memory at 0x0 due to granule hole at 0x0
and
efi.trim_bottom: ignoring 8KB of memory at 0x1feffe000 due to granule hole at 
0x1fe000000

messages.  If anyone thinks they are useful, then they could be added, but
they seem like a lot of noise to me.

This looks like it runs ok for the memory map on my tiger, but I didn't try it 
on
anything else.

-Tony

---- cut here and drop into efi.c ----


struct kern_memdesc {
        u64     start;
        u64     npages;
} kern_memdesc[100];

static inline u64
efi_end(efi_memory_desc_t *e)
{
        return e->phys_addr + (e->num_pages<<EFI_PAGE_SHIFT);
}

static inline int
efi_wb(efi_memory_desc_t *e)
{
        return e->attribute & EFI_MEMORY_WB;
}

static inline u64
kern_end(struct kern_memdesc *k)
{
        return k->start + (k->npages<<EFI_PAGE_SHIFT);
}

void
efi_gather(void)
{
        struct kern_memdesc *k = kern_memdesc, *prev = 0;
        u64     contig_low=0, contig_high=0;
        u64     as, ae;
        void *efi_map_start, *efi_map_end, *p, *q;
        efi_memory_desc_t *md, *pmd = NULL, *check_md;
        u64     efi_desc_size;
        unsigned long total_mem = 0;

        efi_map_start = __va(ia64_boot_param->efi_memmap);
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
        efi_desc_size = ia64_boot_param->efi_memdesc_size;

        for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
                md = p;
                if (!efi_wb(md))
                        continue;
                if (pmd == NULL || !efi_wb(pmd) || efi_end(pmd) != 
md->phys_addr) {
                        contig_low = GRANULEROUNDUP(md->phys_addr);
                        contig_high = efi_end(md);
                        for (q = p + efi_desc_size; q < efi_map_end; q += 
efi_desc_size) {
                                check_md = q;
                                if (!efi_wb(check_md))
                                        break;
                                if (contig_high != check_md->phys_addr)
                                        break;
                                contig_high = efi_end(check_md);
                        }
                        contig_high = GRANULEROUNDDOWN(contig_high);
                }
                if (!is_available_memory(md))
                        continue;

                /* round ends inward to granule boundaries */
                as = max(contig_low, md->phys_addr);
                ae = min(contig_high, efi_end(md));

                /* keep within max_addr= command line arg */
                ae = min(ae, max_addr);
                if (ae <= as)
                        continue;

                /* avoid going over mem= command line arg */
                if (total_mem + (ae - as) > mem_limit)
                        ae -= total_mem + (ae - as) - mem_limit;

                if (ae <= as)
                        continue;
                if (prev && kern_end(prev) == md->phys_addr) {
                        prev->npages += (ae - as) >> EFI_PAGE_SHIFT;
                        total_mem += ae - as;
                        continue;
                }
                k->start = as;
                k->npages = (ae - as) >> EFI_PAGE_SHIFT;
                total_mem += ae - as;
                prev = k++;
        }
        k->start = ~0L; /* end-marker */
}
-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to