aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2006-06-10 22:48:04 -0400
committerJeff Garzik <jeff@garzik.org>2006-06-11 09:25:16 -0400
commit52da35789c305f6f44d0e85b294a9845c1271898 (patch)
tree08a3300452bdd23fbf2d835721fe64700739bd34
parent5ed2616f621b41d3477d4f4ae2ba0e0a0e80bdce (diff)
[PATCH] forcedeth config: statistics
This patch exposes hardware statistic counters through ethtool support. Signed-Off-By: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/forcedeth.c197
1 files changed, 194 insertions, 3 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index eaf6de9a9dfa..2b8fbebd44ac 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -165,6 +165,7 @@
165#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ 165#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */
166#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ 166#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */
167#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ 167#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */
168#define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */
168 169
169enum { 170enum {
170 NvRegIrqStatus = 0x000, 171 NvRegIrqStatus = 0x000,
@@ -333,6 +334,33 @@ enum {
333#define NVREG_POWERSTATE_D1 0x0001 334#define NVREG_POWERSTATE_D1 0x0001
334#define NVREG_POWERSTATE_D2 0x0002 335#define NVREG_POWERSTATE_D2 0x0002
335#define NVREG_POWERSTATE_D3 0x0003 336#define NVREG_POWERSTATE_D3 0x0003
337 NvRegTxCnt = 0x280,
338 NvRegTxZeroReXmt = 0x284,
339 NvRegTxOneReXmt = 0x288,
340 NvRegTxManyReXmt = 0x28c,
341 NvRegTxLateCol = 0x290,
342 NvRegTxUnderflow = 0x294,
343 NvRegTxLossCarrier = 0x298,
344 NvRegTxExcessDef = 0x29c,
345 NvRegTxRetryErr = 0x2a0,
346 NvRegRxFrameErr = 0x2a4,
347 NvRegRxExtraByte = 0x2a8,
348 NvRegRxLateCol = 0x2ac,
349 NvRegRxRunt = 0x2b0,
350 NvRegRxFrameTooLong = 0x2b4,
351 NvRegRxOverflow = 0x2b8,
352 NvRegRxFCSErr = 0x2bc,
353 NvRegRxFrameAlignErr = 0x2c0,
354 NvRegRxLenErr = 0x2c4,
355 NvRegRxUnicast = 0x2c8,
356 NvRegRxMulticast = 0x2cc,
357 NvRegRxBroadcast = 0x2d0,
358 NvRegTxDef = 0x2d4,
359 NvRegTxFrame = 0x2d8,
360 NvRegRxCnt = 0x2dc,
361 NvRegTxPause = 0x2e0,
362 NvRegRxPause = 0x2e4,
363 NvRegRxDropFrame = 0x2e8,
336 NvRegVlanControl = 0x300, 364 NvRegVlanControl = 0x300,
337#define NVREG_VLANCONTROL_ENABLE 0x2000 365#define NVREG_VLANCONTROL_ENABLE 0x2000
338 NvRegMSIXMap0 = 0x3e0, 366 NvRegMSIXMap0 = 0x3e0,
@@ -481,6 +509,7 @@ typedef union _ring_type {
481#define OOM_REFILL (1+HZ/20) 509#define OOM_REFILL (1+HZ/20)
482#define POLL_WAIT (1+HZ/100) 510#define POLL_WAIT (1+HZ/100)
483#define LINK_TIMEOUT (3*HZ) 511#define LINK_TIMEOUT (3*HZ)
512#define STATS_INTERVAL (10*HZ)
484 513
485/* 514/*
486 * desc_ver values: 515 * desc_ver values:
@@ -536,6 +565,75 @@ typedef union _ring_type {
536#define NV_MSI_X_VECTOR_TX 0x1 565#define NV_MSI_X_VECTOR_TX 0x1
537#define NV_MSI_X_VECTOR_OTHER 0x2 566#define NV_MSI_X_VECTOR_OTHER 0x2
538 567
568/* statistics */
569struct nv_ethtool_str {
570 char name[ETH_GSTRING_LEN];
571};
572
573static const struct nv_ethtool_str nv_estats_str[] = {
574 { "tx_bytes" },
575 { "tx_zero_rexmt" },
576 { "tx_one_rexmt" },
577 { "tx_many_rexmt" },
578 { "tx_late_collision" },
579 { "tx_fifo_errors" },
580 { "tx_carrier_errors" },
581 { "tx_excess_deferral" },
582 { "tx_retry_error" },
583 { "tx_deferral" },
584 { "tx_packets" },
585 { "tx_pause" },
586 { "rx_frame_error" },
587 { "rx_extra_byte" },
588 { "rx_late_collision" },
589 { "rx_runt" },
590 { "rx_frame_too_long" },
591 { "rx_over_errors" },
592 { "rx_crc_errors" },
593 { "rx_frame_align_error" },
594 { "rx_length_error" },
595 { "rx_unicast" },
596 { "rx_multicast" },
597 { "rx_broadcast" },
598 { "rx_bytes" },
599 { "rx_pause" },
600 { "rx_drop_frame" },
601 { "rx_packets" },
602 { "rx_errors_total" }
603};
604
605struct nv_ethtool_stats {
606 u64 tx_bytes;
607 u64 tx_zero_rexmt;
608 u64 tx_one_rexmt;
609 u64 tx_many_rexmt;
610 u64 tx_late_collision;
611 u64 tx_fifo_errors;
612 u64 tx_carrier_errors;
613 u64 tx_excess_deferral;
614 u64 tx_retry_error;
615 u64 tx_deferral;
616 u64 tx_packets;
617 u64 tx_pause;
618 u64 rx_frame_error;
619 u64 rx_extra_byte;
620 u64 rx_late_collision;
621 u64 rx_runt;
622 u64 rx_frame_too_long;
623 u64 rx_over_errors;
624 u64 rx_crc_errors;
625 u64 rx_frame_align_error;
626 u64 rx_length_error;
627 u64 rx_unicast;
628 u64 rx_multicast;
629 u64 rx_broadcast;
630 u64 rx_bytes;
631 u64 rx_pause;
632 u64 rx_drop_frame;
633 u64 rx_packets;
634 u64 rx_errors_total;
635};
636
539/* 637/*
540 * SMP locking: 638 * SMP locking:
541 * All hardware access under dev->priv->lock, except the performance 639 * All hardware access under dev->priv->lock, except the performance
@@ -554,6 +652,7 @@ struct fe_priv {
554 /* General data: 652 /* General data:
555 * Locking: spin_lock(&np->lock); */ 653 * Locking: spin_lock(&np->lock); */
556 struct net_device_stats stats; 654 struct net_device_stats stats;
655 struct nv_ethtool_stats estats;
557 int in_shutdown; 656 int in_shutdown;
558 u32 linkspeed; 657 u32 linkspeed;
559 int duplex; 658 int duplex;
@@ -588,6 +687,7 @@ struct fe_priv {
588 unsigned int pkt_limit; 687 unsigned int pkt_limit;
589 struct timer_list oom_kick; 688 struct timer_list oom_kick;
590 struct timer_list nic_poll; 689 struct timer_list nic_poll;
690 struct timer_list stats_poll;
591 u32 nic_poll_irq; 691 u32 nic_poll_irq;
592 int rx_ring_size; 692 int rx_ring_size;
593 693
@@ -2471,6 +2571,56 @@ static void nv_poll_controller(struct net_device *dev)
2471} 2571}
2472#endif 2572#endif
2473 2573
2574static void nv_do_stats_poll(unsigned long data)
2575{
2576 struct net_device *dev = (struct net_device *) data;
2577 struct fe_priv *np = netdev_priv(dev);
2578 u8 __iomem *base = get_hwbase(dev);
2579
2580 np->estats.tx_bytes += readl(base + NvRegTxCnt);
2581 np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt);
2582 np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt);
2583 np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt);
2584 np->estats.tx_late_collision += readl(base + NvRegTxLateCol);
2585 np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow);
2586 np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier);
2587 np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef);
2588 np->estats.tx_retry_error += readl(base + NvRegTxRetryErr);
2589 np->estats.tx_deferral += readl(base + NvRegTxDef);
2590 np->estats.tx_packets += readl(base + NvRegTxFrame);
2591 np->estats.tx_pause += readl(base + NvRegTxPause);
2592 np->estats.rx_frame_error += readl(base + NvRegRxFrameErr);
2593 np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte);
2594 np->estats.rx_late_collision += readl(base + NvRegRxLateCol);
2595 np->estats.rx_runt += readl(base + NvRegRxRunt);
2596 np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong);
2597 np->estats.rx_over_errors += readl(base + NvRegRxOverflow);
2598 np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr);
2599 np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr);
2600 np->estats.rx_length_error += readl(base + NvRegRxLenErr);
2601 np->estats.rx_unicast += readl(base + NvRegRxUnicast);
2602 np->estats.rx_multicast += readl(base + NvRegRxMulticast);
2603 np->estats.rx_broadcast += readl(base + NvRegRxBroadcast);
2604 np->estats.rx_bytes += readl(base + NvRegRxCnt);
2605 np->estats.rx_pause += readl(base + NvRegRxPause);
2606 np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame);
2607 np->estats.rx_packets =
2608 np->estats.rx_unicast +
2609 np->estats.rx_multicast +
2610 np->estats.rx_broadcast;
2611 np->estats.rx_errors_total =
2612 np->estats.rx_crc_errors +
2613 np->estats.rx_over_errors +
2614 np->estats.rx_frame_error +
2615 (np->estats.rx_frame_align_error - np->estats.rx_extra_byte) +
2616 np->estats.rx_late_collision +
2617 np->estats.rx_runt +
2618 np->estats.rx_frame_too_long;
2619
2620 if (!np->in_shutdown)
2621 mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
2622}
2623
2474static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) 2624static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
2475{ 2625{
2476 struct fe_priv *np = netdev_priv(dev); 2626 struct fe_priv *np = netdev_priv(dev);
@@ -3084,6 +3234,35 @@ static int nv_set_sg(struct net_device *dev, u32 data)
3084 return -EOPNOTSUPP; 3234 return -EOPNOTSUPP;
3085} 3235}
3086 3236
3237static int nv_get_stats_count(struct net_device *dev)
3238{
3239 struct fe_priv *np = netdev_priv(dev);
3240
3241 if (np->driver_data & DEV_HAS_STATISTICS)
3242 return (sizeof(struct nv_ethtool_stats)/sizeof(u64));
3243 else
3244 return 0;
3245}
3246
3247static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *buffer)
3248{
3249 struct fe_priv *np = netdev_priv(dev);
3250
3251 /* update stats */
3252 nv_do_stats_poll((unsigned long)dev);
3253
3254 memcpy(buffer, &np->estats, nv_get_stats_count(dev)*sizeof(u64));
3255}
3256
3257static void nv_get_strings(struct net_device *dev, u32 stringset, u8 *buffer)
3258{
3259 switch (stringset) {
3260 case ETH_SS_STATS:
3261 memcpy(buffer, &nv_estats_str, nv_get_stats_count(dev)*sizeof(struct nv_ethtool_str));
3262 break;
3263 }
3264}
3265
3087static struct ethtool_ops ops = { 3266static struct ethtool_ops ops = {
3088 .get_drvinfo = nv_get_drvinfo, 3267 .get_drvinfo = nv_get_drvinfo,
3089 .get_link = ethtool_op_get_link, 3268 .get_link = ethtool_op_get_link,
@@ -3107,6 +3286,9 @@ static struct ethtool_ops ops = {
3107 .set_tx_csum = nv_set_tx_csum, 3286 .set_tx_csum = nv_set_tx_csum,
3108 .get_sg = ethtool_op_get_sg, 3287 .get_sg = ethtool_op_get_sg,
3109 .set_sg = nv_set_sg, 3288 .set_sg = nv_set_sg,
3289 .get_strings = nv_get_strings,
3290 .get_stats_count = nv_get_stats_count,
3291 .get_ethtool_stats = nv_get_ethtool_stats,
3110}; 3292};
3111 3293
3112static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) 3294static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
@@ -3409,6 +3591,11 @@ static int nv_open(struct net_device *dev)
3409 } 3591 }
3410 if (oom) 3592 if (oom)
3411 mod_timer(&np->oom_kick, jiffies + OOM_REFILL); 3593 mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
3594
3595 /* start statistics timer */
3596 if (np->driver_data & DEV_HAS_STATISTICS)
3597 mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
3598
3412 spin_unlock_irq(&np->lock); 3599 spin_unlock_irq(&np->lock);
3413 3600
3414 return 0; 3601 return 0;
@@ -3429,6 +3616,7 @@ static int nv_close(struct net_device *dev)
3429 3616
3430 del_timer_sync(&np->oom_kick); 3617 del_timer_sync(&np->oom_kick);
3431 del_timer_sync(&np->nic_poll); 3618 del_timer_sync(&np->nic_poll);
3619 del_timer_sync(&np->stats_poll);
3432 3620
3433 netif_stop_queue(dev); 3621 netif_stop_queue(dev);
3434 spin_lock_irq(&np->lock); 3622 spin_lock_irq(&np->lock);
@@ -3488,6 +3676,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
3488 init_timer(&np->nic_poll); 3676 init_timer(&np->nic_poll);
3489 np->nic_poll.data = (unsigned long) dev; 3677 np->nic_poll.data = (unsigned long) dev;
3490 np->nic_poll.function = &nv_do_nic_poll; /* timer handler */ 3678 np->nic_poll.function = &nv_do_nic_poll; /* timer handler */
3679 init_timer(&np->stats_poll);
3680 np->stats_poll.data = (unsigned long) dev;
3681 np->stats_poll.function = &nv_do_stats_poll; /* timer handler */
3491 3682
3492 err = pci_enable_device(pci_dev); 3683 err = pci_enable_device(pci_dev);
3493 if (err) { 3684 if (err) {
@@ -3502,7 +3693,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
3502 if (err < 0) 3693 if (err < 0)
3503 goto out_disable; 3694 goto out_disable;
3504 3695
3505 if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) 3696 if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS))
3506 np->register_size = NV_PCI_REGSZ_VER2; 3697 np->register_size = NV_PCI_REGSZ_VER2;
3507 else 3698 else
3508 np->register_size = NV_PCI_REGSZ_VER1; 3699 np->register_size = NV_PCI_REGSZ_VER1;
@@ -3858,11 +4049,11 @@ static struct pci_device_id pci_tbl[] = {
3858 }, 4049 },
3859 { /* MCP55 Ethernet Controller */ 4050 { /* MCP55 Ethernet Controller */
3860 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), 4051 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
3861 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX, 4052 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS,
3862 }, 4053 },
3863 { /* MCP55 Ethernet Controller */ 4054 { /* MCP55 Ethernet Controller */
3864 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), 4055 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
3865 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX, 4056 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS,
3866 }, 4057 },
3867 {0,}, 4058 {0,},
3868}; 4059};