/************************************************************************
* s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
- * Copyright(c) 2002-2007 Neterion Inc.
+ * Copyright(c) 2002-2010 Exar Corp.
*
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
pkt_cnt++;
/* Updating the statistics block */
- nic->dev->stats.tx_bytes += skb->len;
swstats->mem_freed += skb->truesize;
dev_kfree_skb_irq(skb);
* Return value:
* pointer to the updated net_device_stats structure.
*/
-
static struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
struct s2io_nic *sp = netdev_priv(dev);
- struct config_param *config = &sp->config;
struct mac_info *mac_control = &sp->mac_control;
struct stat_block *stats = mac_control->stats_info;
- int i;
+ u64 delta;
/* Configure Stats for immediate updt */
s2io_updt_stats(sp);
- /* Using sp->stats as a staging area, because reset (due to mtu
- change, for example) will clear some hardware counters */
- dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) -
- sp->stats.tx_packets;
- sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms);
-
- dev->stats.tx_errors += le32_to_cpu(stats->tmac_any_err_frms) -
- sp->stats.tx_errors;
- sp->stats.tx_errors = le32_to_cpu(stats->tmac_any_err_frms);
-
- dev->stats.rx_errors += le64_to_cpu(stats->rmac_drop_frms) -
- sp->stats.rx_errors;
- sp->stats.rx_errors = le64_to_cpu(stats->rmac_drop_frms);
-
- dev->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms) -
- sp->stats.multicast;
- sp->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms);
-
- dev->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms) -
- sp->stats.rx_length_errors;
- sp->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms);
+ /* A device reset will cause the on-adapter statistics to be zero'ed.
+ * This can be done while running by changing the MTU. To prevent the
+ * system from having the stats zero'ed, the driver keeps a copy of the
+ * last update to the system (which is also zero'ed on reset). This
+ * enables the driver to accurately know the delta between the last
+ * update and the current update.
+ */
+ delta = ((u64) le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_vld_frms)) - sp->stats.rx_packets;
+ sp->stats.rx_packets += delta;
+ dev->stats.rx_packets += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_frms_oflow) << 32 |
+ le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets;
+ sp->stats.tx_packets += delta;
+ dev->stats.tx_packets += delta;
+
+ delta = ((u64) le32_to_cpu(stats->rmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stats->rmac_data_octets)) - sp->stats.rx_bytes;
+ sp->stats.rx_bytes += delta;
+ dev->stats.rx_bytes += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_data_octets_oflow) << 32 |
+ le32_to_cpu(stats->tmac_data_octets)) - sp->stats.tx_bytes;
+ sp->stats.tx_bytes += delta;
+ dev->stats.tx_bytes += delta;
+
+ delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors;
+ sp->stats.rx_errors += delta;
+ dev->stats.rx_errors += delta;
+
+ delta = ((u64) le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 |
+ le32_to_cpu(stats->tmac_any_err_frms)) - sp->stats.tx_errors;
+ sp->stats.tx_errors += delta;
+ dev->stats.tx_errors += delta;
+
+ delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_dropped;
+ sp->stats.rx_dropped += delta;
+ dev->stats.rx_dropped += delta;
+
+ delta = le64_to_cpu(stats->tmac_drop_frms) - sp->stats.tx_dropped;
+ sp->stats.tx_dropped += delta;
+ dev->stats.tx_dropped += delta;
+
+ /* The adapter MAC interprets pause frames as multicast packets, but
+ * does not pass them up. This erroneously increases the multicast
+ * packet count and needs to be deducted when the multicast frame count
+ * is queried.
+ */
+ delta = (u64) le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_vld_mcst_frms);
+ delta -= le64_to_cpu(stats->rmac_pause_ctrl_frms);
+ delta -= sp->stats.multicast;
+ sp->stats.multicast += delta;
+ dev->stats.multicast += delta;
- /* collect per-ring rx_packets and rx_bytes */
- dev->stats.rx_packets = dev->stats.rx_bytes = 0;
- for (i = 0; i < config->rx_ring_num; i++) {
- struct ring_info *ring = &mac_control->rings[i];
+ delta = ((u64) le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 |
+ le32_to_cpu(stats->rmac_usized_frms)) +
+ le64_to_cpu(stats->rmac_long_frms) - sp->stats.rx_length_errors;
+ sp->stats.rx_length_errors += delta;
+ dev->stats.rx_length_errors += delta;
- dev->stats.rx_packets += ring->rx_packets;
- dev->stats.rx_bytes += ring->rx_bytes;
- }
+ delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors;
+ sp->stats.rx_crc_errors += delta;
+ dev->stats.rx_crc_errors += delta;
return &dev->stats;
}
{
u8 *vpd_data;
u8 data;
- int i = 0, cnt, fail = 0;
+ int i = 0, cnt, len, fail = 0;
int vpd_addr = 0x80;
struct swStat *swstats = &nic->mac_control.stats_info->sw_stat;
if (!fail) {
/* read serial number of adapter */
- for (cnt = 0; cnt < 256; cnt++) {
+ for (cnt = 0; cnt < 252; cnt++) {
if ((vpd_data[cnt] == 'S') &&
- (vpd_data[cnt+1] == 'N') &&
- (vpd_data[cnt+2] < VPD_STRING_LEN)) {
- memset(nic->serial_num, 0, VPD_STRING_LEN);
- memcpy(nic->serial_num, &vpd_data[cnt + 3],
- vpd_data[cnt+2]);
- break;
+ (vpd_data[cnt+1] == 'N')) {
+ len = vpd_data[cnt+2];
+ if (len < min(VPD_STRING_LEN, 256-cnt-2)) {
+ memcpy(nic->serial_num,
+ &vpd_data[cnt + 3],
+ len);
+ memset(nic->serial_num+len,
+ 0,
+ VPD_STRING_LEN-len);
+ break;
+ }
}
}
}
- if ((!fail) && (vpd_data[1] < VPD_STRING_LEN))
- memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
+ if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) {
+ len = vpd_data[1];
+ memcpy(nic->product_name, &vpd_data[3], len);
+ nic->product_name[len] = 0;
+ }
kfree(vpd_data);
swstats->mem_freed += 256;
}
}
}
- /* Updating statistics */
- ring_data->rx_packets++;
rxdp->Host_Control = 0;
if (sp->rxd_mode == RXD_MODE_1) {
int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
- ring_data->rx_bytes += len;
skb_put(skb, len);
-
} else if (sp->rxd_mode == RXD_MODE_3B) {
int get_block = ring_data->rx_curr_get_info.block_index;
int get_off = ring_data->rx_curr_get_info.offset;
unsigned char *buff = skb_push(skb, buf0_len);
struct buffAdd *ba = &ring_data->ba[get_block][get_off];
- ring_data->rx_bytes += buf0_len + buf2_len;
memcpy(buff, ba->ba_0, buf0_len);
skb_put(skb, buf2_len);
}
/* Private member variable initialized to s2io NIC structure */
sp = netdev_priv(dev);
- memset(sp, 0, sizeof(struct s2io_nic));
sp->dev = dev;
sp->pdev = pdev;
sp->high_dma_flag = dma_flag;
goto register_failed;
}
s2io_vpd_read(sp);
- DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n");
+ DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2010 Exar Corp.\n");
DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n", dev->name,
sp->product_name, pdev->revision);
DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,