Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 122777
b: refs/heads/master
c: b8a606b
h: refs/heads/master
i:
  122775: 627b0a0
v: v3
  • Loading branch information
Jesper Dangaard Brouer authored and David S. Miller committed Dec 19, 2008
1 parent ee09d59 commit 1301169
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5664dd5561850df580414783cf3c8e0aa834c62e
refs/heads/master: b8a606b871d37e03b92be1bd3deedeee97ea4f13
51 changes: 51 additions & 0 deletions trunk/drivers/net/niu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3527,6 +3527,51 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp)
}
}

static inline void niu_sync_rx_discard_stats(struct niu *np,
struct rx_ring_info *rp,
const int limit)
{
/* This elaborate scheme is needed for reading the RX discard
* counters, as they are only 16-bit and can overflow quickly,
* and because the overflow indication bit is not usable as
* the counter value does not wrap, but remains at max value
* 0xFFFF.
*
* In theory and in practice counters can be lost in between
* reading nr64() and clearing the counter nw64(). For this
* reason, the number of counter clearings nw64() is
* limited/reduced though the limit parameter.
*/
int rx_channel = rp->rx_channel;
u32 misc, wred;

/* RXMISC (Receive Miscellaneous Discard Count), covers the
* following discard events: IPP (Input Port Process),
* FFLP/TCAM, Full RCR (Receive Completion Ring) RBR (Receive
* Block Ring) prefetch buffer is empty.
*/
misc = nr64(RXMISC(rx_channel));
if (unlikely((misc & RXMISC_COUNT) > limit)) {
nw64(RXMISC(rx_channel), 0);
rp->rx_errors += misc & RXMISC_COUNT;

if (unlikely(misc & RXMISC_OFLOW))
dev_err(np->device, "rx-%d: Counter overflow "
"RXMISC discard\n", rx_channel);
}

/* WRED (Weighted Random Early Discard) by hardware */
wred = nr64(RED_DIS_CNT(rx_channel));
if (unlikely((wred & RED_DIS_CNT_COUNT) > limit)) {
nw64(RED_DIS_CNT(rx_channel), 0);
rp->rx_dropped += wred & RED_DIS_CNT_COUNT;

if (unlikely(wred & RED_DIS_CNT_OFLOW))
dev_err(np->device, "rx-%d: Counter overflow "
"WRED discard\n", rx_channel);
}
}

static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget)
{
int qlen, rcr_done = 0, work_done = 0;
Expand Down Expand Up @@ -3567,6 +3612,8 @@ static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget)

nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat);

niu_sync_rx_discard_stats(np, rp, 0x7FFF);

return work_done;
}

Expand Down Expand Up @@ -6073,6 +6120,8 @@ static void niu_get_rx_stats(struct niu *np)
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];

niu_sync_rx_discard_stats(np, rp, 0);

pkts += rp->rx_packets;
bytes += rp->rx_bytes;
dropped += rp->rx_dropped;
Expand Down Expand Up @@ -7014,6 +7063,8 @@ static void niu_get_ethtool_stats(struct net_device *dev,
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];

niu_sync_rx_discard_stats(np, rp, 0);

data[0] = rp->rx_channel;
data[1] = rp->rx_packets;
data[2] = rp->rx_bytes;
Expand Down

0 comments on commit 1301169

Please sign in to comment.