Skip to content

Commit

Permalink
Merge branch 'gianfar-64-bit-stats'
Browse files Browse the repository at this point in the history
Esben Haabendal says:

====================
net: gianfar: 64-bit statistics and rx_missed_errors counter

This series replaces the legacy 32-bit statistics to proper 64-bit ditto,
and implements rx_missed_errors counter on top of that.

The device supports a 16-bit RDRP counter, and a related carry bit and
interrupt, which allows implementation of a robust 64-bit counter.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jun 17, 2021
2 parents 55d96f7 + 14870b7 commit 4de7725
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 25 deletions.
76 changes: 56 additions & 20 deletions drivers/net/ethernet/freescale/gianfar.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,32 +274,44 @@ static void gfar_configure_coalescing_all(struct gfar_private *priv)
gfar_configure_coalescing(priv, 0xFF, 0xFF);
}

static struct net_device_stats *gfar_get_stats(struct net_device *dev)
static void gfar_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
struct gfar_private *priv = netdev_priv(dev);
unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0;
unsigned long tx_packets = 0, tx_bytes = 0;
int i;

for (i = 0; i < priv->num_rx_queues; i++) {
rx_packets += priv->rx_queue[i]->stats.rx_packets;
rx_bytes += priv->rx_queue[i]->stats.rx_bytes;
rx_dropped += priv->rx_queue[i]->stats.rx_dropped;
stats->rx_packets += priv->rx_queue[i]->stats.rx_packets;
stats->rx_bytes += priv->rx_queue[i]->stats.rx_bytes;
stats->rx_dropped += priv->rx_queue[i]->stats.rx_dropped;
}

dev->stats.rx_packets = rx_packets;
dev->stats.rx_bytes = rx_bytes;
dev->stats.rx_dropped = rx_dropped;

for (i = 0; i < priv->num_tx_queues; i++) {
tx_bytes += priv->tx_queue[i]->stats.tx_bytes;
tx_packets += priv->tx_queue[i]->stats.tx_packets;
stats->tx_bytes += priv->tx_queue[i]->stats.tx_bytes;
stats->tx_packets += priv->tx_queue[i]->stats.tx_packets;
}

dev->stats.tx_bytes = tx_bytes;
dev->stats.tx_packets = tx_packets;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
struct rmon_mib __iomem *rmon = &priv->gfargrp[0].regs->rmon;
unsigned long flags;
u32 rdrp, car, car_before;
u64 rdrp_offset;

spin_lock_irqsave(&priv->rmon_overflow.lock, flags);
car = gfar_read(&rmon->car1) & CAR1_C1RDR;
do {
car_before = car;
rdrp = gfar_read(&rmon->rdrp);
car = gfar_read(&rmon->car1) & CAR1_C1RDR;
} while (car != car_before);
if (car) {
priv->rmon_overflow.rdrp++;
gfar_write(&rmon->car1, car);
}
rdrp_offset = priv->rmon_overflow.rdrp;
spin_unlock_irqrestore(&priv->rmon_overflow.lock, flags);

return &dev->stats;
stats->rx_missed_errors = rdrp + (rdrp_offset << 16);
}
}

/* Set the appropriate hash bit for the given addr */
Expand Down Expand Up @@ -390,7 +402,8 @@ static void gfar_ints_enable(struct gfar_private *priv)
for (i = 0; i < priv->num_grps; i++) {
struct gfar __iomem *regs = priv->gfargrp[i].regs;
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
gfar_write(&regs->imask,
IMASK_DEFAULT | priv->rmon_overflow.imask);
}
}

Expand Down Expand Up @@ -2298,7 +2311,7 @@ static irqreturn_t gfar_receive(int irq, void *grp_id)
if (likely(napi_schedule_prep(&grp->napi_rx))) {
spin_lock_irqsave(&grp->grplock, flags);
imask = gfar_read(&grp->regs->imask);
imask &= IMASK_RX_DISABLED;
imask &= IMASK_RX_DISABLED | grp->priv->rmon_overflow.imask;
gfar_write(&grp->regs->imask, imask);
spin_unlock_irqrestore(&grp->grplock, flags);
__napi_schedule(&grp->napi_rx);
Expand All @@ -2322,7 +2335,7 @@ static irqreturn_t gfar_transmit(int irq, void *grp_id)
if (likely(napi_schedule_prep(&grp->napi_tx))) {
spin_lock_irqsave(&grp->grplock, flags);
imask = gfar_read(&grp->regs->imask);
imask &= IMASK_TX_DISABLED;
imask &= IMASK_TX_DISABLED | grp->priv->rmon_overflow.imask;
gfar_write(&grp->regs->imask, imask);
spin_unlock_irqrestore(&grp->grplock, flags);
__napi_schedule(&grp->napi_tx);
Expand Down Expand Up @@ -2693,6 +2706,18 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
}
netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
if (events & IEVENT_MSRO) {
struct rmon_mib __iomem *rmon = &regs->rmon;
u32 car;

spin_lock(&priv->rmon_overflow.lock);
car = gfar_read(&rmon->car1) & CAR1_C1RDR;
if (car) {
priv->rmon_overflow.rdrp++;
gfar_write(&rmon->car1, car);
}
spin_unlock(&priv->rmon_overflow.lock);
}
if (events & IEVENT_BSY) {
dev->stats.rx_over_errors++;
atomic64_inc(&priv->extra_stats.rx_bsy);
Expand Down Expand Up @@ -3109,11 +3134,14 @@ static void gfar_hw_init(struct gfar_private *priv)

/* Zero out the rmon mib registers if it has them */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib));
memset_io(&regs->rmon, 0, offsetof(struct rmon_mib, car1));

/* Mask off the CAM interrupts */
gfar_write(&regs->rmon.cam1, 0xffffffff);
gfar_write(&regs->rmon.cam2, 0xffffffff);
/* Clear the CAR registers (w1c style) */
gfar_write(&regs->rmon.car1, 0xffffffff);
gfar_write(&regs->rmon.car2, 0xffffffff);
}

/* Initialize ECNTRL */
Expand Down Expand Up @@ -3157,7 +3185,7 @@ static const struct net_device_ops gfar_netdev_ops = {
.ndo_set_rx_mode = gfar_set_multi,
.ndo_tx_timeout = gfar_timeout,
.ndo_do_ioctl = gfar_ioctl,
.ndo_get_stats = gfar_get_stats,
.ndo_get_stats64 = gfar_get_stats64,
.ndo_change_carrier = fixed_phy_change_carrier,
.ndo_set_mac_address = gfar_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
Expand Down Expand Up @@ -3267,6 +3295,14 @@ static int gfar_probe(struct platform_device *ofdev)

gfar_hw_init(priv);

if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
struct rmon_mib __iomem *rmon = &priv->gfargrp[0].regs->rmon;

spin_lock_init(&priv->rmon_overflow.lock);
priv->rmon_overflow.imask = IMASK_MSRO;
gfar_write(&rmon->cam1, gfar_read(&rmon->cam1) & ~CAM1_M1RDR);
}

/* Carrier starts down, phylib will bring it up */
netif_carrier_off(dev);

Expand Down
74 changes: 69 additions & 5 deletions drivers/net/ethernet/freescale/gianfar.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,60 @@ struct ethtool_rx_list {
#define RQFPR_PER 0x00000002
#define RQFPR_EER 0x00000001

/* CAR1 bits */
#define CAR1_C164 0x80000000
#define CAR1_C1127 0x40000000
#define CAR1_C1255 0x20000000
#define CAR1_C1511 0x10000000
#define CAR1_C11K 0x08000000
#define CAR1_C1MAX 0x04000000
#define CAR1_C1MGV 0x02000000
#define CAR1_C1REJ 0x00020000
#define CAR1_C1RBY 0x00010000
#define CAR1_C1RPK 0x00008000
#define CAR1_C1RFC 0x00004000
#define CAR1_C1RMC 0x00002000
#define CAR1_C1RBC 0x00001000
#define CAR1_C1RXC 0x00000800
#define CAR1_C1RXP 0x00000400
#define CAR1_C1RXU 0x00000200
#define CAR1_C1RAL 0x00000100
#define CAR1_C1RFL 0x00000080
#define CAR1_C1RCD 0x00000040
#define CAR1_C1RCS 0x00000020
#define CAR1_C1RUN 0x00000010
#define CAR1_C1ROV 0x00000008
#define CAR1_C1RFR 0x00000004
#define CAR1_C1RJB 0x00000002
#define CAR1_C1RDR 0x00000001

/* CAM1 bits */
#define CAM1_M164 0x80000000
#define CAM1_M1127 0x40000000
#define CAM1_M1255 0x20000000
#define CAM1_M1511 0x10000000
#define CAM1_M11K 0x08000000
#define CAM1_M1MAX 0x04000000
#define CAM1_M1MGV 0x02000000
#define CAM1_M1REJ 0x00020000
#define CAM1_M1RBY 0x00010000
#define CAM1_M1RPK 0x00008000
#define CAM1_M1RFC 0x00004000
#define CAM1_M1RMC 0x00002000
#define CAM1_M1RBC 0x00001000
#define CAM1_M1RXC 0x00000800
#define CAM1_M1RXP 0x00000400
#define CAM1_M1RXU 0x00000200
#define CAM1_M1RAL 0x00000100
#define CAM1_M1RFL 0x00000080
#define CAM1_M1RCD 0x00000040
#define CAM1_M1RCS 0x00000020
#define CAM1_M1RUN 0x00000010
#define CAM1_M1ROV 0x00000008
#define CAM1_M1RFR 0x00000004
#define CAM1_M1RJB 0x00000002
#define CAM1_M1RDR 0x00000001

/* TxBD status field bits */
#define TXBD_READY 0x8000
#define TXBD_PADCRC 0x4000
Expand Down Expand Up @@ -609,6 +663,15 @@ struct rmon_mib
u32 cam2; /* 0x.73c - Carry Mask Register Two */
};

struct rmon_overflow {
/* lock for synchronization of the rdrp field of this struct, and
* CAR1/CAR2 registers
*/
spinlock_t lock;
u32 imask;
u64 rdrp;
};

struct gfar_extra_stats {
atomic64_t rx_alloc_err;
atomic64_t rx_large;
Expand Down Expand Up @@ -913,8 +976,8 @@ enum {
* Per TX queue stats
*/
struct tx_q_stats {
unsigned long tx_packets;
unsigned long tx_bytes;
u64 tx_packets;
u64 tx_bytes;
};

/**
Expand Down Expand Up @@ -963,9 +1026,9 @@ struct gfar_priv_tx_q {
* Per RX queue stats
*/
struct rx_q_stats {
unsigned long rx_packets;
unsigned long rx_bytes;
unsigned long rx_dropped;
u64 rx_packets;
u64 rx_bytes;
u64 rx_dropped;
};

struct gfar_rx_buff {
Expand Down Expand Up @@ -1096,6 +1159,7 @@ struct gfar_private {

/* Network Statistics */
struct gfar_extra_stats extra_stats;
struct rmon_overflow rmon_overflow;

/* PHY stuff */
phy_interface_t interface;
Expand Down

0 comments on commit 4de7725

Please sign in to comment.