驱动使用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
请大家帮忙看看,谢谢了! 你是在中断中调用的吗?
回复 #1 red_eyed_hare 的帖子
这个地方明显是vfree中可能有睡眠调用,而你在中断中睡眠,显然是不允许的。 谢谢了!你能不能说的详细一点,是iounmap中调用了vfree吗?但是我的驱动是在释放中断后再调用iounmap,应该不存在还有中断的影响啊? 问题可不可能是调用驱动的软件引起的?在软件中调用硬件驱动,软件有自己的中断,驱动中有自己的中断,打开设备,关闭设备。在iounmap之前,驱动中的中断都释放了,应该不会有中断干扰了吧?回复 #4 red_eyed_hare 的帖子
应该是调用了vfree造成的 谢谢你啊!我也刚看了源码,是vfree造成的,里面判断了in_interrupt(),驱动里面的中断释放了,但是软件里面还留有,所以还会if (in_interrupt()) {
printk("vfree(): sleeping in interrupt!! ");
#ifdef __i386__
show_stack(NULL);
#endif
能不能解决这个问题啊?
就是我驱动里不想让它打印这些!
谢了!dreamice 下面是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
}
这样就可以用了吧! 不建议修改内核接口,优化一下你的中断ISR吧。。。
我做过一个pci驱动,在驱动模块卸载时也是先irq_free,再iounmap,但是很正常没报错,而且中断卸载之前响应过多次中断的,版本linux 2.6.20
回复 #7 red_eyed_hare 的帖子
你先检查一下,为什么要调用vfree?是不是你前面调用了vmalloc?为什么不采用kmalloc来进行atomic方式分配呢?