1219820Sjeff/* 2272027Shselasky * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff */ 33219820Sjeff 34272027Shselasky#include <sys/types.h> 35219820Sjeff#include <linux/if_vlan.h> 36219820Sjeff 37306486Shselasky#include <dev/mlx4/device.h> 38306486Shselasky#include <dev/mlx4/cmd.h> 39219820Sjeff 40272027Shselasky#include "en_port.h" 41306486Shselasky#include "en.h" 42219820Sjeff 43272027Shselasky 44272027Shselaskyint mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) 45219820Sjeff{ 46219820Sjeff struct mlx4_cmd_mailbox *mailbox; 47219820Sjeff struct mlx4_set_vlan_fltr_mbox *filter; 48272027Shselasky int i; 49272027Shselasky int j; 50272027Shselasky int index = 0; 51272027Shselasky u32 entry; 52219820Sjeff int err = 0; 53219820Sjeff 54219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 55219820Sjeff if (IS_ERR(mailbox)) 56219820Sjeff return PTR_ERR(mailbox); 57219820Sjeff 58219820Sjeff filter = mailbox->buf; 59272027Shselasky for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) { 60272027Shselasky entry = 0; 61296987Shselasky for (j = 0; j < 32; j++) { 62272027Shselasky if (test_bit(index, priv->active_vlans)) 63272027Shselasky entry |= 1 << j; 64296987Shselasky index++; 65296987Shselasky } 66272027Shselasky filter->entry[i] = cpu_to_be32(entry); 67272027Shselasky } 68272027Shselasky err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR, 69272027Shselasky MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); 70219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 71219820Sjeff return err; 72219820Sjeff} 73219820Sjeff 74219820Sjeffint mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) 75219820Sjeff{ 76219820Sjeff struct mlx4_en_query_port_context *qport_context; 77219820Sjeff struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); 78219820Sjeff struct mlx4_en_port_state *state = &priv->port_state; 79219820Sjeff struct mlx4_cmd_mailbox *mailbox; 80219820Sjeff int err; 81219820Sjeff 82219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 83219820Sjeff if (IS_ERR(mailbox)) 84219820Sjeff return PTR_ERR(mailbox); 85219820Sjeff err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, 86272027Shselasky MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, 87272027Shselasky MLX4_CMD_WRAPPED); 88219820Sjeff if (err) 89219820Sjeff goto out; 90219820Sjeff qport_context = mailbox->buf; 91219820Sjeff 92219820Sjeff /* This command is always accessed from Ethtool context 93219820Sjeff * already synchronized, no need in locking */ 94219820Sjeff state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); 95234099Sjhb switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) { 96329159Shselasky case MLX4_EN_100M_SPEED: 97329159Shselasky state->link_speed = 100; 98329159Shselasky break; 99234099Sjhb case MLX4_EN_1G_SPEED: 100219820Sjeff state->link_speed = 1000; 101234099Sjhb break; 102234099Sjhb case MLX4_EN_10G_SPEED_XAUI: 103234099Sjhb case MLX4_EN_10G_SPEED_XFI: 104219820Sjeff state->link_speed = 10000; 105234099Sjhb break; 106272027Shselasky case MLX4_EN_20G_SPEED: 107272027Shselasky state->link_speed = 20000; 108272027Shselasky break; 109234099Sjhb case MLX4_EN_40G_SPEED: 110234099Sjhb state->link_speed = 40000; 111234099Sjhb break; 112272027Shselasky case MLX4_EN_56G_SPEED: 113272027Shselasky state->link_speed = 56000; 114272027Shselasky break; 115234099Sjhb default: 116234099Sjhb state->link_speed = -1; 117234099Sjhb break; 118234099Sjhb } 119219820Sjeff 120329159Shselasky state->transceiver = qport_context->transceiver; 121329159Shselasky 122329159Shselasky state->flags = 0; /* Reset and recalculate the port flags */ 123329159Shselasky state->flags |= (qport_context->link_up & MLX4_EN_ANC_MASK) ? 124329159Shselasky MLX4_EN_PORT_ANC : 0; 125329159Shselasky state->flags |= (qport_context->autoneg & MLX4_EN_AUTONEG_MASK) ? 126329159Shselasky MLX4_EN_PORT_ANE : 0; 127329159Shselasky 128219820Sjeffout: 129219820Sjeff mlx4_free_cmd_mailbox(mdev->dev, mailbox); 130219820Sjeff return err; 131219820Sjeff} 132219820Sjeff 133329159Shselasky/* Each counter set is located in struct mlx4_en_stat_out_mbox 134329159Shselasky * with a const offset between its prio components. 135329159Shselasky * This function runs over a counter set and sum all of it's prio components. 136329159Shselasky */ 137329159Shselaskystatic u64 en_stats_adder(__be64 *start, __be64 *next, int num) 138219820Sjeff{ 139329159Shselasky __be64 *curr = start; 140329159Shselasky u64 ret = 0; 141272027Shselasky int i; 142329159Shselasky int offset = next - start; 143219820Sjeff 144329159Shselasky for (i = 0; i < num; i++) { 145329159Shselasky ret += be64_to_cpu(*curr); 146329159Shselasky curr += offset; 147272027Shselasky } 148219820Sjeff 149329159Shselasky return ret; 150329159Shselasky} 151219820Sjeff 152329159Shselaskystatic void mlx4_en_fold_software_stats(struct net_device *dev) 153329159Shselasky{ 154329159Shselasky struct mlx4_en_priv *priv = netdev_priv(dev); 155329159Shselasky struct mlx4_en_dev *mdev = priv->mdev; 156329159Shselasky u64 packets, bytes; 157329159Shselasky int i; 158219820Sjeff 159329159Shselasky if (!priv->port_up || mlx4_is_master(mdev->dev)) 160329159Shselasky return; 161219820Sjeff 162329159Shselasky packets = 0; 163329159Shselasky bytes = 0; 164329159Shselasky for (i = 0; i < priv->rx_ring_num; i++) { 165329159Shselasky const struct mlx4_en_rx_ring *ring = priv->rx_ring[i]; 166329159Shselasky 167329159Shselasky packets += READ_ONCE(ring->packets); 168329159Shselasky bytes += READ_ONCE(ring->bytes); 169272027Shselasky } 170329159Shselasky priv->pkstats.rx_packets = packets; 171329159Shselasky priv->pkstats.rx_bytes = bytes; 172219820Sjeff 173329159Shselasky packets = 0; 174329159Shselasky bytes = 0; 175329159Shselasky for (i = 0; i < priv->tx_ring_num; i++) { 176329159Shselasky const struct mlx4_en_tx_ring *ring = priv->tx_ring[i]; 177329159Shselasky 178329159Shselasky packets += READ_ONCE(ring->packets); 179329159Shselasky bytes += READ_ONCE(ring->bytes); 180329159Shselasky } 181329159Shselasky priv->pkstats.tx_packets = packets; 182329159Shselasky priv->pkstats.tx_bytes = bytes; 183329159Shselasky} 184329159Shselasky 185329159Shselaskyint mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) 186329159Shselasky{ 187329159Shselasky struct mlx4_counter tmp_vport_stats; 188329159Shselasky struct mlx4_en_stat_out_mbox *mlx4_en_stats; 189329159Shselasky struct mlx4_en_stat_out_flow_control_mbox *flowstats; 190329159Shselasky struct net_device *dev = mdev->pndev[port]; 191329159Shselasky struct mlx4_en_priv *priv = netdev_priv(dev); 192329159Shselasky struct mlx4_en_vport_stats *vport_stats = &priv->vport_stats; 193329159Shselasky struct mlx4_cmd_mailbox *mailbox; 194329159Shselasky u64 in_mod = reset << 8 | port; 195329159Shselasky int err; 196329159Shselasky int i, counter_index; 197329159Shselasky 198329159Shselasky mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 199329159Shselasky if (IS_ERR(mailbox)) 200329159Shselasky return PTR_ERR(mailbox); 201219820Sjeff err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0, 202272027Shselasky MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, 203272027Shselasky MLX4_CMD_NATIVE); 204219820Sjeff if (err) 205219820Sjeff goto out; 206219820Sjeff 207219820Sjeff mlx4_en_stats = mailbox->buf; 208219820Sjeff 209219820Sjeff spin_lock(&priv->stats_lock); 210219820Sjeff 211272027Shselasky priv->port_stats.rx_chksum_good = 0; 212272027Shselasky priv->port_stats.rx_chksum_none = 0; 213219820Sjeff for (i = 0; i < priv->rx_ring_num; i++) { 214272027Shselasky priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok; 215272027Shselasky priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none; 216219820Sjeff } 217272027Shselasky priv->port_stats.tx_chksum_offload = 0; 218272027Shselasky priv->port_stats.queue_stopped = 0; 219272027Shselasky priv->port_stats.wake_queue = 0; 220329159Shselasky priv->port_stats.oversized_packets = 0; 221329159Shselasky priv->port_stats.tso_packets = 0; 222329159Shselasky priv->port_stats.defrag_attempts = 0; 223329159Shselasky 224272027Shselasky for (i = 0; i < priv->tx_ring_num; i++) { 225329159Shselasky const struct mlx4_en_tx_ring *ring; 226329159Shselasky ring = priv->tx_ring[i]; 227329159Shselasky 228329159Shselasky priv->port_stats.tx_chksum_offload += ring->tx_csum; 229329159Shselasky priv->port_stats.queue_stopped += ring->queue_stopped; 230329159Shselasky priv->port_stats.wake_queue += ring->wake_queue; 231329159Shselasky priv->port_stats.oversized_packets += ring->oversized_packets; 232329159Shselasky priv->port_stats.tso_packets += ring->tso_packets; 233329159Shselasky priv->port_stats.defrag_attempts += ring->defrag_attempts; 234219820Sjeff } 235329159Shselasky 236329159Shselasky priv->pkstats.rx_errors = 237329159Shselasky be64_to_cpu(mlx4_en_stats->PCS) + 238329159Shselasky be32_to_cpu(mlx4_en_stats->RJBBR) + 239329159Shselasky be32_to_cpu(mlx4_en_stats->RCRC) + 240329159Shselasky be32_to_cpu(mlx4_en_stats->RRUNT) + 241329159Shselasky be64_to_cpu(mlx4_en_stats->RInRangeLengthErr) + 242329159Shselasky be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr) + 243329159Shselasky be32_to_cpu(mlx4_en_stats->RSHORT) + 244329159Shselasky en_stats_adder(&mlx4_en_stats->RGIANT_prio_0, 245329159Shselasky &mlx4_en_stats->RGIANT_prio_1, 246329159Shselasky NUM_PRIORITIES); 247329159Shselasky priv->pkstats.tx_errors = 248329159Shselasky en_stats_adder(&mlx4_en_stats->TGIANT_prio_0, 249329159Shselasky &mlx4_en_stats->TGIANT_prio_1, 250329159Shselasky NUM_PRIORITIES); 251329159Shselasky priv->pkstats.rx_multicast_packets = 252329159Shselasky en_stats_adder(&mlx4_en_stats->MCAST_prio_0, 253329159Shselasky &mlx4_en_stats->MCAST_prio_1, 254329159Shselasky NUM_PRIORITIES); 255329159Shselasky priv->pkstats.rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP); 256272027Shselasky priv->pkstats.rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength); 257272027Shselasky priv->pkstats.rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw); 258272027Shselasky priv->pkstats.rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC); 259329159Shselasky priv->pkstats.tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP); 260329159Shselasky 261329159Shselasky /* RX stats */ 262329159Shselasky priv->pkstats.rx_packets = en_stats_adder(&mlx4_en_stats->RTOT_prio_0, 263329159Shselasky &mlx4_en_stats->RTOT_prio_1, 264329159Shselasky NUM_PRIORITIES); 265329159Shselasky priv->pkstats.rx_bytes = en_stats_adder(&mlx4_en_stats->ROCT_prio_0, 266329159Shselasky &mlx4_en_stats->ROCT_prio_1, 267329159Shselasky NUM_PRIORITIES); 268329159Shselasky priv->pkstats.rx_broadcast_packets = 269329159Shselasky en_stats_adder(&mlx4_en_stats->RBCAST_prio_0, 270329159Shselasky &mlx4_en_stats->RBCAST_prio_1, 271329159Shselasky NUM_PRIORITIES); 272272027Shselasky priv->pkstats.rx_jabbers = be32_to_cpu(mlx4_en_stats->RJBBR); 273329159Shselasky priv->pkstats.rx_in_range_length_error = 274329159Shselasky be64_to_cpu(mlx4_en_stats->RInRangeLengthErr); 275329159Shselasky priv->pkstats.rx_out_range_length_error = 276329159Shselasky be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr); 277219820Sjeff 278329159Shselasky /* Tx stats */ 279329159Shselasky priv->pkstats.tx_packets = en_stats_adder(&mlx4_en_stats->TTOT_prio_0, 280329159Shselasky &mlx4_en_stats->TTOT_prio_1, 281329159Shselasky NUM_PRIORITIES); 282329159Shselasky priv->pkstats.tx_bytes = en_stats_adder(&mlx4_en_stats->TOCT_prio_0, 283329159Shselasky &mlx4_en_stats->TOCT_prio_1, 284329159Shselasky NUM_PRIORITIES); 285329159Shselasky priv->pkstats.tx_multicast_packets = 286329159Shselasky en_stats_adder(&mlx4_en_stats->TMCAST_prio_0, 287329159Shselasky &mlx4_en_stats->TMCAST_prio_1, 288329159Shselasky NUM_PRIORITIES); 289329159Shselasky priv->pkstats.tx_broadcast_packets = 290329159Shselasky en_stats_adder(&mlx4_en_stats->TBCAST_prio_0, 291329159Shselasky &mlx4_en_stats->TBCAST_prio_1, 292329159Shselasky NUM_PRIORITIES); 293219820Sjeff 294272027Shselasky priv->pkstats.rx_prio[0][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0); 295272027Shselasky priv->pkstats.rx_prio[0][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_0); 296272027Shselasky priv->pkstats.rx_prio[1][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1); 297272027Shselasky priv->pkstats.rx_prio[1][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_1); 298272027Shselasky priv->pkstats.rx_prio[2][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2); 299272027Shselasky priv->pkstats.rx_prio[2][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_2); 300272027Shselasky priv->pkstats.rx_prio[3][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3); 301272027Shselasky priv->pkstats.rx_prio[3][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_3); 302272027Shselasky priv->pkstats.rx_prio[4][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4); 303272027Shselasky priv->pkstats.rx_prio[4][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_4); 304272027Shselasky priv->pkstats.rx_prio[5][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5); 305272027Shselasky priv->pkstats.rx_prio[5][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_5); 306272027Shselasky priv->pkstats.rx_prio[6][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6); 307272027Shselasky priv->pkstats.rx_prio[6][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_6); 308272027Shselasky priv->pkstats.rx_prio[7][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7); 309272027Shselasky priv->pkstats.rx_prio[7][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_7); 310272027Shselasky priv->pkstats.rx_prio[8][0] = be64_to_cpu(mlx4_en_stats->RTOT_novlan); 311272027Shselasky priv->pkstats.rx_prio[8][1] = be64_to_cpu(mlx4_en_stats->ROCT_novlan); 312272027Shselasky priv->pkstats.tx_prio[0][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0); 313272027Shselasky priv->pkstats.tx_prio[0][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_0); 314272027Shselasky priv->pkstats.tx_prio[1][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1); 315272027Shselasky priv->pkstats.tx_prio[1][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_1); 316272027Shselasky priv->pkstats.tx_prio[2][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2); 317272027Shselasky priv->pkstats.tx_prio[2][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_2); 318272027Shselasky priv->pkstats.tx_prio[3][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3); 319272027Shselasky priv->pkstats.tx_prio[3][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_3); 320272027Shselasky priv->pkstats.tx_prio[4][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4); 321272027Shselasky priv->pkstats.tx_prio[4][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_4); 322272027Shselasky priv->pkstats.tx_prio[5][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5); 323272027Shselasky priv->pkstats.tx_prio[5][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_5); 324272027Shselasky priv->pkstats.tx_prio[6][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6); 325272027Shselasky priv->pkstats.tx_prio[6][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_6); 326272027Shselasky priv->pkstats.tx_prio[7][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7); 327272027Shselasky priv->pkstats.tx_prio[7][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_7); 328272027Shselasky priv->pkstats.tx_prio[8][0] = be64_to_cpu(mlx4_en_stats->TTOT_novlan); 329272027Shselasky priv->pkstats.tx_prio[8][1] = be64_to_cpu(mlx4_en_stats->TOCT_novlan); 330272027Shselasky 331329159Shselasky mlx4_en_fold_software_stats(dev); 332272027Shselasky 333329159Shselasky spin_unlock(&priv->stats_lock); 334329159Shselasky 335329159Shselasky memset(&tmp_vport_stats, 0, sizeof(tmp_vport_stats)); 336329159Shselasky counter_index = mlx4_get_default_counter_index(mdev->dev, port); 337329159Shselasky err = mlx4_get_counter_stats(mdev->dev, counter_index, 338329159Shselasky &tmp_vport_stats, reset); 339329159Shselasky 340329159Shselasky spin_lock(&priv->stats_lock); 341329159Shselasky if (!err) { 342329159Shselasky /* ethtool stats format */ 343329159Shselasky vport_stats->rx_bytes = be64_to_cpu(tmp_vport_stats.rx_bytes); 344329159Shselasky vport_stats->rx_frames = be64_to_cpu(tmp_vport_stats.rx_frames); 345329159Shselasky vport_stats->tx_bytes = be64_to_cpu(tmp_vport_stats.tx_bytes); 346329159Shselasky vport_stats->tx_frames = be64_to_cpu(tmp_vport_stats.tx_frames); 347329159Shselasky } 348329159Shselasky 349329159Shselasky#if __FreeBSD_version >= 1100000 350329159Shselasky if (reset == 0) { 351329159Shselasky if_inc_counter(dev, IFCOUNTER_IPACKETS, 352329159Shselasky priv->pkstats.rx_packets - priv->pkstats_last.rx_packets); 353329159Shselasky if_inc_counter(dev, IFCOUNTER_OPACKETS, 354329159Shselasky priv->pkstats.tx_packets - priv->pkstats_last.tx_packets); 355329159Shselasky if_inc_counter(dev, IFCOUNTER_IBYTES, 356329159Shselasky priv->pkstats.rx_bytes - priv->pkstats_last.rx_bytes); 357329159Shselasky if_inc_counter(dev, IFCOUNTER_OBYTES, 358329159Shselasky priv->pkstats.tx_bytes - priv->pkstats_last.tx_bytes); 359329159Shselasky if_inc_counter(dev, IFCOUNTER_IERRORS, 360329159Shselasky priv->pkstats.rx_errors - priv->pkstats_last.rx_errors); 361329159Shselasky if_inc_counter(dev, IFCOUNTER_IQDROPS, 362329159Shselasky priv->pkstats.rx_dropped - priv->pkstats_last.rx_dropped); 363329159Shselasky if_inc_counter(dev, IFCOUNTER_IMCASTS, 364329159Shselasky priv->pkstats.rx_multicast_packets - priv->pkstats_last.rx_multicast_packets); 365329159Shselasky if_inc_counter(dev, IFCOUNTER_OMCASTS, 366329159Shselasky priv->pkstats.tx_multicast_packets - priv->pkstats_last.tx_multicast_packets); 367329159Shselasky } 368329159Shselasky priv->pkstats_last = priv->pkstats; 369329159Shselasky#else 370329159Shselasky dev->if_ipackets = priv->pkstats.rx_packets; 371329159Shselasky dev->if_opackets = priv->pkstats.tx_packets; 372329159Shselasky dev->if_ibytes = priv->pkstats.rx_bytes; 373329159Shselasky dev->if_obytes = priv->pkstats.tx_bytes; 374329159Shselasky dev->if_ierrors = priv->pkstats.rx_errors; 375329159Shselasky dev->if_iqdrops = priv->pkstats.rx_dropped; 376329159Shselasky dev->if_imcasts = priv->pkstats.rx_multicast_packets; 377329159Shselasky dev->if_omcasts = priv->pkstats.tx_multicast_packets; 378329159Shselasky dev->if_collisions = 0; 379329159Shselasky#endif 380329159Shselasky 381329159Shselasky spin_unlock(&priv->stats_lock); 382329159Shselasky 383329159Shselasky /* 0xffs indicates invalid value */ 384329159Shselasky memset(mailbox->buf, 0xff, sizeof(*flowstats) * MLX4_NUM_PRIORITIES); 385329159Shselasky 386329159Shselasky if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) { 387329159Shselasky memset(mailbox->buf, 0, 388329159Shselasky sizeof(*flowstats) * MLX4_NUM_PRIORITIES); 389329159Shselasky err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, 390329159Shselasky in_mod | MLX4_DUMP_ETH_STATS_FLOW_CONTROL, 391329159Shselasky 0, MLX4_CMD_DUMP_ETH_STATS, 392329159Shselasky MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); 393329159Shselasky if (err) 394329159Shselasky goto out; 395329159Shselasky } 396329159Shselasky 397329159Shselasky flowstats = mailbox->buf; 398329159Shselasky 399329159Shselasky spin_lock(&priv->stats_lock); 400329159Shselasky 401272027Shselasky for (i = 0; i < MLX4_NUM_PRIORITIES; i++) { 402329159Shselasky priv->rx_priority_flowstats[i].rx_pause = 403272027Shselasky be64_to_cpu(flowstats[i].rx_pause); 404329159Shselasky priv->rx_priority_flowstats[i].rx_pause_duration = 405272027Shselasky be64_to_cpu(flowstats[i].rx_pause_duration); 406329159Shselasky priv->rx_priority_flowstats[i].rx_pause_transition = 407272027Shselasky be64_to_cpu(flowstats[i].rx_pause_transition); 408329159Shselasky priv->tx_priority_flowstats[i].tx_pause = 409272027Shselasky be64_to_cpu(flowstats[i].tx_pause); 410329159Shselasky priv->tx_priority_flowstats[i].tx_pause_duration = 411272027Shselasky be64_to_cpu(flowstats[i].tx_pause_duration); 412329159Shselasky priv->tx_priority_flowstats[i].tx_pause_transition = 413272027Shselasky be64_to_cpu(flowstats[i].tx_pause_transition); 414272027Shselasky } 415272027Shselasky 416329159Shselasky /* if pfc is not in use, all priorities counters have the same value */ 417329159Shselasky priv->rx_flowstats.rx_pause = 418329159Shselasky be64_to_cpu(flowstats[0].rx_pause); 419329159Shselasky priv->rx_flowstats.rx_pause_duration = 420329159Shselasky be64_to_cpu(flowstats[0].rx_pause_duration); 421329159Shselasky priv->rx_flowstats.rx_pause_transition = 422329159Shselasky be64_to_cpu(flowstats[0].rx_pause_transition); 423329159Shselasky priv->tx_flowstats.tx_pause = 424329159Shselasky be64_to_cpu(flowstats[0].tx_pause); 425329159Shselasky priv->tx_flowstats.tx_pause_duration = 426329159Shselasky be64_to_cpu(flowstats[0].tx_pause_duration); 427329159Shselasky priv->tx_flowstats.tx_pause_transition = 428329159Shselasky be64_to_cpu(flowstats[0].tx_pause_transition); 429329159Shselasky 430219820Sjeff spin_unlock(&priv->stats_lock); 431329159Shselasky 432329159Shselaskyout: 433329159Shselasky mlx4_free_cmd_mailbox(mdev->dev, mailbox); 434329159Shselasky return err; 435329159Shselasky} 436329159Shselasky 437329159Shselaskyint mlx4_en_get_vport_stats(struct mlx4_en_dev *mdev, u8 port) 438329159Shselasky{ 439329159Shselasky struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); 440329159Shselasky struct mlx4_counter tmp_vport_stats; 441329159Shselasky struct mlx4_en_vf_stats *vf_stats = &priv->vf_stats; 442329159Shselasky int err, i, counter_index; 443329159Shselasky 444272027Shselasky spin_lock(&priv->stats_lock); 445329159Shselasky 446329159Shselasky priv->pkstats.rx_packets = 0; 447329159Shselasky priv->pkstats.rx_bytes = 0; 448329159Shselasky priv->port_stats.rx_chksum_good = 0; 449329159Shselasky priv->port_stats.rx_chksum_none = 0; 450329159Shselasky for (i = 0; i < priv->rx_ring_num; i++) { 451329159Shselasky priv->pkstats.rx_packets += priv->rx_ring[i]->packets; 452329159Shselasky priv->pkstats.rx_bytes += priv->rx_ring[i]->bytes; 453329159Shselasky priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok; 454329159Shselasky priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none; 455272027Shselasky } 456329159Shselasky priv->pkstats.tx_packets = 0; 457329159Shselasky priv->pkstats.tx_bytes = 0; 458329159Shselasky priv->port_stats.tx_chksum_offload = 0; 459329159Shselasky priv->port_stats.queue_stopped = 0; 460329159Shselasky priv->port_stats.wake_queue = 0; 461219820Sjeff 462329159Shselasky for (i = 0; i < priv->tx_ring_num; i++) { 463329159Shselasky const struct mlx4_en_tx_ring *ring = priv->tx_ring[i]; 464329159Shselasky 465329159Shselasky priv->pkstats.tx_packets += ring->packets; 466329159Shselasky priv->pkstats.tx_bytes += ring->bytes; 467329159Shselasky priv->port_stats.tx_chksum_offload += ring->tx_csum; 468329159Shselasky priv->port_stats.queue_stopped += ring->queue_stopped; 469329159Shselasky priv->port_stats.wake_queue += ring->wake_queue; 470329159Shselasky priv->port_stats.oversized_packets += priv->tx_ring[i]->oversized_packets; 471272027Shselasky } 472272027Shselasky 473272027Shselasky spin_unlock(&priv->stats_lock); 474272027Shselasky 475329159Shselasky memset(&tmp_vport_stats, 0, sizeof(tmp_vport_stats)); 476272027Shselasky 477329159Shselasky counter_index = mlx4_get_default_counter_index(mdev->dev, port); 478329159Shselasky err = mlx4_get_counter_stats(mdev->dev, counter_index, 479329159Shselasky &tmp_vport_stats, 0); 480272027Shselasky 481329159Shselasky if (!err) { 482329159Shselasky spin_lock(&priv->stats_lock); 483329159Shselasky 484329159Shselasky vf_stats->rx_bytes = be64_to_cpu(tmp_vport_stats.rx_bytes); 485329159Shselasky vf_stats->rx_frames = be64_to_cpu(tmp_vport_stats.rx_frames); 486329159Shselasky vf_stats->tx_bytes = be64_to_cpu(tmp_vport_stats.tx_bytes); 487329159Shselasky vf_stats->tx_frames = be64_to_cpu(tmp_vport_stats.tx_frames); 488329159Shselasky 489329159Shselasky priv->pkstats.rx_packets = vf_stats->rx_frames; 490329159Shselasky priv->pkstats.rx_bytes = vf_stats->rx_bytes; 491329159Shselasky priv->pkstats.tx_packets = vf_stats->tx_frames; 492329159Shselasky priv->pkstats.tx_bytes = vf_stats->tx_bytes; 493329159Shselasky 494329159Shselasky /* PF&VFs are not expected to report errors in ifconfig. 495329159Shselasky * rx_errors will be reprted in PF's ethtool statistics, 496329159Shselasky * see: mlx4_en_DUMP_ETH_STATS 497329159Shselasky */ 498329159Shselasky priv->pkstats.rx_errors = 0; 499329159Shselasky priv->pkstats.rx_dropped = 0; 500329159Shselasky priv->pkstats.tx_dropped = 0; 501329159Shselasky priv->pkstats.rx_multicast_packets = 0; 502329159Shselasky 503329159Shselasky spin_unlock(&priv->stats_lock); 504329159Shselasky } 505329159Shselasky 506219820Sjeff return err; 507219820Sjeff} 508