diff options
Diffstat (limited to 'drivers/net/sundance.c')
| -rw-r--r-- | drivers/net/sundance.c | 94 |
1 files changed, 87 insertions, 7 deletions
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 4283cc52a8c9..3ed2a67bd6d3 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c | |||
| @@ -363,6 +363,19 @@ struct netdev_private { | |||
| 363 | dma_addr_t tx_ring_dma; | 363 | dma_addr_t tx_ring_dma; |
| 364 | dma_addr_t rx_ring_dma; | 364 | dma_addr_t rx_ring_dma; |
| 365 | struct timer_list timer; /* Media monitoring timer. */ | 365 | struct timer_list timer; /* Media monitoring timer. */ |
| 366 | /* ethtool extra stats */ | ||
| 367 | struct { | ||
| 368 | u64 tx_multiple_collisions; | ||
| 369 | u64 tx_single_collisions; | ||
| 370 | u64 tx_late_collisions; | ||
| 371 | u64 tx_deferred; | ||
| 372 | u64 tx_deferred_excessive; | ||
| 373 | u64 tx_aborted; | ||
| 374 | u64 tx_bcasts; | ||
| 375 | u64 rx_bcasts; | ||
| 376 | u64 tx_mcasts; | ||
| 377 | u64 rx_mcasts; | ||
| 378 | } xstats; | ||
| 366 | /* Frequently used values: keep some adjacent for cache effect. */ | 379 | /* Frequently used values: keep some adjacent for cache effect. */ |
| 367 | spinlock_t lock; | 380 | spinlock_t lock; |
| 368 | int msg_enable; | 381 | int msg_enable; |
| @@ -1486,21 +1499,34 @@ static struct net_device_stats *get_stats(struct net_device *dev) | |||
| 1486 | { | 1499 | { |
| 1487 | struct netdev_private *np = netdev_priv(dev); | 1500 | struct netdev_private *np = netdev_priv(dev); |
| 1488 | void __iomem *ioaddr = np->base; | 1501 | void __iomem *ioaddr = np->base; |
| 1489 | int i; | ||
| 1490 | unsigned long flags; | 1502 | unsigned long flags; |
| 1503 | u8 late_coll, single_coll, mult_coll; | ||
| 1491 | 1504 | ||
| 1492 | spin_lock_irqsave(&np->statlock, flags); | 1505 | spin_lock_irqsave(&np->statlock, flags); |
| 1493 | /* The chip only need report frame silently dropped. */ | 1506 | /* The chip only need report frame silently dropped. */ |
| 1494 | dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); | 1507 | dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); |
| 1495 | dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK); | 1508 | dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK); |
| 1496 | dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK); | 1509 | dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK); |
| 1497 | dev->stats.collisions += ioread8(ioaddr + StatsLateColl); | ||
| 1498 | dev->stats.collisions += ioread8(ioaddr + StatsMultiColl); | ||
| 1499 | dev->stats.collisions += ioread8(ioaddr + StatsOneColl); | ||
| 1500 | dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); | 1510 | dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); |
| 1501 | ioread8(ioaddr + StatsTxDefer); | 1511 | |
| 1502 | for (i = StatsTxDefer; i <= StatsMcastRx; i++) | 1512 | mult_coll = ioread8(ioaddr + StatsMultiColl); |
| 1503 | ioread8(ioaddr + i); | 1513 | np->xstats.tx_multiple_collisions += mult_coll; |
| 1514 | single_coll = ioread8(ioaddr + StatsOneColl); | ||
| 1515 | np->xstats.tx_single_collisions += single_coll; | ||
| 1516 | late_coll = ioread8(ioaddr + StatsLateColl); | ||
| 1517 | np->xstats.tx_late_collisions += late_coll; | ||
| 1518 | dev->stats.collisions += mult_coll | ||
| 1519 | + single_coll | ||
| 1520 | + late_coll; | ||
| 1521 | |||
| 1522 | np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer); | ||
| 1523 | np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer); | ||
| 1524 | np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort); | ||
| 1525 | np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx); | ||
| 1526 | np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx); | ||
| 1527 | np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx); | ||
| 1528 | np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx); | ||
| 1529 | |||
| 1504 | dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); | 1530 | dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); |
| 1505 | dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; | 1531 | dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; |
| 1506 | dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); | 1532 | dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); |
| @@ -1566,6 +1592,21 @@ static int __set_mac_addr(struct net_device *dev) | |||
| 1566 | return 0; | 1592 | return 0; |
| 1567 | } | 1593 | } |
| 1568 | 1594 | ||
| 1595 | static const struct { | ||
| 1596 | const char name[ETH_GSTRING_LEN]; | ||
| 1597 | } sundance_stats[] = { | ||
| 1598 | { "tx_multiple_collisions" }, | ||
| 1599 | { "tx_single_collisions" }, | ||
| 1600 | { "tx_late_collisions" }, | ||
| 1601 | { "tx_deferred" }, | ||
| 1602 | { "tx_deferred_excessive" }, | ||
| 1603 | { "tx_aborted" }, | ||
| 1604 | { "tx_bcasts" }, | ||
| 1605 | { "rx_bcasts" }, | ||
| 1606 | { "tx_mcasts" }, | ||
| 1607 | { "rx_mcasts" }, | ||
| 1608 | }; | ||
| 1609 | |||
| 1569 | static int check_if_running(struct net_device *dev) | 1610 | static int check_if_running(struct net_device *dev) |
| 1570 | { | 1611 | { |
| 1571 | if (!netif_running(dev)) | 1612 | if (!netif_running(dev)) |
| @@ -1624,6 +1665,42 @@ static void set_msglevel(struct net_device *dev, u32 val) | |||
| 1624 | np->msg_enable = val; | 1665 | np->msg_enable = val; |
| 1625 | } | 1666 | } |
| 1626 | 1667 | ||
| 1668 | static void get_strings(struct net_device *dev, u32 stringset, | ||
| 1669 | u8 *data) | ||
| 1670 | { | ||
| 1671 | if (stringset == ETH_SS_STATS) | ||
| 1672 | memcpy(data, sundance_stats, sizeof(sundance_stats)); | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | static int get_sset_count(struct net_device *dev, int sset) | ||
| 1676 | { | ||
| 1677 | switch (sset) { | ||
| 1678 | case ETH_SS_STATS: | ||
| 1679 | return ARRAY_SIZE(sundance_stats); | ||
| 1680 | default: | ||
| 1681 | return -EOPNOTSUPP; | ||
| 1682 | } | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | static void get_ethtool_stats(struct net_device *dev, | ||
| 1686 | struct ethtool_stats *stats, u64 *data) | ||
| 1687 | { | ||
| 1688 | struct netdev_private *np = netdev_priv(dev); | ||
| 1689 | int i = 0; | ||
| 1690 | |||
| 1691 | get_stats(dev); | ||
| 1692 | data[i++] = np->xstats.tx_multiple_collisions; | ||
| 1693 | data[i++] = np->xstats.tx_single_collisions; | ||
| 1694 | data[i++] = np->xstats.tx_late_collisions; | ||
| 1695 | data[i++] = np->xstats.tx_deferred; | ||
| 1696 | data[i++] = np->xstats.tx_deferred_excessive; | ||
| 1697 | data[i++] = np->xstats.tx_aborted; | ||
| 1698 | data[i++] = np->xstats.tx_bcasts; | ||
| 1699 | data[i++] = np->xstats.rx_bcasts; | ||
| 1700 | data[i++] = np->xstats.tx_mcasts; | ||
| 1701 | data[i++] = np->xstats.rx_mcasts; | ||
| 1702 | } | ||
| 1703 | |||
| 1627 | static const struct ethtool_ops ethtool_ops = { | 1704 | static const struct ethtool_ops ethtool_ops = { |
| 1628 | .begin = check_if_running, | 1705 | .begin = check_if_running, |
| 1629 | .get_drvinfo = get_drvinfo, | 1706 | .get_drvinfo = get_drvinfo, |
| @@ -1633,6 +1710,9 @@ static const struct ethtool_ops ethtool_ops = { | |||
| 1633 | .get_link = get_link, | 1710 | .get_link = get_link, |
| 1634 | .get_msglevel = get_msglevel, | 1711 | .get_msglevel = get_msglevel, |
| 1635 | .set_msglevel = set_msglevel, | 1712 | .set_msglevel = set_msglevel, |
| 1713 | .get_strings = get_strings, | ||
| 1714 | .get_sset_count = get_sset_count, | ||
| 1715 | .get_ethtool_stats = get_ethtool_stats, | ||
| 1636 | }; | 1716 | }; |
| 1637 | 1717 | ||
| 1638 | static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 1718 | static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
