Skip to content

Commit

Permalink
[PATCH] 8139cp: allocate statistics space only when needed
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stephen Hemminger authored and Jeff Garzik committed Sep 16, 2005
1 parent ed4b9f8 commit 8b51292
Showing 1 changed file with 23 additions and 23 deletions.
46 changes: 23 additions & 23 deletions drivers/net/8139cp.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,6 @@ struct cp_private {

struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
struct cp_dma_stats *nic_stats;
dma_addr_t nic_stats_dma;

unsigned rx_tail ____cacheline_aligned;
struct cp_desc *rx_ring;
Expand Down Expand Up @@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp)
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];

mem += (CP_RING_BYTES - CP_STATS_SIZE);
cp->nic_stats = mem;
cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);

return cp_init_rings(cp);
}

Expand Down Expand Up @@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
cp->nic_stats = NULL;
}

static int cp_open (struct net_device *dev)
Expand Down Expand Up @@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = netdev_priv(dev);
struct cp_dma_stats *nic_stats;
dma_addr_t dma;
int i;

memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
if (!nic_stats)
return;

/* begin NIC statistics dump */
cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
cpw32(StatsAddr + 4, (u64)dma >> 32);
cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
cpr32(StatsAddr);

for (i = 0; i < 1000; i++) {
Expand All @@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev,
}
cpw32(StatsAddr, 0);
cpw32(StatsAddr + 4, 0);
cpr32(StatsAddr);

i = 0;
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
if (i != CP_NUM_STATS)
BUG();

pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}

static struct ethtool_ops cp_ethtool_ops = {
Expand Down

0 comments on commit 8b51292

Please sign in to comment.