Bug#826629: Possible offb unload fix.
On Tue, Oct 4, 2016 at 9:13 PM, Lennart Sorensen
<lsorense@csclub.uwaterloo.ca> wrote:
> On Tue, Oct 04, 2016 at 08:41:45PM +0200, Mathieu Malaterre wrote:
>> Hi Len,
>>
>> Here is the release function I am using:
>>
>> static void offb_destroy(struct fb_info *info)
>> {
>> struct offb_par *par = (struct offb_par *) info->par;
>> if (info->screen_base)
>> iounmap(info->screen_base);
>> if (par->cmap_adr != NULL) {
>> iounmap(par->cmap_adr);
>> par->cmap_adr = NULL;
>> }
>> release_mem_region(info->apertures->ranges[0].base,
>> info->apertures->ranges[0].size);
>> framebuffer_release(info);
>> }
>>
>>
>> (you need the cast to avoid warning about deref of void*).
>>
>> And if I do `modprobe radeonfb`:
>>
>> [ 72.163546] bus: 'pci': add driver radeonfb
>> [ 72.163618] bus: 'pci': driver_probe_device: matched device
>> 0000:00:10.0 with driver radeonfb
>> [ 72.163627] bus: 'pci': really_probe: probing driver radeonfb with
>> device 0000:00:10.0
>> [ 72.163651] devices_kset: Moving 0000:00:10.0 to end of list
>> [ 72.163659] radeonfb_pci_register BEGIN
>> [ 72.163680] radeonfb 0000:00:10.0: enabling device (0006 -> 0007)
>> [ 72.163721] radeonfb 0000:00:10.0: BAR 0: can't reserve [mem
>> 0x98000000-0x9fffffff pref]
>> [ 72.163726] radeonfb (0000:00:10.0): cannot request region 0.
>> [ 72.163746] radeonfb: probe of 0000:00:10.0 failed with error -16
>
> Could you put a print statement in offb_destroy to make sure that is
> actually being called?
>
> And this is radeonfb with code added to actually try to kick out offb,
> right?
Here is what I see:
[ 52.270154] bus: 'pci': add driver radeonfb
[ 52.270224] bus: 'pci': driver_probe_device: matched device
0000:00:10.0 with driver radeonfb
[ 52.270233] bus: 'pci': really_probe: probing driver radeonfb with
device 0000:00:10.0
[ 52.270256] devices_kset: Moving 0000:00:10.0 to end of list
[ 52.270264] radeonfb_pci_register BEGIN
[ 52.270267] radeonfb: MM1
[ 52.275001] radeonfb 0000:00:10.0: enabling device (0006 -> 0007)
[ 52.279727] radeonfb: MM2
[ 52.295202] radeonfb: MM3
[ 52.299816] radeonfb: MM4
[ 52.304934] radeonfb: MM0 98000000 8000000 radeonfb
[ 52.309768] checking generic (9c008000 96000) vs hw (98000000 8000000)
[ 52.309776] fb: switching to radeonfb from OFfb ATY,RockHo
[ 52.315075] Console: switching to colour dummy device 80x25
[ 52.315595] device: 'fb0': device_unregister
[ 52.315736] PM: Removing info for No Bus:fb0
[ 52.317348] device: 'fb0': device_create_release
[ 52.317407] radeonfb: MM5 0
[ 52.317447] device: 'vtcon1': device_unregister
[ 52.317500] PM: Removing info for No Bus:vtcon1
[ 52.317565] device: 'vtcon1': device_create_release
[ 52.318992] radeonfb 0000:00:10.0: BAR 0: can't reserve [mem
0x98000000-0x9fffffff pref]
[ 52.319029] radeonfb (0000:00:10.0): cannot request region 0.
[ 52.319066] radeonfb: probe of 0000:00:10.0 failed with error -16
With patch attached.
diff -ru tmp/linux-4.7.5/drivers/video/fbdev/aty/radeon_base.c linux-4.7.5/drivers/video/fbdev/aty/radeon_base.c
--- tmp/linux-4.7.5/drivers/video/fbdev/aty/radeon_base.c 2016-09-24 10:10:18.000000000 +0200
+++ linux-4.7.5/drivers/video/fbdev/aty/radeon_base.c 2016-10-04 21:17:09.864838492 +0200
@@ -2259,6 +2259,43 @@
.read = radeon_show_edid2,
};
+static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+ struct apertures_struct *ap;
+
+ ap = alloc_apertures(1);
+ if (!ap)
+ return -ENOMEM;
+
+ ap->ranges[0].base = pci_resource_start(pdev, 0);
+ ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+ printk(KERN_INFO "radeonfb: MM0 %x %x %s\n", ap->ranges[0].base, ap->ranges[0].size, KBUILD_MODNAME);
+ remove_conflicting_framebuffers(ap, KBUILD_MODNAME, false);
+ //remove_conflicting_framebuffers(ap, KBUILD_MODNAME, true);
+ kfree(ap);
+
+ return 0;
+}
+
+/*static int radeon_kick_out_firmware_fb2(struct pci_dev *pdev)
+{
+ struct apertures_struct *ap;
+
+ ap = alloc_apertures(1);
+ if (!ap)
+ return -ENOMEM;
+
+ ap->ranges[0].base = pci_resource_start(pdev, 0);
+ ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+ printk(KERN_INFO "radeonfb: MM1 %d %d %s\n", ap->ranges[0].base, ap->ranges[0].size, KBUILD_MODNAME);
+ remove_conflicting_framebuffers(ap, KBUILD_MODNAME, false);
+ //remove_conflicting_framebuffers(ap, KBUILD_MODNAME, true);
+ kfree(ap);
+
+ return 0;
+}*/
static int radeonfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -2270,6 +2307,7 @@
int err = 0;
pr_debug("radeonfb_pci_register BEGIN\n");
+ printk(KERN_INFO "radeonfb: MM1\n");
/* Enable device in PCI config */
ret = pci_enable_device(pdev);
@@ -2278,6 +2316,7 @@
pci_name(pdev));
goto err_out;
}
+ printk(KERN_INFO "radeonfb: MM2\n");
info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
if (!info) {
@@ -2286,6 +2325,7 @@
ret = -ENOMEM;
goto err_disable;
}
+ printk(KERN_INFO "radeonfb: MM3\n");
rinfo = info->par;
rinfo->info = info;
rinfo->pdev = pdev;
@@ -2313,6 +2353,13 @@
/* Set base addrs */
rinfo->fb_base_phys = pci_resource_start (pdev, 0);
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
+ printk(KERN_INFO "radeonfb: MM4\n");
+
+ //radeon_kick_out_firmware_fb(pdev);
+ ret = radeon_kick_out_firmware_fb(pdev);
+ printk(KERN_INFO "radeonfb: MM5 %d \n", ret);
+ if (ret) return ret;
+
/* request the mem regions */
ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
diff -ru tmp/linux-4.7.5/drivers/video/fbdev/offb.c linux-4.7.5/drivers/video/fbdev/offb.c
--- tmp/linux-4.7.5/drivers/video/fbdev/offb.c 2016-09-24 10:10:18.000000000 +0200
+++ linux-4.7.5/drivers/video/fbdev/offb.c 2016-10-04 21:19:10.002185027 +0200
@@ -133,9 +133,9 @@
switch (par->cmap_type) {
case cmap_simple:
writeb(regno, par->cmap_adr);
- writeb(red, par->cmap_data);
- writeb(green, par->cmap_data);
writeb(blue, par->cmap_data);
+ writeb(green, par->cmap_data);
+ writeb(red, par->cmap_data);
break;
case cmap_M3A:
/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
@@ -159,6 +159,7 @@
/* Set palette index & data (could be smarter) */
out_8(par->cmap_adr + 0xb0, regno);
out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));
+ //out_le32(par->cmap_adr + 0xb4, (blue << 16 | green << 8 | red));
break;
case cmap_gxt2000:
out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
@@ -277,8 +278,16 @@
static void offb_destroy(struct fb_info *info)
{
+ struct offb_par *par = (struct offb_par *) info->par;
+ printk(KERN_INFO " DBG MM4 RockH" );
if (info->screen_base)
iounmap(info->screen_base);
+ printk(KERN_INFO " DBG MM5 RockH" );
+ if (par->cmap_adr != NULL) {
+ iounmap(par->cmap_adr);
+ par->cmap_adr = NULL;
+ }
+ printk(KERN_INFO " DBG MM6 RockH" );
release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
framebuffer_release(info);
}
@@ -338,6 +347,11 @@
par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
if (par->cmap_adr)
par->cmap_type = cmap_radeon;
+ } else if (dp && !strncmp(name, "ATY,RockH", 9)) {
+ printk(KERN_INFO " DBG MM1 RockH" );
+ par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_radeon;
} else if (!strncmp(name, "ATY,", 4)) {
unsigned long base = address & 0xff000000UL;
par->cmap_adr =
Reply to: