diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2005-09-14 12:45:44 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-16 02:51:31 -0400 |
commit | 8b51292764a0ed46d7eb6bead4625ba83ee2ec05 (patch) | |
tree | 20cf43cd3b26099542072fac695a50d0d8dc57a0 /drivers/net | |
parent | ed4b9f8014db4f343e89b44b7c5ca355f439ce36 (diff) |
[PATCH] 8139cp: allocate statistics space only when needed
Don't crash if ethtool statistics are requested and device is down.
Fix is to allocate pci space for statistics only when needed.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/8139cp.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 34b80de34fae..bc537440ca02 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -353,8 +353,6 @@ struct cp_private { | |||
353 | 353 | ||
354 | struct net_device_stats net_stats; | 354 | struct net_device_stats net_stats; |
355 | struct cp_extra_stats cp_stats; | 355 | struct cp_extra_stats cp_stats; |
356 | struct cp_dma_stats *nic_stats; | ||
357 | dma_addr_t nic_stats_dma; | ||
358 | 356 | ||
359 | unsigned rx_tail ____cacheline_aligned; | 357 | unsigned rx_tail ____cacheline_aligned; |
360 | struct cp_desc *rx_ring; | 358 | struct cp_desc *rx_ring; |
@@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp) | |||
1143 | cp->rx_ring = mem; | 1141 | cp->rx_ring = mem; |
1144 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; | 1142 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; |
1145 | 1143 | ||
1146 | mem += (CP_RING_BYTES - CP_STATS_SIZE); | ||
1147 | cp->nic_stats = mem; | ||
1148 | cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); | ||
1149 | |||
1150 | return cp_init_rings(cp); | 1144 | return cp_init_rings(cp); |
1151 | } | 1145 | } |
1152 | 1146 | ||
@@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp) | |||
1187 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); | 1181 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); |
1188 | cp->rx_ring = NULL; | 1182 | cp->rx_ring = NULL; |
1189 | cp->tx_ring = NULL; | 1183 | cp->tx_ring = NULL; |
1190 | cp->nic_stats = NULL; | ||
1191 | } | 1184 | } |
1192 | 1185 | ||
1193 | static int cp_open (struct net_device *dev) | 1186 | static int cp_open (struct net_device *dev) |
@@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1516 | struct ethtool_stats *estats, u64 *tmp_stats) | 1509 | struct ethtool_stats *estats, u64 *tmp_stats) |
1517 | { | 1510 | { |
1518 | struct cp_private *cp = netdev_priv(dev); | 1511 | struct cp_private *cp = netdev_priv(dev); |
1512 | struct cp_dma_stats *nic_stats; | ||
1513 | dma_addr_t dma; | ||
1519 | int i; | 1514 | int i; |
1520 | 1515 | ||
1521 | memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); | 1516 | nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); |
1517 | if (!nic_stats) | ||
1518 | return; | ||
1522 | 1519 | ||
1523 | /* begin NIC statistics dump */ | 1520 | /* begin NIC statistics dump */ |
1524 | cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); | 1521 | cpw32(StatsAddr + 4, (u64)dma >> 32); |
1525 | cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); | 1522 | cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); |
1526 | cpr32(StatsAddr); | 1523 | cpr32(StatsAddr); |
1527 | 1524 | ||
1528 | for (i = 0; i < 1000; i++) { | 1525 | for (i = 0; i < 1000; i++) { |
@@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1532 | } | 1529 | } |
1533 | cpw32(StatsAddr, 0); | 1530 | cpw32(StatsAddr, 0); |
1534 | cpw32(StatsAddr + 4, 0); | 1531 | cpw32(StatsAddr + 4, 0); |
1532 | cpr32(StatsAddr); | ||
1535 | 1533 | ||
1536 | i = 0; | 1534 | i = 0; |
1537 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); | 1535 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); |
1538 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); | 1536 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); |
1539 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); | 1537 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); |
1540 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); | 1538 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); |
1541 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); | 1539 | tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); |
1542 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); | 1540 | tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); |
1543 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); | 1541 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); |
1544 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); | 1542 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); |
1545 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); | 1543 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); |
1546 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); | 1544 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); |
1547 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); | 1545 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); |
1548 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); | 1546 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); |
1549 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); | 1547 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); |
1550 | tmp_stats[i++] = cp->cp_stats.rx_frags; | 1548 | tmp_stats[i++] = cp->cp_stats.rx_frags; |
1551 | if (i != CP_NUM_STATS) | 1549 | if (i != CP_NUM_STATS) |
1552 | BUG(); | 1550 | BUG(); |
1551 | |||
1552 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); | ||
1553 | } | 1553 | } |
1554 | 1554 | ||
1555 | static struct ethtool_ops cp_ethtool_ops = { | 1555 | static struct ethtool_ops cp_ethtool_ops = { |