forcedeth: minor fixes for stats, rmmod, sparse
Subsystems (3)
v4 cover forcedeth: minor fixes for stats, rmmod, sparse
David,
Thanks for your feedback. Here is v4, with only the (minor) bug fixes for net. I am setting the "new features" patches aside for later (net-next).
Since I am still very much of a newbie with the way net & net-next work, could you please redirect me to some pointer on how/when the schedule works?
Regards,
Tested: 16-way x86_64 + forcedeth
Changes since v3:
- removed feature additions, this leaves minor sparse and stats fixes. Feature additions shipped previously will go to net-next
Changes since v2:
- removed "Fix a race during rmmod of forcedeth" from the series (will look at it separately with original author)
- added "remove unneeded stats updates" and "64-bit stats"
- reordered patches
Changes since v1:
- rebased on top of netdev tip
- do not repeat name of device in netdev_dbg
- do not completely mute TX timeout messages when debug_tx_timeout is not set
- make debug_tx_timeout writable in /sys/module
Note: I am re-submitting "expose module parameters in /sys/module" as
it can be useful in production and I was assured it doesn't add much memory overhead by the sysfs maintainers.
Tested:
16-way x86_64 SMP, dual forcedeth ->
RX bytes:7244556582 (7.2 GB) TX bytes:181904254 (181.9 MB)
############################################
# Patch Set Summary:
David Decotigny (2):
forcedeth: remove unneeded stats updates
forcedeth: fix a few sparse warnings (variable shadowing)
Mandeep Baines (1):
forcedeth: Improve stats counters
Mike Ditto (1):
forcedeth: Acknowledge only interrupts that are being processed
drivers/net/ethernet/nvidia/forcedeth.c | 86 +++++++++++-------------------- 1 files changed, 30 insertions(+), 56 deletions(-)
Signature · 1 line
1.7.3.1
PATCH v4 1/4 forcedeth: Acknowledge only interrupts that are being processed
From: Mike Ditto <[email protected]>
This is to avoid a race, accidentally acknowledging an interrupt that we didn't notice and won't immediately process. This is based solely on code inspection; it is not known if there was an actual bug here.
--- drivers/net/ethernet/nvidia/forcedeth.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)
drivers/net/ethernet/nvidia/forcedeth.c +8 -5
@@ -3398,7 +3398,8 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)for (i =0 ;; i++) { events =readl (base + NvRegMSIXIrqStatus) &NVREG_IRQ_TX_ALL ; -writel (NVREG_IRQ_TX_ALL , base + NvRegMSIXIrqStatus); +writel (events, base + NvRegMSIXIrqStatus); +netdev_dbg (dev,"tx irq events: %08x\n" , events);if (!(events & np->irqmask))break ;
@@ -3509,7 +3510,8 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)for (i =0 ;; i++) { events =readl (base + NvRegMSIXIrqStatus) &NVREG_IRQ_RX_ALL ; -writel (NVREG_IRQ_RX_ALL , base + NvRegMSIXIrqStatus); +writel (events, base + NvRegMSIXIrqStatus); +netdev_dbg (dev,"rx irq events: %08x\n" , events);if (!(events & np->irqmask))break ;
@@ -3553,7 +3555,8 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)for (i =0 ;; i++) { events =readl (base + NvRegMSIXIrqStatus) &NVREG_IRQ_OTHER ; -writel (NVREG_IRQ_OTHER , base + NvRegMSIXIrqStatus); +writel (events, base + NvRegMSIXIrqStatus); +netdev_dbg (dev,"irq events: %08x\n" , events);if (!(events & np->irqmask))break ;
@@ -3617,10 +3620,10 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data)if (!(np->msi_flags &NV_MSI_X_ENABLED )) { events =readl (base + NvRegIrqStatus) &NVREG_IRQSTAT_MASK ; -writel (NVREG_IRQ_TIMER , base + NvRegIrqStatus); +writel (events &NVREG_IRQ_TIMER , base + NvRegIrqStatus); }else { events =readl (base + NvRegMSIXIrqStatus) &NVREG_IRQSTAT_MASK ; -writel (NVREG_IRQ_TIMER , base + NvRegMSIXIrqStatus); +writel (events &NVREG_IRQ_TIMER , base + NvRegMSIXIrqStatus); }pci_push (base);if (!(events &NVREG_IRQ_TIMER ))
Signature · 1 line
1.7.3.1
PATCH v4 2/4 forcedeth: remove unneeded stats updates
In reply to David DecotignyFunction ndo_get_stats() updates most of the stats from hardware registers, making the manual updates un-needed. This change removes these manual updates. Main exception is rx_missed_errors which needs manual update. Another exception is rx_packets, still updated manually in this commit to make sure this patch doesn't change behavior of driver (this is addressed by a later commit in this series).
--- drivers/net/ethernet/nvidia/forcedeth.c | 35 +------------------------------ 1 files changed, 1 insertions(+), 34 deletions(-)
drivers/net/ethernet/nvidia/forcedeth.c +1 -34
@@ -2374,16 +2374,8 @@ static int nv_tx_done(struct net_device *dev, int limit)if (np->desc_ver ==DESC_VER_1 ) {if (flags &NV_TX_LASTPACKET ) {if (flags &NV_TX_ERROR ) { -if (flags &NV_TX_UNDERFLOW ) - dev->stats.tx_fifo_errors++; -if (flags &NV_TX_CARRIERLOST ) - dev->stats.tx_carrier_errors++;if ((flags &NV_TX_RETRYERROR ) && !(flags &NV_TX_RETRYCOUNT_MASK ))nv_legacybackoff_reseed (dev); - dev->stats.tx_errors++; - }else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; }dev_kfree_skb_any (np->get_tx_ctx->skb); np->get_tx_ctx->skb =NULL ;
@@ -2392,16 +2384,8 @@ static int nv_tx_done(struct net_device *dev, int limit) }else {if (flags &NV_TX2_LASTPACKET ) {if (flags &NV_TX2_ERROR ) { -if (flags &NV_TX2_UNDERFLOW ) - dev->stats.tx_fifo_errors++; -if (flags &NV_TX2_CARRIERLOST ) - dev->stats.tx_carrier_errors++;if ((flags &NV_TX2_RETRYERROR ) && !(flags &NV_TX2_RETRYCOUNT_MASK ))nv_legacybackoff_reseed (dev); - dev->stats.tx_errors++; - }else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; }dev_kfree_skb_any (np->get_tx_ctx->skb); np->get_tx_ctx->skb =NULL ;
@@ -2434,9 +2418,7 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit)nv_unmap_txskb (np, np->get_tx_ctx);if (flags &NV_TX2_LASTPACKET ) { -if (!(flags &NV_TX2_ERROR )) - dev->stats.tx_packets++; -else { +if (flags &NV_TX2_ERROR ) {if ((flags &NV_TX2_RETRYERROR ) && !(flags &NV_TX2_RETRYCOUNT_MASK )) {if (np->driver_data &DEV_HAS_GEAR_MODE )nv_gear_backoff_reseed (dev);
@@ -2636,7 +2618,6 @@ static int nv_rx_process(struct net_device *dev, int limit)if ((flags &NV_RX_ERROR_MASK ) ==NV_RX_ERROR4 ) { len =nv_getlen (dev, skb->data, len);if (len <0 ) { - dev->stats.rx_errors++;dev_kfree_skb (skb); goto next_pkt; }
@@ -2650,11 +2631,6 @@ static int nv_rx_process(struct net_device *dev, int limit)else {if (flags &NV_RX_MISSEDFRAME ) dev->stats.rx_missed_errors++; -if (flags &NV_RX_CRCERR ) - dev->stats.rx_crc_errors++; -if (flags &NV_RX_OVERFLOW ) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++;dev_kfree_skb (skb); goto next_pkt; }
@@ -2670,7 +2646,6 @@ static int nv_rx_process(struct net_device *dev, int limit)if ((flags &NV_RX2_ERROR_MASK ) ==NV_RX2_ERROR4 ) { len =nv_getlen (dev, skb->data, len);if (len <0 ) { - dev->stats.rx_errors++;dev_kfree_skb (skb); goto next_pkt; }
@@ -2682,11 +2657,6 @@ static int nv_rx_process(struct net_device *dev, int limit) }/* the rest are hard errors */ else { -if (flags &NV_RX2_CRCERR ) - dev->stats.rx_crc_errors++; -if (flags &NV_RX2_OVERFLOW ) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++;dev_kfree_skb (skb); goto next_pkt; }
@@ -2704,7 +2674,6 @@ static int nv_rx_process(struct net_device *dev, int limit) skb->protocol =eth_type_trans (skb, dev);napi_gro_receive (&np->napi, skb); dev->stats.rx_packets++; - dev->stats.rx_bytes += len; next_pkt:if (unlikely (np->get_rx.orig++ == np->last_rx.orig)) np->get_rx.orig = np->first_rx.orig;
@@ -2787,9 +2756,7 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)__vlan_hwaccel_put_tag (skb, vid); }napi_gro_receive (&np->napi, skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; }else {dev_kfree_skb (skb); }
Signature · 1 line
1.7.3.1
PATCH v4 3/4 forcedeth: Improve stats counters
In reply to David DecotignyFrom: Mandeep Baines <[email protected]>
Rx byte count was off; instead use the hardware's count. Tx packet count was counting pre-TSO packets; instead count on-the-wire packets. Report hardware dropped frame count as rx_fifo_errors.
- The count of transmitted packets reported by the forcedeth driver reports pre-TSO (TCP Segmentation Offload) packet counts and not the count of the number of packets sent on the wire. This change fixes the forcedeth driver to report the correct count. Fixed the code by copying the count stored in the NIC H/W to the value reported by the driver.
- Count rx_drop_frame errors as rx_fifo_errors:
We see a lot of rx_drop_frame errors if we disable the rx bottom-halves for too long. Normally, rx_fifo_errors would be counted in this case. The rx_drop_frame error count is private to forcedeth and is not reported by ifconfig or sysfs. The rx_fifo_errors count is currently unused in the forcedeth driver. It is reported by ifconfig as overruns. This change reports rx_drop_frame errors as rx_fifo_errors.
--- drivers/net/ethernet/nvidia/forcedeth.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
drivers/net/ethernet/nvidia/forcedeth.c +4 -0
@@ -1682,6 +1682,7 @@ static void nv_get_hw_stats(struct net_device *dev) np->estats.tx_pause +=readl (base + NvRegTxPause); np->estats.rx_pause +=readl (base + NvRegRxPause); np->estats.rx_drop_frame +=readl (base + NvRegRxDropFrame); + np->estats.rx_errors_total += np->estats.rx_drop_frame; }if (np->driver_data &DEV_HAS_STATISTICS_V3 ) {
@@ -1706,11 +1707,14 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)nv_get_hw_stats (dev);/* copy to net_device stats */ + dev->stats.tx_packets = np->estats.tx_packets; + dev->stats.rx_bytes = np->estats.rx_bytes; dev->stats.tx_bytes = np->estats.tx_bytes; dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors; dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors; dev->stats.rx_crc_errors = np->estats.rx_crc_errors; dev->stats.rx_over_errors = np->estats.rx_over_errors; + dev->stats.rx_fifo_errors = np->estats.rx_drop_frame; dev->stats.rx_errors = np->estats.rx_errors_total; dev->stats.tx_errors = np->estats.tx_errors_total; }
Signature · 1 line
1.7.3.1
PATCH v4 4/4 forcedeth: fix a few sparse warnings (variable shadowing)
In reply to David DecotignyThis fixes the following sparse warnings:drivers/net/ethernet/nvidia/forcedeth.c:2113:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2102:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2155:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2102:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2227:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2215:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2271:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2215:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2986:20: warning: symbol 'addr' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2963:6: originally declared here
--- drivers/net/ethernet/nvidia/forcedeth.c | 34 +++++++++++++++--------------- 1 files changed, 17 insertions(+), 17 deletions(-)
drivers/net/ethernet/nvidia/forcedeth.c +17 -17
@@ -2103,10 +2103,10 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)/* add fragments to entries count */ for (i =0 ; i < fragments; i++) { -u32 size =skb_frag_size (&skb_shinfo (skb)->frags[i]); +u32 frag_size =skb_frag_size (&skb_shinfo (skb)->frags[i]); - entries += (size >>NV_TX2_TSO_MAX_SHIFT ) + - ((size & (NV_TX2_TSO_MAX_SIZE -1 )) ?1 :0 ); + entries += (frag_size >>NV_TX2_TSO_MAX_SHIFT ) + + ((frag_size & (NV_TX2_TSO_MAX_SIZE -1 )) ?1 :0 ); }spin_lock_irqsave (&np->lock, flags);
@@ -2145,13 +2145,13 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) /* setup the fragments */ for (i = 0; i < fragments; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = skb_frag_size(frag); + u32 frag_size = skb_frag_size(frag); offset = 0; do { prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; np->put_tx_ctx->dma = skb_frag_dma_map( &np->pci_dev->dev, frag, offset,
@@ -2163,12 +2163,12 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) put_tx->flaglen =cpu_to_le32 ((bcnt-1 ) | tx_flags); offset += bcnt; - size -= bcnt; + frag_size -= bcnt;if (unlikely (put_tx++ == np->last_tx.orig)) put_tx = np->first_tx.orig;if (unlikely (np->put_tx_ctx++ == np->last_tx_ctx)) np->put_tx_ctx = np->first_tx_ctx; - }while (size); + }while (frag_size); }/* set last fragment flag */
@@ -2217,10 +2217,10 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,/* add fragments to entries count */ for (i =0 ; i < fragments; i++) { -u32 size =skb_frag_size (&skb_shinfo (skb)->frags[i]); +u32 frag_size =skb_frag_size (&skb_shinfo (skb)->frags[i]); - entries += (size >>NV_TX2_TSO_MAX_SHIFT ) + - ((size & (NV_TX2_TSO_MAX_SIZE -1 )) ?1 :0 ); + entries += (frag_size >>NV_TX2_TSO_MAX_SHIFT ) + + ((frag_size & (NV_TX2_TSO_MAX_SIZE -1 )) ?1 :0 ); }spin_lock_irqsave (&np->lock, flags);
@@ -2261,13 +2261,13 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, /* setup the fragments */ for (i = 0; i < fragments; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = skb_frag_size(frag); + u32 frag_size = skb_frag_size(frag); offset = 0; do { prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; np->put_tx_ctx->dma = skb_frag_dma_map( &np->pci_dev->dev, frag, offset,
@@ -2280,12 +2280,12 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, put_tx->flaglen =cpu_to_le32 ((bcnt-1 ) | tx_flags); offset += bcnt; - size -= bcnt; + frag_size -= bcnt;if (unlikely (put_tx++ == np->last_tx.ex)) put_tx = np->first_tx.ex;if (unlikely (np->put_tx_ctx++ == np->last_tx_ctx)) np->put_tx_ctx = np->first_tx_ctx; - }while (size); + }while (frag_size); }/* set last fragment flag */
@@ -2933,11 +2933,11 @@ static void nv_set_multicast(struct net_device *dev)struct netdev_hw_addr *ha;netdev_for_each_mc_addr (ha, dev) { -unsigned char *addr = ha->addr; +unsigned char *hw_addr = ha->addr;u32 a, b; - a =le32_to_cpu (*(__le32 *) addr); - b =le16_to_cpu (*(__le16 *) (&addr[4 ])); + a =le32_to_cpu (*(__le32 *) hw_addr); + b =le16_to_cpu (*(__le16 *) (&hw_addr[4 ])); alwaysOn[0 ] &= a; alwaysOff[0 ] &= ~a; alwaysOn[1 ] &= b;
Signature · 1 line
1.7.3.1