免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2430 | 回复: 2
打印 上一主题 下一主题

usb驱动引起kernel panic? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-07 10:52 |只看该作者 |倒序浏览
我现在不确定是不是usb驱动引起的,具体症状就是突然系统死机,没有任何打印,但usb device通过LED灯显示出(单片机程序)运作正常。
以前驱动出现过这种情况,就是设备断线的时候,urb没有被取消,然后urb的callback调用有野指针,改过之后就好用了。
现在我通过主机发给usb device一些配置寄存器的命令,跑着跑着就死机不动了,可能搞kgdb来调试会有效,但是需要两台机器,一台烂机器跑虚拟机还跑不动。

可不可能是因为usb device硬件上的一些改变导致的死机?
  1. struct usb_skel {
  2.     char *              devname;
  3.         struct usb_device *        udev;                        /* the usb device for this device */
  4.         struct usb_interface *        interface;                /* the interface for this device */
  5.         struct semaphore        limit_sem;                /* limiting the number of writes in progress */
  6.     struct urb  *       rcv_urb_pool[DEFAULT_URBPOOL_SIZE]; /* urb pool */
  7.         struct data_list    rcv_data_list;   /*recv data's buffer list*/
  8.         __u8                        bulk_in_endpointAddr;        /* the address of the bulk in endpoint */
  9.         __u8                        bulk_out_endpointAddr;        /* the address of the bulk out endpoint */
  10.     int                            open_count;                /* count the number of openers */
  11.     int                present;                /* this is 1 as long as the device is connected */
  12.         struct kref                kref;
  13.     struct mutex    io_mutex;                /* synchronize I/O with disconnect */
  14.     wait_queue_head_t    outq;      /* read wait queue */
  15.     unsigned   int  discard_count;  /* count the number of packets dicarded */
  16.     unsigned   int  fail_count;     /* count the number of packets sent unsuccess */
  17.     unsigned   int  sent_count;     /* count the number of packets sent */
  18.     unsigned   int  bufferqueue_maxlength;
  19.     unsigned   int  recv_count;     /* count the number of packets recieved*/
  20. };
复制代码
probe函数里将urb pool初始化,open函数里填充提交urb,并在urb回调函数中循环提交。
  1. static void skel_read_bulk_callback(struct urb *urb,struct pt_regs * r)
  2. {
  3.         struct usb_skel *dev;
  4.     struct data_list_node *node;
  5.     int retval;
  6.        
  7.         dev = (struct usb_skel *)urb->context;

  8.         /* sync/async unlink faults aren't errors */
  9.         if (urb->status)
  10.         {
  11.             dbg("%s - nonzero write bulk status received: %d",__FUNCTION__, urb->status);
  12.             if(urb->status == -ENOENT ||
  13.               urb->status == -ECONNRESET ||
  14.               urb->status == -ESHUTDOWN)
  15.                 {
  16.             goto error;
  17.                 }
  18.                 else
  19.                 {
  20.                     goto out;
  21.                 }
  22.         }
  23.     /* if the read was successful, push the data to readqueue */
  24.    
  25.     if( urb->actual_length > 0)
  26.     {
  27.         spin_lock(&dev->rcv_data_list.listlock);
  28.         
  29.         if(dev->rcv_data_list.enqueue <= 0)
  30.             {
  31.             struct list_head * ptr;
  32.             struct data_list_node * entry;
  33.             
  34.                 ptr = dev->rcv_data_list.list.next;
  35.             entry = list_entry(ptr,struct data_list_node,list);

  36.             list_del(ptr);

  37.                 kmem_cache_free(buffer_cache,entry->bulk_in_buffer);
  38.             kmem_cache_free(listnode_cache,entry);

  39.             ++ dev->rcv_data_list.enqueue;
  40.             -- dev->rcv_data_list.dequeue;

  41.             ++ dev->discard_count;
  42.             }
  43.         
  44.         node = kmem_cache_alloc(listnode_cache, GFP_ATOMIC);

  45.         if(node == NULL)
  46.         {
  47.             err("Out of memory");
  48.             spin_unlock(&dev->rcv_data_list.listlock);
  49.             kmem_cache_free(buffer_cache,urb->transfer_buffer);
  50.             goto error;
  51.         }
  52.         node->list.prev = NULL;
  53.         node->list.next = NULL;

  54.         node->bulk_in_buffer = urb->transfer_buffer;
  55.         node->bulk_in_size = urb->actual_length;
  56.         
  57.         list_add_tail(&node->list,&dev->rcv_data_list.list);

  58.         if(dev->rcv_data_list.dequeue <= 0)
  59.         {
  60.             wake_up_interruptible(&dev->outq);  /*wake up read and poll*/
  61.         }

  62.         -- dev->rcv_data_list.enqueue;
  63.         ++ dev->rcv_data_list.dequeue;

  64.         ++ dev->recv_count;

  65.         spin_unlock(&dev->rcv_data_list.listlock);

  66.         urb->transfer_buffer = NULL;
  67.         
  68.         urb->transfer_buffer = kmem_cache_alloc(buffer_cache, GFP_ATOMIC);
  69.         
  70.         if(!urb->transfer_buffer)
  71.             goto error;
  72.     }

  73. out:
  74.     retval = usb_submit_urb(urb, GFP_ATOMIC);
  75.     if (retval) {
  76.         err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);                   
  77.         kmem_cache_free(buffer_cache,urb->transfer_buffer);
  78.     }
  79. error:
  80.     return;
  81. }
复制代码
release函数或是其它判别出设备unpresent的地方,将urb kill掉。
disconnect函数中free urb


代码由usb-skeleton改来
我以为在disconnect调用之前release必被先调用

论坛徽章:
0
2 [报告]
发表于 2010-08-09 16:37 |只看该作者
不是panic,系统挂起,应该是死锁了
把urb pool大小改为1,一切都正常

我这里设置的是15,可能多了点

论坛徽章:
0
3 [报告]
发表于 2010-08-09 18:40 |只看该作者
自旋锁的问题,去掉就不会挂起,但互斥不了了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP