Linux 内核调试之3 debugfs(以atheros wifi驱动分析)

作用:在调试linux驱动的时候,可以用debugfs来调试,debugfs类似字符设备驱动一样,不需要主设备号次设备号等等。

只需要实现一个file_operations,然后通过debugfs_create_file就可以在debugfs中建立一个文件结点,就像字符设备驱动那样,只需要对这个文件结点进行open就可以进行readwriteioctl,等等操作,这些操作对应到我们在驱动里为debugfs准备的file_operations

内核启动后会把debugfs文件系统挂载到/sys/kernel/debug目录下,如果没有找到,那么可以手动挂载mount -t debugfs none /data/debug

如果挂载失败,确认内核是否配置CONFIG_DEBUG_FS

让内核支持DEBUGFS,使能宏CONFIG_DEBUG_FS,在内核配置中选中,一般是在Kernel hacking中:

选择-*- Debug Filesystem

实例

Ath6kl-3.5驱动调试===================================

cd /data/

mkdir debug

mount -t debugfs none debug

root@android:/data/debug/ieee80211/phy1/ath6kl # ls

 cat tgt_stats     

对应的下面驱动中的调试

1. 创建文件操作函数

static const struct file_operations fops_tgt_stats = {

.read = read_file_tgt_stats,

.open = ath6kl_debugfs_open,

.owner = THIS_MODULE,

.llseek = default_llseek,

};

2.创建文件目录

ar->debugfs_phy = debugfs_create_dir("ath6kl",

     ar->wiphy->debugfsdir);

if (!ar->debugfs_phy)

return -ENOMEM;

注: /* dir in debugfs: ieee80211/ */

struct dentry *debugfsdir;

3.创建读写文件tgt_stats

debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,

    &fops_tgt_stats);

4.实现fops_tgt_stats 


static int ath6kl_debugfs_open(struct inode *inode, struct file *file)

{

file->private_data = inode->i_private;

return 0;

}


static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,

   size_t count, loff_t *ppos)

{

struct ath6kl *ar = file->private_data;

struct ath6kl_vif *vif;

struct target_stats *tgt_stats;

char *buf;

unsigned int len = 0, buf_len = 1500;

int i;

long left;

ssize_t ret_cnt;


vif = ath6kl_vif_first(ar);

if (!vif)

return -EIO;


tgt_stats = &vif->target_stats;


buf = kzalloc(buf_len, GFP_KERNEL);

if (!buf) {

kfree(buf);

return -ENOMEM;

}


if (down_interruptible(&ar->sem)) {

kfree(buf);

return -EBUSY;

}


set_bit(STATS_UPDATE_PEND, &vif->flags);


if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {

up(&ar->sem);

kfree(buf);

return -EIO;

}


left = wait_event_interruptible_timeout(ar->event_wq,

!test_bit(STATS_UPDATE_PEND,

&vif->flags), WMI_TIMEOUT);


up(&ar->sem);


if (left <= 0) {

kfree(buf);

return -ETIMEDOUT;

}


len += scnprintf(buf + len, buf_len - len, "\n");

len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "Target Tx stats");

len += scnprintf(buf + len, buf_len - len, "%25s\n\n",

 "=================");

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Ucast packets", tgt_stats->tx_ucast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Bcast packets", tgt_stats->tx_bcast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Mcast packets", tgt_stats->tx_mcast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Ucast byte", tgt_stats->tx_ucast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Bcast byte", tgt_stats->tx_bcast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Mcast byte", tgt_stats->tx_mcast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Rts success cnt", tgt_stats->tx_rts_success_cnt);

for (i = 0; i < 4; i++)

len += scnprintf(buf + len, buf_len - len,

 "%18s %d %10llu\n", "PER on ac",

 i, tgt_stats->tx_pkt_per_ac[i]);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Error", tgt_stats->tx_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Fail count", tgt_stats->tx_fail_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Retry count", tgt_stats->tx_retry_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);

len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",

 "TKIP counter measure used",

 tgt_stats->tkip_cnter_measures_invoked);


len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "Target Rx stats");

len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "=================");


len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Ucast packets", tgt_stats->rx_ucast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",

 "Ucast Rate", tgt_stats->rx_ucast_rate);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Bcast packets", tgt_stats->rx_bcast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Mcast packets", tgt_stats->rx_mcast_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Ucast byte", tgt_stats->rx_ucast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Bcast byte", tgt_stats->rx_bcast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Mcast byte", tgt_stats->rx_mcast_byte);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Fragmented pkt", tgt_stats->rx_frgment_pkt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Error", tgt_stats->rx_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "CRC Err", tgt_stats->rx_crc_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Key chache miss", tgt_stats->rx_key_cache_miss);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Decrypt Err", tgt_stats->rx_decrypt_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Duplicate frame", tgt_stats->rx_dupl_frame);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "TKIP format err", tgt_stats->tkip_fmt_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "CCMP format Err", tgt_stats->ccmp_fmt_err);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",

 "CCMP Replay Err", tgt_stats->ccmp_replays);


len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "Misc Target stats");

len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "=================");

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Beacon Miss count", tgt_stats->cs_bmiss_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Num Connects", tgt_stats->cs_connect_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",

 "Num disconnects", tgt_stats->cs_discon_cnt);

len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",

 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);


len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "Wow stats");

len += scnprintf(buf + len, buf_len - len, "%25s\n",

 "=================");

len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",

 "Wow pkt dropped", tgt_stats->wow_pkt_dropped);

len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",

 "Wow evt discarded", tgt_stats->wow_evt_discarded);

len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",

 "Wow host pkt wakeup", tgt_stats->wow_host_pkt_wakeups);

len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",

 "Wow host evt wakeups", tgt_stats->wow_host_evt_wakeups);


if (len > buf_len)

len = buf_len;


ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);


kfree(buf);

return ret_cnt;

}


你可能感兴趣的:(Network,Linux)