red_eyed_hare 发表于 2009-08-04 22:27

驱动使用iounmap出现vfree(): sleeping in interrupt!!

在测试pci驱动时,用ioremap把bark空间映射到内存虚拟地址,
但iounmap时出现了:
vfree(): sleeping in interrupt!!
c038b484 db2c700c db2c700c 00000000 e09300c3 e0938000 00000000 e09343e0
       c038b4d4 00000202 00000282 db2c708c db2c700c d47a1580 d6e00d80 c038b4e0
       e092f8d4 db2c700c db2c700c 00000005 db2c7000 db2c7168 db2c7000 c038b500
请大家帮忙看看,谢谢了!

Cyberman.Wu 发表于 2009-08-06 12:35

你是在中断中调用的吗?

dreamice 发表于 2009-08-06 12:40

回复 #1 red_eyed_hare 的帖子

这个地方明显是vfree中可能有睡眠调用,而你在中断中睡眠,显然是不允许的。

red_eyed_hare 发表于 2009-08-06 15:06

谢谢了!你能不能说的详细一点,是iounmap中调用了vfree吗?但是我的驱动是在释放中断后再调用iounmap,应该不存在还有中断的影响啊?

red_eyed_hare 发表于 2009-08-06 15:11

问题可不可能是调用驱动的软件引起的?在软件中调用硬件驱动,软件有自己的中断,驱动中有自己的中断,打开设备,关闭设备。在iounmap之前,驱动中的中断都释放了,应该不会有中断干扰了吧?

dreamice 发表于 2009-08-06 15:27

回复 #4 red_eyed_hare 的帖子

应该是调用了vfree造成的

red_eyed_hare 发表于 2009-08-06 15:59

谢谢你啊!我也刚看了源码,是vfree造成的,里面判断了in_interrupt(),驱动里面的中断释放了,但是软件里面还留有,所以还会
if (in_interrupt()) {
printk("vfree(): sleeping in interrupt!! ");
#ifdef __i386__
show_stack(NULL);
#endif
能不能解决这个问题啊?
就是我驱动里不想让它打印这些!
谢了!dreamice

red_eyed_hare 发表于 2009-08-06 16:15

下面是vfree的函数:
void vfree(void * addr)
{
struct vm_struct **p, *tmp;

if (!addr)
return;
if ((PAGE_SIZE-1) & (unsigned long) addr) {
printk(KERN_ERR "Trying to vfree() bad address (%p) ", addr);
return; if (in_interrupt()) {
printk("vfree(): sleeping in interrupt!! ");
#ifdef __i386__
show_stack(NULL);
#endif
}

}
write_lock(&vmlist_lock);
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
write_unlock(&vmlist_lock);
kfree(tmp);
return;
}
}
write_unlock(&vmlist_lock);
printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p) ", addr);
#ifdef __i386__
show_stack(NULL);
#endif
}
我可不可以直接写一个
void vfree123(void * addr)
{
struct vm_struct **p, *tmp;

if (!addr)
return;
if ((PAGE_SIZE-1) & (unsigned long) addr) {
printk(KERN_ERR "Trying to vfree() bad address (%p) ", addr);
return;
}
write_lock(&vmlist_lock);
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
write_unlock(&vmlist_lock);
kfree(tmp);
return;
}
}
write_unlock(&vmlist_lock);
printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p) ", addr);
#ifdef __i386__
show_stack(NULL);
#endif
}
这样就可以用了吧!

garyv 发表于 2009-08-06 17:58

不建议修改内核接口,优化一下你的中断ISR吧。。。

我做过一个pci驱动,在驱动模块卸载时也是先irq_free,再iounmap,但是很正常没报错,而且中断卸载之前响应过多次中断的,版本linux 2.6.20

dreamice 发表于 2009-08-06 18:59

回复 #7 red_eyed_hare 的帖子

你先检查一下,为什么要调用vfree?是不是你前面调用了vmalloc?
为什么不采用kmalloc来进行atomic方式分配呢?
页: [1] 2 3
查看完整版本: 驱动使用iounmap出现vfree(): sleeping in interrupt!!