Linux设备驱动故障定位指引与实例
Linux设备驱动故障定位指引
Linux设备驱动种类繁多,涉及的知识点多,想写一个通用的故障定位方法指引,是个难度颇大且不容易做好的工作。限于笔者的经验,难以避免存在疏漏之处,欢迎大家留言指正补充。
Linux设备驱动的知识点涉及硬件和软件,其故障原因也各种各样。不过从笔者多年的维护经验来看,与内核驱动相比,硬件相关问题导致的设备驱动故障还是占了较大的比例,而且大部分的硬件问题特别是环境问题也是相对来说较容易排查的。下图是Linux设备驱动故障定位脑图(大图),图中按硬件和软件分为两类,硬件分类又细分为环境、芯片和上级总线/桥片,软件分类又细分为bootloader和内核驱动。每个检查点给出检查项和检查方法。
MTD设备驱动故障定位示例
故障描述
某一块单板上有一块型号S29GL01GT11TFIV10的NOR flash,其上使用UBIFS文件系统,用于储存3.10内核镜像。测试中发现单板上电过程中,大概有10%的概率会偶现如下内核异常,并且此后所有flash命令操作都失败,flash无法正常访问:
MTD get_chip(): chip not ready after erase suspend
UBI error: ubi_io_write: error -5 while writing 512 bytes to PEB 932:36992, written 0 bytes
notice(4295011711): cpu0 max interrupt interval is 112812200ns
sCall Trace: [jiffies: 0x10000ad9b]
[<ffffffffc0be76cc>] dump_stack+0x8/0x34
[<ffffffffc0a0b624>] ubi_io_write+0x52c/0x670
[<ffffffffc0a079e8>] ubi_eba_write_leb+0xd8/0x758
[<ffffffffc0897470>] ubifs_leb_write+0xd0/0x178
[<ffffffffc0898cd0>] ubifs_wbuf_write_nolock+0x430/0x798
[<ffffffffc088b16c>] ubifs_jnl_write_data+0x1e4/0x348
[<ffffffffc088e5a8>] do_writepage+0xc8/0x258
[<ffffffffc0714d70>] __writepage+0x18/0x78
[<ffffffffc0715ab8>] write_cache_pages+0x1e0/0x4c8
[<ffffffffc0715de0>] generic_writepages+0x40/0x78
[<ffffffffc0784620>] __writeback_single_inode+0x58/0x370
[<ffffffffc0785b84>] writeback_sb_inodes+0x2e4/0x498
[<ffffffffc0785df8>] __writeback_inodes_wb+0xc0/0x118
[<ffffffffc07862fc>] wb_writeback+0x234/0x3c0
[<ffffffffc0786918>] wb_do_writeback+0x230/0x2b0
[<ffffffffc0786a1c>] bdi_writeback_workfn+0x84/0x268
[<ffffffffc0670300>] process_one_work+0x180/0x4d0
[<ffffffffc0671848>] worker_thread+0x158/0x420
[<ffffffffc06786c0>] kthread+0xa8/0xb0
[<ffffffffc06204c8>] ret_from_kernel_thread+0x10/0x18
故障分析及定位步骤
相应代码片段如下(所在位置:drivers/mtd/chips/cfi_cmdset_0002.c:get_chip),其实现功能是如果发现当前flash处在擦除状态,下发erase suspend(CMD(0xB0))命令,暂停块擦除操作,使flash处理就绪状态。
之所以需要有erase suspend,是因为UBI有后台进程ubi_bgt0d,此进程功能是对flash块进行垃圾回收、磨损均衡、torture check等,当用户访问flash时,为了立即响应用户,需要立即暂停后台进程的操作,避免因为后台进程长时间占用flash而导致用户请求得不到及时响应的情况。
下发了erase suspend命令后,如果timeo时间内(这里是1s),flash还没有进入就绪状态,则说明flash出现问题,后面所有的flash命令操作都开始失败。flash的就绪检查由chip_ready实现,其实现原理是:同一个地址读两次,如果值相同,则说明flash已就绪。问题出现后,flash出错地址读出的字节的确一直在0x28和0x6c间跳变,无法稳定下来。
case FL_ERASING:
if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
!(mode == FL_READY || mode == FL_POINT ||
(mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
goto sleep; /* We could check to see if we're trying to access the sector
* that is currently being erased. However, no user will try
* anything like that so we just wait for the timeout. */ /* Erase suspend */
/* It's harmless to issue the Erase-Suspend and Erase-Resume
* commands when the erase algorithm isn't in progress. */
map_write(map, CMD(0xB0), chip->in_progress_block_addr);
chip->oldstate = FL_ERASING;
chip->state = FL_ERASE_SUSPENDING;
chip->erase_suspended = ;
for (;;) {
if (chip_ready(map, adr))
break; if (time_after(jiffies, timeo)) {
/* Should have suspended the erase by now.
* Send an Erase-Resume command as either
* there was an error (so leave the erase
* routine to recover from it) or we trying to
* use the erase-in-progress sector. */
put_chip(map, chip, adr);
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
return -EIO;
} mutex_unlock(&chip->mutex);
cfi_udelay();
mutex_lock(&chip->mutex);
/* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
So we can just loop here. */
}
chip->state = FL_READY;
return ;
参照上面的故障定位脑图,排除一些不适用此故障的排查点,我们的故障排查顺序和结果如下:
修复方案及补丁提交
修改方案也很简单,就是针对S29GL01GT/S29GL512T,在Erase Resume命令下发后,延时500μs。
具体实现可查看此补丁提交链接。
--EOF--
Linux设备驱动故障定位指引与实例的更多相关文章
- Linux 设备驱动开发 —— platform设备驱动应用实例解析
前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 —— platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...
- Linux设备驱动工程师之路——内核链表的使用【转】
本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...
- linux设备驱动归纳总结(八):2.总线、设备和驱动的关系【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-110295.html linux设备驱动归纳总结(八):2.总线.设备和驱动的关系 xxxxxxxxx ...
- linux设备驱动归纳总结(一)内核的相关基础概念【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-59413.html linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxx ...
- Smart210学习记录-------Linux设备驱动结构
cdev结构体 1 struct cdev { 2 struct kobject kobj; /* 内嵌的 kobject 对象 */ 3 struct module *owner; /*所属模块*/ ...
- 《Linux设备驱动开发详解(第2版)》配套视频登录51cto教育频道
http://edu.51cto.com/course/course_id-379-page-1.html http://edu.51cto.com/course/course_id-379-page ...
- Linux设备驱动中的阻塞和非阻塞I/O
[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到 ...
- 《Linux设备驱动开发具体解释(第3版)》进展同步更新
本博实时更新<Linux设备驱动开发具体解释(第3版)>的最新进展. 2015.2.26 差点儿完毕初稿. 本书已经rebase到开发中的Linux 4.0内核,案例多数基于多核CORTE ...
- 【转】Linux设备驱动--块设备(一)之概念和框架
原文地址:Linux设备驱动--块设备(一)之概念和框架 基本概念 块设备(blockdevice) --- 是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时 ...
随机推荐
- Tensorflow中实现BN为什么需要加入这个额外依赖?见CS231N作业源码
batch normalization in tensorflow requires this extra dependency 为什么加上这两句? extra_update_ops = tf.get ...
- UVA-714 二分
把可能的进行二分判断,判断的时候尽量向右取,一直取到不能去为止,这样才有可能成功分割. 判断是否可以把up作为最大值的代码: bool judge(LL up){ if(up < Big) re ...
- Zookeeper笔记3——原理及其安装使用
Zookeeper到底能干什么? 1.配置管理:这个好理解.分布式系统都有好多机器,Zookeeper提供了这样的一种服务:一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣 ...
- Swift 之属性setter、getter方法
Swift 之属性setter.getter方法 Swift中的属性分为两种属性,一种就是计算型属性 一种就是存储型属性,开始我虽然知道这两种属性,但是了解并不深对于他的setter和getter方法 ...
- linux虚拟化概述
虚拟化硬件虚拟化:一台物理机虚拟出多台逻辑上的计算机cpu,内存可分配给多个虚拟机软件虚拟化:一个LAMP平台支撑多个网站桌面虚拟化...... 虚拟机:通过软件平台模拟出的计算机对最终用户来说,感受 ...
- caffe+GPU︱AWS.G2+Ubuntu14.04+GPU+CUDA8.0+cudnn8.0
国服亚马逊的GPU实例G2.2xlarge的python+caffe的安装过程,被虐- 一周才装出来- BVLC/caffe的在AWS安装的官方教程github: https://github.com ...
- java中servletContextListener、httpSessionListener和servletRequestListener使用整理
在java web应用中,listener监听器似乎是必不可少的,常常用来监听servletContext.httpSession.servletRequest等域对象的创建.销毁以及属性的变化等等, ...
- ubuntu11.04启动 及虚拟文件系统
虚拟文件系统(VFS)是由Sun microsystems公司在定义网络文件系统(NFS)时创造的.它是一种用于网络环境的分布式文件系统,是允许和操作系统使用不同的文件系统实现的接口.虚拟文件系统(V ...
- 最新的Android版本和API Level的对应关系表
在项目开发过程中,经常会用到API Level和Android平台版本的对照,来进行一些方法的调用,现在就把对照表贴出来,供开发人员参考,并且方便自己查阅. Platform Version API ...
- dojo省份地市级联之地市封装类(二)
dojo省份地市级联之地市封装类 City.java: /** * 地市封装类 */ package com.you.model; import java.io.Serializable; /** * ...