Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

at86rf230: add debugfs support

This patch introduce debugfs support for collect trac status stats. To
clear the stats ifdown the interface of at86rf230 and start the
interface again.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Alexander Aring and committed by
Marcel Holtmann
493bc90a ed4a26b0

+159 -14
+7
drivers/net/ieee802154/Kconfig
··· 32 32 This driver can also be built as a module. To do so, say M here. 33 33 the module will be called 'at86rf230'. 34 34 35 + config IEEE802154_AT86RF230_DEBUGFS 36 + depends on IEEE802154_AT86RF230 37 + bool "AT86RF230 debugfs interface" 38 + depends on DEBUG_FS 39 + ---help--- 40 + This option compiles debugfs code for the at86rf230 driver. 41 + 35 42 config IEEE802154_MRF24J40 36 43 tristate "Microchip MRF24J40 transceiver driver" 37 44 depends on IEEE802154_DRIVERS && MAC802154
+144 -14
drivers/net/ieee802154/at86rf230.c
··· 31 31 #include <linux/skbuff.h> 32 32 #include <linux/of_gpio.h> 33 33 #include <linux/ieee802154.h> 34 + #include <linux/debugfs.h> 34 35 35 36 #include <net/mac802154.h> 36 37 #include <net/cfg802154.h> ··· 84 83 bool irq_enable; 85 84 }; 86 85 86 + struct at86rf230_trac { 87 + u64 success; 88 + u64 success_data_pending; 89 + u64 success_wait_for_ack; 90 + u64 channel_access_failure; 91 + u64 no_ack; 92 + u64 invalid; 93 + }; 94 + 87 95 struct at86rf230_local { 88 96 struct spi_device *spi; 89 97 ··· 113 103 u8 tx_retry; 114 104 struct sk_buff *tx_skb; 115 105 struct at86rf230_state_change tx; 106 + 107 + struct at86rf230_trac trac; 116 108 }; 117 109 118 110 #define AT86RF2XX_NUMREGS 0x3F ··· 672 660 struct at86rf230_state_change *ctx = context; 673 661 struct at86rf230_local *lp = ctx->lp; 674 662 663 + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) { 664 + u8 trac = TRAC_MASK(ctx->buf[1]); 665 + 666 + switch (trac) { 667 + case TRAC_SUCCESS: 668 + lp->trac.success++; 669 + break; 670 + case TRAC_SUCCESS_DATA_PENDING: 671 + lp->trac.success_data_pending++; 672 + break; 673 + case TRAC_CHANNEL_ACCESS_FAILURE: 674 + lp->trac.channel_access_failure++; 675 + break; 676 + case TRAC_NO_ACK: 677 + lp->trac.no_ack++; 678 + break; 679 + case TRAC_INVALID: 680 + lp->trac.invalid++; 681 + break; 682 + default: 683 + WARN_ONCE(1, "received tx trac status %d\n", trac); 684 + break; 685 + } 686 + } 687 + 675 688 at86rf230_async_state_change(lp, &lp->irq, STATE_TX_ON, 676 689 at86rf230_tx_on, true); 677 690 } ··· 733 696 } 734 697 735 698 static void 736 - at86rf230_rx_read_frame(void *context) 699 + at86rf230_rx_trac_check(void *context) 737 700 { 738 701 struct at86rf230_state_change *ctx = context; 739 702 struct at86rf230_local *lp = ctx->lp; 740 703 u8 *buf = ctx->buf; 741 704 int rc; 705 + 706 + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) { 707 + u8 trac = TRAC_MASK(buf[1]); 708 + 709 + switch (trac) { 710 + case TRAC_SUCCESS: 711 + lp->trac.success++; 712 + break; 713 + case TRAC_SUCCESS_WAIT_FOR_ACK: 714 + lp->trac.success_wait_for_ack++; 715 + break; 716 + case TRAC_INVALID: 717 + lp->trac.invalid++; 718 + break; 719 + default: 720 + WARN_ONCE(1, "received rx trac status %d\n", trac); 721 + break; 722 + } 723 + } 742 724 743 725 buf[0] = CMD_FB; 744 726 ctx->trx.len = AT86RF2XX_MAX_BUF; ··· 768 712 enable_irq(ctx->irq); 769 713 at86rf230_async_error(lp, ctx, rc); 770 714 } 771 - } 772 - 773 - static void 774 - at86rf230_rx_trac_check(void *context) 775 - { 776 - /* Possible check on trac status here. This could be useful to make 777 - * some stats why receive is failed. Not used at the moment, but it's 778 - * maybe timing relevant. Datasheet doesn't say anything about this. 779 - * The programming guide say do it so. 780 - */ 781 - 782 - at86rf230_rx_read_frame(context); 783 715 } 784 716 785 717 static void ··· 934 890 at86rf230_start(struct ieee802154_hw *hw) 935 891 { 936 892 struct at86rf230_local *lp = hw->priv; 893 + 894 + /* reset trac stats on start */ 895 + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) 896 + memset(&lp->trac, 0, sizeof(struct at86rf230_trac)); 937 897 938 898 at86rf230_awake(lp); 939 899 enable_irq(lp->spi->irq); ··· 1639 1591 lp->tx.timer.function = at86rf230_async_state_timer; 1640 1592 } 1641 1593 1594 + #ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS 1595 + static struct dentry *at86rf230_debugfs_root; 1596 + 1597 + static int at86rf230_stats_show(struct seq_file *file, void *offset) 1598 + { 1599 + struct at86rf230_local *lp = file->private; 1600 + int ret; 1601 + 1602 + ret = seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success); 1603 + if (ret < 0) 1604 + return ret; 1605 + 1606 + ret = seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n", 1607 + lp->trac.success_data_pending); 1608 + if (ret < 0) 1609 + return ret; 1610 + 1611 + ret = seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n", 1612 + lp->trac.success_wait_for_ack); 1613 + if (ret < 0) 1614 + return ret; 1615 + 1616 + ret = seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n", 1617 + lp->trac.channel_access_failure); 1618 + if (ret < 0) 1619 + return ret; 1620 + 1621 + ret = seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack); 1622 + if (ret < 0) 1623 + return ret; 1624 + 1625 + return seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid); 1626 + } 1627 + 1628 + static int at86rf230_stats_open(struct inode *inode, struct file *file) 1629 + { 1630 + return single_open(file, at86rf230_stats_show, inode->i_private); 1631 + } 1632 + 1633 + static const struct file_operations at86rf230_stats_fops = { 1634 + .open = at86rf230_stats_open, 1635 + .read = seq_read, 1636 + .llseek = seq_lseek, 1637 + .release = single_release, 1638 + }; 1639 + 1640 + static int at86rf230_debugfs_init(struct at86rf230_local *lp) 1641 + { 1642 + char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-"; 1643 + struct dentry *stats; 1644 + 1645 + strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN); 1646 + 1647 + at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL); 1648 + if (!at86rf230_debugfs_root) 1649 + return -ENOMEM; 1650 + 1651 + stats = debugfs_create_file("trac_stats", S_IRUGO, 1652 + at86rf230_debugfs_root, lp, 1653 + &at86rf230_stats_fops); 1654 + if (!stats) 1655 + return -ENOMEM; 1656 + 1657 + return 0; 1658 + } 1659 + 1660 + static void at86rf230_debugfs_remove(void) 1661 + { 1662 + debugfs_remove_recursive(at86rf230_debugfs_root); 1663 + } 1664 + #else 1665 + static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; } 1666 + static void at86rf230_debugfs_remove(void) { } 1667 + #endif 1668 + 1642 1669 static int at86rf230_probe(struct spi_device *spi) 1643 1670 { 1644 1671 struct ieee802154_hw *hw; ··· 1809 1686 /* going into sleep by default */ 1810 1687 at86rf230_sleep(lp); 1811 1688 1812 - rc = ieee802154_register_hw(lp->hw); 1689 + rc = at86rf230_debugfs_init(lp); 1813 1690 if (rc) 1814 1691 goto free_dev; 1815 1692 1693 + rc = ieee802154_register_hw(lp->hw); 1694 + if (rc) 1695 + goto free_debugfs; 1696 + 1816 1697 return rc; 1817 1698 1699 + free_debugfs: 1700 + at86rf230_debugfs_remove(); 1818 1701 free_dev: 1819 1702 ieee802154_free_hw(lp->hw); 1820 1703 ··· 1835 1706 at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); 1836 1707 ieee802154_unregister_hw(lp->hw); 1837 1708 ieee802154_free_hw(lp->hw); 1709 + at86rf230_debugfs_remove(); 1838 1710 dev_dbg(&spi->dev, "unregistered at86rf230\n"); 1839 1711 1840 1712 return 0;
+8
drivers/net/ieee802154/at86rf230.h
··· 216 216 #define STATE_TRANSITION_IN_PROGRESS 0x1F 217 217 218 218 #define TRX_STATE_MASK (0x1F) 219 + #define TRAC_MASK(x) ((x & 0xe0) >> 5) 220 + 221 + #define TRAC_SUCCESS 0 222 + #define TRAC_SUCCESS_DATA_PENDING 1 223 + #define TRAC_SUCCESS_WAIT_FOR_ACK 2 224 + #define TRAC_CHANNEL_ACCESS_FAILURE 3 225 + #define TRAC_NO_ACK 5 226 + #define TRAC_INVALID 7 219 227 220 228 #endif /* !_AT86RF230_H */