Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'gianfar-64-bit-stats'

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 <davem@davemloft.net>

+125 -25
+56 -20
drivers/net/ethernet/freescale/gianfar.c
··· 274 274 gfar_configure_coalescing(priv, 0xFF, 0xFF); 275 275 } 276 276 277 - static struct net_device_stats *gfar_get_stats(struct net_device *dev) 277 + static void gfar_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) 278 278 { 279 279 struct gfar_private *priv = netdev_priv(dev); 280 - unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; 281 - unsigned long tx_packets = 0, tx_bytes = 0; 282 280 int i; 283 281 284 282 for (i = 0; i < priv->num_rx_queues; i++) { 285 - rx_packets += priv->rx_queue[i]->stats.rx_packets; 286 - rx_bytes += priv->rx_queue[i]->stats.rx_bytes; 287 - rx_dropped += priv->rx_queue[i]->stats.rx_dropped; 283 + stats->rx_packets += priv->rx_queue[i]->stats.rx_packets; 284 + stats->rx_bytes += priv->rx_queue[i]->stats.rx_bytes; 285 + stats->rx_dropped += priv->rx_queue[i]->stats.rx_dropped; 288 286 } 289 - 290 - dev->stats.rx_packets = rx_packets; 291 - dev->stats.rx_bytes = rx_bytes; 292 - dev->stats.rx_dropped = rx_dropped; 293 287 294 288 for (i = 0; i < priv->num_tx_queues; i++) { 295 - tx_bytes += priv->tx_queue[i]->stats.tx_bytes; 296 - tx_packets += priv->tx_queue[i]->stats.tx_packets; 289 + stats->tx_bytes += priv->tx_queue[i]->stats.tx_bytes; 290 + stats->tx_packets += priv->tx_queue[i]->stats.tx_packets; 297 291 } 298 292 299 - dev->stats.tx_bytes = tx_bytes; 300 - dev->stats.tx_packets = tx_packets; 293 + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { 294 + struct rmon_mib __iomem *rmon = &priv->gfargrp[0].regs->rmon; 295 + unsigned long flags; 296 + u32 rdrp, car, car_before; 297 + u64 rdrp_offset; 301 298 302 - return &dev->stats; 299 + spin_lock_irqsave(&priv->rmon_overflow.lock, flags); 300 + car = gfar_read(&rmon->car1) & CAR1_C1RDR; 301 + do { 302 + car_before = car; 303 + rdrp = gfar_read(&rmon->rdrp); 304 + car = gfar_read(&rmon->car1) & CAR1_C1RDR; 305 + } while (car != car_before); 306 + if (car) { 307 + priv->rmon_overflow.rdrp++; 308 + gfar_write(&rmon->car1, car); 309 + } 310 + rdrp_offset = priv->rmon_overflow.rdrp; 311 + spin_unlock_irqrestore(&priv->rmon_overflow.lock, flags); 312 + 313 + stats->rx_missed_errors = rdrp + (rdrp_offset << 16); 314 + } 303 315 } 304 316 305 317 /* Set the appropriate hash bit for the given addr */ ··· 402 390 for (i = 0; i < priv->num_grps; i++) { 403 391 struct gfar __iomem *regs = priv->gfargrp[i].regs; 404 392 /* Unmask the interrupts we look for */ 405 - gfar_write(&regs->imask, IMASK_DEFAULT); 393 + gfar_write(&regs->imask, 394 + IMASK_DEFAULT | priv->rmon_overflow.imask); 406 395 } 407 396 } 408 397 ··· 2311 2298 if (likely(napi_schedule_prep(&grp->napi_rx))) { 2312 2299 spin_lock_irqsave(&grp->grplock, flags); 2313 2300 imask = gfar_read(&grp->regs->imask); 2314 - imask &= IMASK_RX_DISABLED; 2301 + imask &= IMASK_RX_DISABLED | grp->priv->rmon_overflow.imask; 2315 2302 gfar_write(&grp->regs->imask, imask); 2316 2303 spin_unlock_irqrestore(&grp->grplock, flags); 2317 2304 __napi_schedule(&grp->napi_rx); ··· 2335 2322 if (likely(napi_schedule_prep(&grp->napi_tx))) { 2336 2323 spin_lock_irqsave(&grp->grplock, flags); 2337 2324 imask = gfar_read(&grp->regs->imask); 2338 - imask &= IMASK_TX_DISABLED; 2325 + imask &= IMASK_TX_DISABLED | grp->priv->rmon_overflow.imask; 2339 2326 gfar_write(&grp->regs->imask, imask); 2340 2327 spin_unlock_irqrestore(&grp->grplock, flags); 2341 2328 __napi_schedule(&grp->napi_tx); ··· 2705 2692 schedule_work(&priv->reset_task); 2706 2693 } 2707 2694 netif_dbg(priv, tx_err, dev, "Transmit Error\n"); 2695 + } 2696 + if (events & IEVENT_MSRO) { 2697 + struct rmon_mib __iomem *rmon = &regs->rmon; 2698 + u32 car; 2699 + 2700 + spin_lock(&priv->rmon_overflow.lock); 2701 + car = gfar_read(&rmon->car1) & CAR1_C1RDR; 2702 + if (car) { 2703 + priv->rmon_overflow.rdrp++; 2704 + gfar_write(&rmon->car1, car); 2705 + } 2706 + spin_unlock(&priv->rmon_overflow.lock); 2708 2707 } 2709 2708 if (events & IEVENT_BSY) { 2710 2709 dev->stats.rx_over_errors++; ··· 3134 3109 3135 3110 /* Zero out the rmon mib registers if it has them */ 3136 3111 if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { 3137 - memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib)); 3112 + memset_io(&regs->rmon, 0, offsetof(struct rmon_mib, car1)); 3138 3113 3139 3114 /* Mask off the CAM interrupts */ 3140 3115 gfar_write(&regs->rmon.cam1, 0xffffffff); 3141 3116 gfar_write(&regs->rmon.cam2, 0xffffffff); 3117 + /* Clear the CAR registers (w1c style) */ 3118 + gfar_write(&regs->rmon.car1, 0xffffffff); 3119 + gfar_write(&regs->rmon.car2, 0xffffffff); 3142 3120 } 3143 3121 3144 3122 /* Initialize ECNTRL */ ··· 3185 3157 .ndo_set_rx_mode = gfar_set_multi, 3186 3158 .ndo_tx_timeout = gfar_timeout, 3187 3159 .ndo_do_ioctl = gfar_ioctl, 3188 - .ndo_get_stats = gfar_get_stats, 3160 + .ndo_get_stats64 = gfar_get_stats64, 3189 3161 .ndo_change_carrier = fixed_phy_change_carrier, 3190 3162 .ndo_set_mac_address = gfar_set_mac_addr, 3191 3163 .ndo_validate_addr = eth_validate_addr, ··· 3294 3266 set_bit(GFAR_DOWN, &priv->state); 3295 3267 3296 3268 gfar_hw_init(priv); 3269 + 3270 + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { 3271 + struct rmon_mib __iomem *rmon = &priv->gfargrp[0].regs->rmon; 3272 + 3273 + spin_lock_init(&priv->rmon_overflow.lock); 3274 + priv->rmon_overflow.imask = IMASK_MSRO; 3275 + gfar_write(&rmon->cam1, gfar_read(&rmon->cam1) & ~CAM1_M1RDR); 3276 + } 3297 3277 3298 3278 /* Carrier starts down, phylib will bring it up */ 3299 3279 netif_carrier_off(dev);
+69 -5
drivers/net/ethernet/freescale/gianfar.h
··· 445 445 #define RQFPR_PER 0x00000002 446 446 #define RQFPR_EER 0x00000001 447 447 448 + /* CAR1 bits */ 449 + #define CAR1_C164 0x80000000 450 + #define CAR1_C1127 0x40000000 451 + #define CAR1_C1255 0x20000000 452 + #define CAR1_C1511 0x10000000 453 + #define CAR1_C11K 0x08000000 454 + #define CAR1_C1MAX 0x04000000 455 + #define CAR1_C1MGV 0x02000000 456 + #define CAR1_C1REJ 0x00020000 457 + #define CAR1_C1RBY 0x00010000 458 + #define CAR1_C1RPK 0x00008000 459 + #define CAR1_C1RFC 0x00004000 460 + #define CAR1_C1RMC 0x00002000 461 + #define CAR1_C1RBC 0x00001000 462 + #define CAR1_C1RXC 0x00000800 463 + #define CAR1_C1RXP 0x00000400 464 + #define CAR1_C1RXU 0x00000200 465 + #define CAR1_C1RAL 0x00000100 466 + #define CAR1_C1RFL 0x00000080 467 + #define CAR1_C1RCD 0x00000040 468 + #define CAR1_C1RCS 0x00000020 469 + #define CAR1_C1RUN 0x00000010 470 + #define CAR1_C1ROV 0x00000008 471 + #define CAR1_C1RFR 0x00000004 472 + #define CAR1_C1RJB 0x00000002 473 + #define CAR1_C1RDR 0x00000001 474 + 475 + /* CAM1 bits */ 476 + #define CAM1_M164 0x80000000 477 + #define CAM1_M1127 0x40000000 478 + #define CAM1_M1255 0x20000000 479 + #define CAM1_M1511 0x10000000 480 + #define CAM1_M11K 0x08000000 481 + #define CAM1_M1MAX 0x04000000 482 + #define CAM1_M1MGV 0x02000000 483 + #define CAM1_M1REJ 0x00020000 484 + #define CAM1_M1RBY 0x00010000 485 + #define CAM1_M1RPK 0x00008000 486 + #define CAM1_M1RFC 0x00004000 487 + #define CAM1_M1RMC 0x00002000 488 + #define CAM1_M1RBC 0x00001000 489 + #define CAM1_M1RXC 0x00000800 490 + #define CAM1_M1RXP 0x00000400 491 + #define CAM1_M1RXU 0x00000200 492 + #define CAM1_M1RAL 0x00000100 493 + #define CAM1_M1RFL 0x00000080 494 + #define CAM1_M1RCD 0x00000040 495 + #define CAM1_M1RCS 0x00000020 496 + #define CAM1_M1RUN 0x00000010 497 + #define CAM1_M1ROV 0x00000008 498 + #define CAM1_M1RFR 0x00000004 499 + #define CAM1_M1RJB 0x00000002 500 + #define CAM1_M1RDR 0x00000001 501 + 448 502 /* TxBD status field bits */ 449 503 #define TXBD_READY 0x8000 450 504 #define TXBD_PADCRC 0x4000 ··· 661 607 u32 car2; /* 0x.734 - Carry Register Two */ 662 608 u32 cam1; /* 0x.738 - Carry Mask Register One */ 663 609 u32 cam2; /* 0x.73c - Carry Mask Register Two */ 610 + }; 611 + 612 + struct rmon_overflow { 613 + /* lock for synchronization of the rdrp field of this struct, and 614 + * CAR1/CAR2 registers 615 + */ 616 + spinlock_t lock; 617 + u32 imask; 618 + u64 rdrp; 664 619 }; 665 620 666 621 struct gfar_extra_stats { ··· 976 913 * Per TX queue stats 977 914 */ 978 915 struct tx_q_stats { 979 - unsigned long tx_packets; 980 - unsigned long tx_bytes; 916 + u64 tx_packets; 917 + u64 tx_bytes; 981 918 }; 982 919 983 920 /** ··· 1026 963 * Per RX queue stats 1027 964 */ 1028 965 struct rx_q_stats { 1029 - unsigned long rx_packets; 1030 - unsigned long rx_bytes; 1031 - unsigned long rx_dropped; 966 + u64 rx_packets; 967 + u64 rx_bytes; 968 + u64 rx_dropped; 1032 969 }; 1033 970 1034 971 struct gfar_rx_buff { ··· 1159 1096 1160 1097 /* Network Statistics */ 1161 1098 struct gfar_extra_stats extra_stats; 1099 + struct rmon_overflow rmon_overflow; 1162 1100 1163 1101 /* PHY stuff */ 1164 1102 phy_interface_t interface;