ATA port 上插入盘后的错误处理(AHCI)
在X86 平台上电后,进行相应的ahci controller(pci 设备)初始化之后,就进行插盘打印log,观察期间的内核调用流程。
对于此学习使用的是linux3.16.4 的内核。
1)前期准备抓log
使用ftrace 进行相应的log 追踪。在/sys/kernel/debug/tracing下进行操作:
echo 0 > tracing_on 关闭trace的开关;
echo function_graph > current_tracer ;(提前先看一下:cat available_tracer)
echo > trace ;(清空一下trace)
echo ahci_error_handler > set_graph_function;(设置要追踪的函数)
2) 在ata port 插入SSD盘
3) cat trace(由于内容太多,复制主要的流程)
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
0) | ahci_error_handler [libahci]() {
0) | sata_pmp_error_handler() {
0) | ata_eh_autopsy() {
0) 0.100 us | ata_link_next();
0) | ata_eh_link_autopsy() {
0) | sata_scr_read() {
0) 0.321 us | ahci_scr_read [libahci]();
0) 0.902 us | }
0) 1.103 us | ata_eh_analyze_ncq_error();
0) + 88.132 us | }
0) 0.200 us | ata_link_next();
0) + 91.198 us | }
0) | ata_eh_report() {
。。。。。。。
0) | sata_pmp_eh_recover()
ahci_error_handler 调用sata_pmp_error_handler ,结合内核也知道sata_pmp_error_handler里调用了三个函数ata_eh_autopsy(),ata_eh_report(), sata_pmp_eh_recover();重点关注一下sata_pmp_eh_recover函数;
sata_pmp_error_handler() {
ata_eh_report() {
ata_eh_link_report()//打印调试信息
}
sata_pmp_eh_recover{
rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
ops->hardreset, ops->postreset, NULL);
rc = ata_eh_reset(link, ata_link_nr_vacant(link),
prereset, softreset, hardreset, postreset); //hardreset对应的函数打印hard reseting link
rc = ata_eh_revalidate_and_attach(link, &dev);
rc = ata_dev_read_id(dev, &dev->class,
readid_flags, dev->id); //初始化ata_taskfile的参数(为H2D FIS读device ID命令做准备)以及发送ATA_CMD_ID_ATA,返回值保存在dev_id中,共有512bytes。
ata_exec_internal_sg() //执行内部命令,这里面是有相关的command timeout ,完成变量阻塞执行命令
ata_qc_issue() {
1) | ahci_qc_prep [libahci]() {
1) 0.301 us | ata_tf_to_fis();
1) 1.182 us | }
1) 0.180 us | ahci_qc_issue [libahci]();
1) 3.828 us | }
err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);//ata驱动在待机模式下加电,需要一个特定的spin_up的set_feature子功能,然后才能接受除了原始识别命令之外的任何命令。
rc = ata_set_mode(link, &dev);//Set ATA disk trasfer mode
rc = ata_dev_configure(dev);
后续在写一下整个ahci 的初始化规程,包括使用scsi层和block 层。