aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-05-27 15:11:56 -0400
committerFrancois Romieu <romieu@fr.zoreil.com>2005-05-27 15:11:56 -0400
commitd4a3a0fc9c2d012093cf75a8d95034966c17e71e (patch)
tree38caaccf7d8a4f69e099aca4515296a0f3f14019 /drivers
parentb57b7e5a11c4e45565cf34d786d74ad35483fe83 (diff)
[PATCH] r8169: add ethtool support for dumping the chip statistics
There aren't lots of statistics available, but this is what is available according to the RealTek documentation. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/r8169.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index d795b31649f3..b30e13867e1e 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -201,6 +201,8 @@ static struct {
201enum RTL8169_registers { 201enum RTL8169_registers {
202 MAC0 = 0, /* Ethernet hardware address. */ 202 MAC0 = 0, /* Ethernet hardware address. */
203 MAR0 = 8, /* Multicast filter. */ 203 MAR0 = 8, /* Multicast filter. */
204 CounterAddrLow = 0x10,
205 CounterAddrHigh = 0x14,
204 TxDescStartAddrLow = 0x20, 206 TxDescStartAddrLow = 0x20,
205 TxDescStartAddrHigh = 0x24, 207 TxDescStartAddrHigh = 0x24,
206 TxHDescStartAddrLow = 0x28, 208 TxHDescStartAddrLow = 0x28,
@@ -342,6 +344,9 @@ enum RTL8169_register_content {
342 344
343 /* _TBICSRBit */ 345 /* _TBICSRBit */
344 TBILinkOK = 0x02000000, 346 TBILinkOK = 0x02000000,
347
348 /* DumpCounterCommand */
349 CounterDump = 0x8,
345}; 350};
346 351
347enum _DescStatusBit { 352enum _DescStatusBit {
@@ -910,6 +915,98 @@ static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
910 tp->msg_enable = value; 915 tp->msg_enable = value;
911} 916}
912 917
918static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
919 "tx_packets",
920 "rx_packets",
921 "tx_errors",
922 "rx_errors",
923 "rx_missed",
924 "align_errors",
925 "tx_single_collisions",
926 "tx_multi_collisions",
927 "unicast",
928 "broadcast",
929 "multicast",
930 "tx_aborted",
931 "tx_underrun",
932};
933
934struct rtl8169_counters {
935 u64 tx_packets;
936 u64 rx_packets;
937 u64 tx_errors;
938 u32 rx_errors;
939 u16 rx_missed;
940 u16 align_errors;
941 u32 tx_one_collision;
942 u32 tx_multi_collision;
943 u64 rx_unicast;
944 u64 rx_broadcast;
945 u32 rx_multicast;
946 u16 tx_aborted;
947 u16 tx_underun;
948};
949
950static int rtl8169_get_stats_count(struct net_device *dev)
951{
952 return ARRAY_SIZE(rtl8169_gstrings);
953}
954
955static void rtl8169_get_ethtool_stats(struct net_device *dev,
956 struct ethtool_stats *stats, u64 *data)
957{
958 struct rtl8169_private *tp = netdev_priv(dev);
959 void __iomem *ioaddr = tp->mmio_addr;
960 struct rtl8169_counters *counters;
961 dma_addr_t paddr;
962 u32 cmd;
963
964 ASSERT_RTNL();
965
966 counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
967 if (!counters)
968 return;
969
970 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
971 cmd = (u64)paddr & DMA_32BIT_MASK;
972 RTL_W32(CounterAddrLow, cmd);
973 RTL_W32(CounterAddrLow, cmd | CounterDump);
974
975 while (RTL_R32(CounterAddrLow) & CounterDump) {
976 if (msleep_interruptible(1))
977 break;
978 }
979
980 RTL_W32(CounterAddrLow, 0);
981 RTL_W32(CounterAddrHigh, 0);
982
983 data[0] = le64_to_cpu(counters->tx_packets);
984 data[1] = le64_to_cpu(counters->rx_packets);
985 data[2] = le64_to_cpu(counters->tx_errors);
986 data[3] = le32_to_cpu(counters->rx_errors);
987 data[4] = le16_to_cpu(counters->rx_missed);
988 data[5] = le16_to_cpu(counters->align_errors);
989 data[6] = le32_to_cpu(counters->tx_one_collision);
990 data[7] = le32_to_cpu(counters->tx_multi_collision);
991 data[8] = le64_to_cpu(counters->rx_unicast);
992 data[9] = le64_to_cpu(counters->rx_broadcast);
993 data[10] = le32_to_cpu(counters->rx_multicast);
994 data[11] = le16_to_cpu(counters->tx_aborted);
995 data[12] = le16_to_cpu(counters->tx_underun);
996
997 pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
998}
999
1000static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1001{
1002 switch(stringset) {
1003 case ETH_SS_STATS:
1004 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1005 break;
1006 }
1007}
1008
1009
913static struct ethtool_ops rtl8169_ethtool_ops = { 1010static struct ethtool_ops rtl8169_ethtool_ops = {
914 .get_drvinfo = rtl8169_get_drvinfo, 1011 .get_drvinfo = rtl8169_get_drvinfo,
915 .get_regs_len = rtl8169_get_regs_len, 1012 .get_regs_len = rtl8169_get_regs_len,
@@ -927,6 +1024,9 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
927 .get_tso = ethtool_op_get_tso, 1024 .get_tso = ethtool_op_get_tso,
928 .set_tso = ethtool_op_set_tso, 1025 .set_tso = ethtool_op_set_tso,
929 .get_regs = rtl8169_get_regs, 1026 .get_regs = rtl8169_get_regs,
1027 .get_strings = rtl8169_get_strings,
1028 .get_stats_count = rtl8169_get_stats_count,
1029 .get_ethtool_stats = rtl8169_get_ethtool_stats,
930}; 1030};
931 1031
932static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum, 1032static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,