1/* 2 * Ralink SoC ethernet driver debugfs code 3 * 4 * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation. 9 */ 10 11#include <linux/debugfs.h> 12#include <linux/module.h> 13#include <linux/phy.h> 14 15#include "ramips_eth.h" 16 17static struct dentry *raeth_debugfs_root; 18 19static int raeth_debugfs_generic_open(struct inode *inode, struct file *file) 20{ 21 file->private_data = inode->i_private; 22 return 0; 23} 24 25void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status) 26{ 27 re->debug.int_stats.total += !!status; 28 29 re->debug.int_stats.rx_delayed += !!(status & RAMIPS_RX_DLY_INT); 30 re->debug.int_stats.rx_done0 += !!(status & RAMIPS_RX_DONE_INT0); 31 re->debug.int_stats.rx_coherent += !!(status & RAMIPS_RX_COHERENT); 32 33 re->debug.int_stats.tx_delayed += !!(status & RAMIPS_TX_DLY_INT); 34 re->debug.int_stats.tx_done0 += !!(status & RAMIPS_TX_DONE_INT0); 35 re->debug.int_stats.tx_done1 += !!(status & RAMIPS_TX_DONE_INT1); 36 re->debug.int_stats.tx_done2 += !!(status & RAMIPS_TX_DONE_INT2); 37 re->debug.int_stats.tx_done3 += !!(status & RAMIPS_TX_DONE_INT3); 38 re->debug.int_stats.tx_coherent += !!(status & RAMIPS_TX_COHERENT); 39 40 re->debug.int_stats.pse_fq_empty += !!(status & RAMIPS_PSE_FQ_EMPTY); 41 re->debug.int_stats.pse_p0_fc += !!(status & RAMIPS_PSE_P0_FC); 42 re->debug.int_stats.pse_p1_fc += !!(status & RAMIPS_PSE_P1_FC); 43 re->debug.int_stats.pse_p2_fc += !!(status & RAMIPS_PSE_P2_FC); 44 re->debug.int_stats.pse_buf_drop += !!(status & RAMIPS_PSE_BUF_DROP); 45} 46 47static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, 48 size_t count, loff_t *ppos) 49{ 50#define PR_INT_STAT(_label, _field) \ 51 len += snprintf(buf + len, sizeof(buf) - len, \ 52 "%-18s: %10lu\n", _label, re->debug.int_stats._field); 53 54 struct raeth_priv *re = file->private_data; 55 char buf[512]; 56 unsigned int len = 0; 57 unsigned long flags; 58 59 spin_lock_irqsave(&re->page_lock, flags); 60 61 PR_INT_STAT("RX Delayed", rx_delayed); 62 PR_INT_STAT("RX Done 0", rx_done0); 63 PR_INT_STAT("RX Coherent", rx_coherent); 64 65 PR_INT_STAT("TX Delayed", tx_delayed); 66 PR_INT_STAT("TX Done 0", tx_done0); 67 PR_INT_STAT("TX Done 1", tx_done1); 68 PR_INT_STAT("TX Done 2", tx_done2); 69 PR_INT_STAT("TX Done 3", tx_done3); 70 PR_INT_STAT("TX Coherent", tx_coherent); 71 72 PR_INT_STAT("PSE FQ empty", pse_fq_empty); 73 PR_INT_STAT("CDMA Flow control", pse_p0_fc); 74 PR_INT_STAT("GDMA1 Flow control", pse_p1_fc); 75 PR_INT_STAT("GDMA2 Flow control", pse_p2_fc); 76 PR_INT_STAT("PSE discard", pse_buf_drop); 77 78 len += snprintf(buf + len, sizeof(buf) - len, "\n"); 79 PR_INT_STAT("Total", total); 80 81 spin_unlock_irqrestore(&re->page_lock, flags); 82 83 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 84#undef PR_INT_STAT 85} 86 87static const struct file_operations raeth_fops_int_stats = { 88 .open = raeth_debugfs_generic_open, 89 .read = read_file_int_stats, 90 .owner = THIS_MODULE 91}; 92 93void raeth_debugfs_exit(struct raeth_priv *re) 94{ 95 debugfs_remove_recursive(re->debug.debugfs_dir); 96} 97 98int raeth_debugfs_init(struct raeth_priv *re) 99{ 100 re->debug.debugfs_dir = debugfs_create_dir(re->netdev->name, 101 raeth_debugfs_root); 102 if (!re->debug.debugfs_dir) 103 return -ENOMEM; 104 105 debugfs_create_file("int_stats", S_IRUGO, re->debug.debugfs_dir, 106 re, &raeth_fops_int_stats); 107 108 return 0; 109} 110 111int raeth_debugfs_root_init(void) 112{ 113 if (raeth_debugfs_root) 114 return -EBUSY; 115 116 raeth_debugfs_root = debugfs_create_dir("raeth", NULL); 117 if (!raeth_debugfs_root) 118 return -ENOENT; 119 120 return 0; 121} 122 123void raeth_debugfs_root_exit(void) 124{ 125 debugfs_remove(raeth_debugfs_root); 126 raeth_debugfs_root = NULL; 127} 128