I think the problem with registereing the PCI address in radeonfb is
that the offb does not unmap its addresses fully in the destroy function.

After all, it allocates both info->screen_base and par->cmap_addr as
using seperate ioremap calls on some hardware.  The radeonfb on the
other hand does a single large ioremap of the entire range.

The destroy function is:

static void offb_destroy(struct fb_info *info)
{
        if (info->screen_base)
                iounmap(info->screen_base);
        release_mem_region(info->apertures->ranges[0].base, 
info->apertures->ranges[0].size);
        framebuffer_release(info);
}

While the error handling of offb_init_fb is:

out_err:
        iounmap(info->screen_base);
out_aper:
        iounmap(par->cmap_adr);
        par->cmap_adr = NULL;

So I think the solution is to change offb_destroy to:

static void offb_destroy(struct fb_info *info)
{
        if (info->screen_base)
                iounmap(info->screen_base);
        if (info->par->cmap_adr) {
                iounmap(info->par->cmap_adr);
                info->par->cmap_adr = NULL;
        }
        release_mem_region(info->apertures->ranges[0].base, 
info->apertures->ranges[0].size);
        framebuffer_release(info);
}

I think that will then let the radeonfb do its ioremap call after kicking
out the offb driver.

Certainly your logs indicate the offb was using:
9c008000 96000 (so 9c008000-9c09dfff)
I also believe the code is using:
9c7ff000-9c7fffff for cmap_adr based on:

        } else if (!strncmp(name, "ATY,", 4)) {
                unsigned long base = address & 0xff000000UL;
                par->cmap_adr =
                        ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
                par->cmap_data = par->cmap_adr + 1;
                par->cmap_type = cmap_simple;

The first is info->screen_base and the second is info->par->cmap_adr,
but in destroy only the first one was freed, while the second stays
allocated and blocks the call in the radeonfb that wants:
98000000-9fffffff
This of course overlaps both the other ranges.

Now the second ioremap for the cmap_adr should only happen when the
depth is 8 as far as I can tell.  Does it seem likely that is the mode
it is using for the offb initially?  From a bit of searching on google I
found some indications that 8 bit depth is very likely in fact by default.

-- 
Len Sorensen

Reply via email to