diff --git a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_debugfs.c b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_debugfs.c index 8e06b744a..20afcf502 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_debugfs.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_debugfs.c @@ -9,12 +9,87 @@ */ #include +#include #include #include "ramips_eth.h" static struct dentry *raeth_debugfs_root; +static int raeth_debugfs_generic_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status) +{ + re->debug.int_stats.total += !!status; + + re->debug.int_stats.rx_delayed += !!(status & RAMIPS_RX_DLY_INT); + re->debug.int_stats.rx_done0 += !!(status & RAMIPS_RX_DONE_INT0); + re->debug.int_stats.rx_coherent += !!(status & RAMIPS_RX_COHERENT); + + re->debug.int_stats.tx_delayed += !!(status & RAMIPS_TX_DLY_INT); + re->debug.int_stats.tx_done0 += !!(status & RAMIPS_TX_DONE_INT0); + re->debug.int_stats.tx_done1 += !!(status & RAMIPS_TX_DONE_INT1); + re->debug.int_stats.tx_done2 += !!(status & RAMIPS_TX_DONE_INT2); + re->debug.int_stats.tx_done3 += !!(status & RAMIPS_TX_DONE_INT3); + re->debug.int_stats.tx_coherent += !!(status & RAMIPS_TX_COHERENT); + + re->debug.int_stats.pse_fq_empty += !!(status & RAMIPS_PSE_FQ_EMPTY); + re->debug.int_stats.pse_p0_fc += !!(status & RAMIPS_PSE_P0_FC); + re->debug.int_stats.pse_p1_fc += !!(status & RAMIPS_PSE_P1_FC); + re->debug.int_stats.pse_p2_fc += !!(status & RAMIPS_PSE_P2_FC); + re->debug.int_stats.pse_buf_drop += !!(status & RAMIPS_PSE_BUF_DROP); +} + +static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PR_INT_STAT(_label, _field) \ + len += snprintf(buf + len, sizeof(buf) - len, \ + "%-18s: %10lu\n", _label, re->debug.int_stats._field); + + struct raeth_priv *re = file->private_data; + char buf[512]; + unsigned int len = 0; + unsigned long flags; + + spin_lock_irqsave(&re->page_lock, flags); + + PR_INT_STAT("RX Delayed", rx_delayed); + PR_INT_STAT("RX Done 0", rx_done0); + PR_INT_STAT("RX Coherent", rx_coherent); + + PR_INT_STAT("TX Delayed", tx_delayed); + PR_INT_STAT("TX Done 0", tx_done0); + PR_INT_STAT("TX Done 1", tx_done1); + PR_INT_STAT("TX Done 2", tx_done2); + PR_INT_STAT("TX Done 3", tx_done3); + PR_INT_STAT("TX Coherent", tx_coherent); + + PR_INT_STAT("PSE FQ empty", pse_fq_empty); + PR_INT_STAT("CDMA Flow control", pse_p0_fc); + PR_INT_STAT("GDMA1 Flow control", pse_p1_fc); + PR_INT_STAT("GDMA2 Flow control", pse_p2_fc); + PR_INT_STAT("PSE discard", pse_buf_drop); + + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + PR_INT_STAT("Total", total); + + spin_unlock_irqrestore(&re->page_lock, flags); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +#undef PR_INT_STAT +} + +static const struct file_operations raeth_fops_int_stats = { + .open = raeth_debugfs_generic_open, + .read = read_file_int_stats, + .owner = THIS_MODULE +}; + void raeth_debugfs_exit(struct raeth_priv *re) { debugfs_remove_recursive(re->debug.debugfs_dir); @@ -27,6 +102,9 @@ int raeth_debugfs_init(struct raeth_priv *re) if (!re->debug.debugfs_dir) return -ENOMEM; + debugfs_create_file("int_stats", S_IRUGO, re->debug.debugfs_dir, + re, &raeth_fops_int_stats); + return 0; } diff --git a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_eth.h b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_eth.h index ea3e92340..c8df434a4 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_eth.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_eth.h @@ -213,8 +213,30 @@ struct ramips_tx_dma { unsigned int txd4; } __packed __aligned(4); +struct raeth_int_stats { + unsigned long rx_delayed; + unsigned long tx_delayed; + unsigned long rx_done0; + unsigned long tx_done0; + unsigned long tx_done1; + unsigned long tx_done2; + unsigned long tx_done3; + unsigned long rx_coherent; + unsigned long tx_coherent; + + unsigned long pse_fq_empty; + unsigned long pse_p0_fc; + unsigned long pse_p1_fc; + unsigned long pse_p2_fc; + unsigned long pse_buf_drop; + + unsigned long total; +}; + struct raeth_debug { struct dentry *debugfs_dir; + + struct raeth_int_stats int_stats; }; struct raeth_priv @@ -258,11 +280,14 @@ int raeth_debugfs_root_init(void); void raeth_debugfs_root_exit(void); int raeth_debugfs_init(struct raeth_priv *re); void raeth_debugfs_exit(struct raeth_priv *re); +void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status); #else static inline int raeth_debugfs_root_init(void) { return 0; } static inline void raeth_debugfs_root_exit(void) {} static inline int raeth_debugfs_init(struct raeth_priv *re) { return 0; } static inline void raeth_debugfs_exit(struct raeth_priv *re) {} +static inline void raeth_debugfs_update_int_stats(struct raeth_priv *re, + u32 status) {} #endif /* CONFIG_NET_RAMIPS_DEBUG_FS */ #endif /* RAMIPS_ETH_H */ diff --git a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_main.c b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_main.c index 26c98d85a..01945872e 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_main.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_main.c @@ -769,6 +769,8 @@ ramips_eth_irq(int irq, void *dev) tasklet_schedule(&re->tx_housekeeping_tasklet); } + raeth_debugfs_update_int_stats(re, fe_int); + return IRQ_HANDLED; }