Hi, Jon.
Jon Smirl wrote:
I Found the cause of the segfault, but didn't try to provide a fix. The diff with the extra debugging printouts are attached to the mail.I'm not sure this trap is in the via driver: EIP is at __crc_via_fb_free+0x131f4b1b via just happened to be the closest symbol since it was the last thing you loaded. You may be trying to execute the framebuffer.
recompile your kernel with the kernel debug framepointer option turned on to get a better stack trace. You can also try running with DRM debugging info: insmod ./via.ko drm_opts=debug:on
Add DRM_DEBUG() statements to help narrow down the problem.
From a clean boot you should be able to rmmod/insmod the via driver asmuch as you want.
The segfault occurs in drm_exit when DRM(global)->cards_limit is being accessed in the second run of the loop (i=1) and DRM(global) is NULL.
/Thomas
dmesg:
via: no version for "struct_module" found: kernel tainted.
[drm] Debug messages ON
PCI: Unable to reserve mem region #1:[EMAIL PROTECTED] for device 0000:01:00.0
PCI: Unable to reserve mem region #1:[EMAIL PROTECTED] for device 0000:01:00.0
[drm:viadrv_probe]
[drm:viadrv_probe] first probe
[drm:viadrv_probe] calling inter_module_register
[drm:get_minor]
[drm:get_minor] assigning minor 0
[drm:viadrv_ctxbitmap_next] drm_ctxbitmap_next bit : 0
[drm:viadrv_ctxbitmap_init] drm_ctxbitmap_init : 0
[drm] Initialized via 1.5.0 20040907 on minor 0: VIA Technologies, Inc. VT8623 [Apollo CLE266] integrated CastleRock graphics
[drm:get_minor] new primary minor assigned 0
[drm] Used old pci detect: framebuffer loaded
[drm:drm_exit]
[drm:drm_exit] i is 0, drm(global) is 0xd4f4e360
[drm:drm_exit] i is 0, minor is 0xc17510c0
[drm:drm_exit] fb loaded release minor 0
[drm:drm_cleanup]
[drm:viadrv_takedown]
[drm:drm_cleanup] mtrr_del=2
[drm:viadrv_put_minor] release primary minor 0
[drm:viadrv_put_minor] unregistering inter_module
[drm:viadrv_put_minor] remove_proc_entry
[drm:viadrv_put_minor] sysfs_destroy
[drm:viadrv_put_minor] unregister_chrdev
[drm:viadrv_put_minor] drm_firstfree
[drm:viadrv_put_minor] drm_secondfree
[drm:viadrv_put_minor] drm_globalnull
[drm:viadrv_put_minor] returning
[drm:drm_cleanup] Done drm_cleanup
[drm:drm_exit] Back in drm_exit
[drm:drm_exit] End of For-loop
[drm:drm_exit] i is 1, drm(global) is 0x0
Unable to handle kernel NULL pointer dereference at virtual address 00000004
printing eip:
e00c4326
*pde = 00000000
Oops: 0000 [#1]
CPU: 0
EIP: 0060:[<e00c4326>] Tainted: GF VLI
EFLAGS: 00010286
EIP is at __crc_via_fb_free+0x13a4bc97/0x13a4bdfc [via]
eax: 00000000 ebx: 0000000c ecx: 00000000 edx: 00000001
esi: 0000000c edi: 00000001 ebp: d384df64 esp: d384df50
ds: 007b es: 007b ss: 0068
Process rmmod (pid: 3079, threadinfo=d384c000 task=d3c02080)
Stack: 0000000c 00000010 e00caa40 c0327818 00000000 d384dfbc c0134d03 00000000
00616976 d39c4760 40019000 d39c4760 d384dfa0 c0149e34 d3c1c3a0 d39c4760
d39c4b20 d3c1c3a0 d3c1c3c0 00000000 d384dfbc c0149eb4 00c1c3a0 40018000
Call Trace:
[<c0134d03>] sys_delete_module+0x133/0x1c0
[<c0149e34>] do_munmap+0xf4/0x140
[<c0149eb4>] sys_munmap+0x34/0x60
[<c010b017>] syscall_call+0x7/0xb
Code: 01 74 b2 8b 1d dc ab 0c e0 53 57 68 b4 47 0c e0 68 e0 53 0c e0 e8 1b ee 05 e0 8b 15 d4 ab 0c e0 83 c4 10 a1 dc ab 0c e0 8b 5d ec <8b> 48 04 01 cb f6 c2 01 74 92 53 57 68 b4 47 0c e0 68 20 54 0c
Index: drm_drv.h
===================================================================
RCS file: /cvs/dri/drm/linux/drm_drv.h,v
retrieving revision 1.89
diff -u -r1.89 drm_drv.h
--- drm_drv.h 20 Sep 2004 19:23:26 -0000 1.89
+++ drm_drv.h 6 Oct 2004 23:02:54 -0000
@@ -653,6 +653,7 @@
if ( DRM(put_minor)(dev) )
DRM_ERROR( "Cannot unload module\n" );
+ DRM_DEBUG("Done drm_cleanup\n");
}
static void __exit drm_exit (void)
@@ -664,8 +665,13 @@
DRM_DEBUG( "\n" );
if (DRM(fb_loaded)) {
if (DRM(global)) {
- for (i = 0; i < DRM(global)->cards_limit; i++) {
+ int cards_limit = DRM(global)->cards_limit;
+ for (i = 0; i < cards_limit; i++) {
+ DRM_DEBUG("i is %d, drm(global) is 0x%lx\n",
+ i,(unsigned long)DRM(global));
minor = &DRM(global)->minors[i];
+ DRM_DEBUG("i is %d, minor is 0x%lx\n",
+ i,(unsigned long)minor);
dev = minor->dev;
DRM_DEBUG("fb loaded release minor %d\n", dev->minor);
if ((minor->class == DRM_MINOR_PRIMARY) && (dev->fops
== &DRM(fops))) {
@@ -673,11 +679,17 @@
if (dev->pdev)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
+ DRM_DEBUG("Back in drm_exit\n");
}
+ DRM_DEBUG("End of For-loop\n");
}
+ DRM_DEBUG("End of if drm(global)\n");
}
- } else
- pci_unregister_driver(&drm_driver);
+ DRM_DEBUG("End of if drm(fb_loaded)\n");
+ } else {
+ pci_unregister_driver(&drm_driver);
+ }
+ DRM_DEBUG("About to leave drm_exit\n");
DRM_INFO( "Module unloaded\n" );
}
Index: drm_stub.h
===================================================================
RCS file: /cvs/dri/drm/linux/drm_stub.h,v
retrieving revision 1.35
diff -u -r1.35 drm_stub.h
--- drm_stub.h 23 Sep 2004 17:22:27 -0000 1.35
+++ drm_stub.h 6 Oct 2004 23:02:54 -0000
@@ -245,15 +245,22 @@
}
DRM_DEBUG("unregistering inter_module \n");
inter_module_unregister("drm");
+ DRM_DEBUG("remove_proc_entry\n");
remove_proc_entry("dri", NULL);
+ DRM_DEBUG("sysfs_destroy\n");
DRM(sysfs_destroy)(DRM(global)->drm_class);
+ DRM_DEBUG("unregister_chrdev\n");
unregister_chrdev(DRM_MAJOR, "drm");
+ DRM_DEBUG("drm_firstfree\n");
DRM(free)(DRM(global)->minors, sizeof(*DRM(global)->minors) *
DRM(global)->cards_limit, DRM_MEM_STUB);
+ DRM_DEBUG("drm_secondfree\n");
DRM(free)(DRM(global), sizeof(*DRM(global)), DRM_MEM_STUB);
+ DRM_DEBUG("drm_globalnull\n");
DRM(global) = NULL;
+ DRM_DEBUG("returning\n");
return 0;
}
