Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157148220
D4283.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
83 KB
Referenced Files
None
Subscribers
None
D4283.diff
View Options
Index: head/sys/ofed/drivers/net/mlx4/en_ethtool.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_ethtool.c
+++ head/sys/ofed/drivers/net/mlx4/en_ethtool.c
@@ -1,1616 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/mlx4/driver.h>
-#include <linux/in.h>
-#include <net/ip.h>
-#include <linux/bitmap.h>
-
-#include "mlx4_en.h"
-#include "en_port.h"
-
-#define EN_ETHTOOL_QP_ATTACH (1ull << 63)
-
-union mlx4_ethtool_flow_union {
- struct ethtool_tcpip4_spec tcp_ip4_spec;
- struct ethtool_tcpip4_spec udp_ip4_spec;
- struct ethtool_tcpip4_spec sctp_ip4_spec;
- struct ethtool_ah_espip4_spec ah_ip4_spec;
- struct ethtool_ah_espip4_spec esp_ip4_spec;
- struct ethtool_usrip4_spec usr_ip4_spec;
- struct ethhdr ether_spec;
- __u8 hdata[52];
-};
-
-struct mlx4_ethtool_flow_ext {
- __u8 padding[2];
- unsigned char h_dest[ETH_ALEN];
- __be16 vlan_etype;
- __be16 vlan_tci;
- __be32 data[2];
-};
-
-struct mlx4_ethtool_rx_flow_spec {
- __u32 flow_type;
- union mlx4_ethtool_flow_union h_u;
- struct mlx4_ethtool_flow_ext h_ext;
- union mlx4_ethtool_flow_union m_u;
- struct mlx4_ethtool_flow_ext m_ext;
- __u64 ring_cookie;
- __u32 location;
-};
-
-struct mlx4_ethtool_rxnfc {
- __u32 cmd;
- __u32 flow_type;
- __u64 data;
- struct mlx4_ethtool_rx_flow_spec fs;
- __u32 rule_cnt;
- __u32 rule_locs[0];
-};
-
-#ifndef FLOW_MAC_EXT
-#define FLOW_MAC_EXT 0x40000000
-#endif
-
-static void
-mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
-
- strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
- strlcpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")",
- sizeof(drvinfo->version));
- snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
- "%d.%d.%d",
- (u16) (mdev->dev->caps.fw_ver >> 32),
- (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
- (u16) (mdev->dev->caps.fw_ver & 0xffff));
- strlcpy(drvinfo->bus_info, pci_name(mdev->dev->pdev),
- sizeof(drvinfo->bus_info));
- drvinfo->n_stats = 0;
- drvinfo->regdump_len = 0;
- drvinfo->eedump_len = 0;
-}
-
-static const char main_strings[][ETH_GSTRING_LEN] = {
- /* packet statistics */
- "rx_packets",
- "rx_bytes",
- "rx_multicast_packets",
- "rx_broadcast_packets",
- "rx_errors",
- "rx_dropped",
- "rx_length_errors",
- "rx_over_errors",
- "rx_crc_errors",
- "rx_jabbers",
- "rx_in_range_length_error",
- "rx_out_range_length_error",
- "rx_lt_64_bytes_packets",
- "rx_127_bytes_packets",
- "rx_255_bytes_packets",
- "rx_511_bytes_packets",
- "rx_1023_bytes_packets",
- "rx_1518_bytes_packets",
- "rx_1522_bytes_packets",
- "rx_1548_bytes_packets",
- "rx_gt_1548_bytes_packets",
- "tx_packets",
- "tx_bytes",
- "tx_multicast_packets",
- "tx_broadcast_packets",
- "tx_errors",
- "tx_dropped",
- "tx_lt_64_bytes_packets",
- "tx_127_bytes_packets",
- "tx_255_bytes_packets",
- "tx_511_bytes_packets",
- "tx_1023_bytes_packets",
- "tx_1518_bytes_packets",
- "tx_1522_bytes_packets",
- "tx_1548_bytes_packets",
- "tx_gt_1548_bytes_packets",
- "rx_prio_0_packets", "rx_prio_0_bytes",
- "rx_prio_1_packets", "rx_prio_1_bytes",
- "rx_prio_2_packets", "rx_prio_2_bytes",
- "rx_prio_3_packets", "rx_prio_3_bytes",
- "rx_prio_4_packets", "rx_prio_4_bytes",
- "rx_prio_5_packets", "rx_prio_5_bytes",
- "rx_prio_6_packets", "rx_prio_6_bytes",
- "rx_prio_7_packets", "rx_prio_7_bytes",
- "rx_novlan_packets", "rx_novlan_bytes",
- "tx_prio_0_packets", "tx_prio_0_bytes",
- "tx_prio_1_packets", "tx_prio_1_bytes",
- "tx_prio_2_packets", "tx_prio_2_bytes",
- "tx_prio_3_packets", "tx_prio_3_bytes",
- "tx_prio_4_packets", "tx_prio_4_bytes",
- "tx_prio_5_packets", "tx_prio_5_bytes",
- "tx_prio_6_packets", "tx_prio_6_bytes",
- "tx_prio_7_packets", "tx_prio_7_bytes",
- "tx_novlan_packets", "tx_novlan_bytes",
-
- /* flow control statistics */
- "rx_pause_prio_0", "rx_pause_duration_prio_0",
- "rx_pause_transition_prio_0", "tx_pause_prio_0",
- "tx_pause_duration_prio_0", "tx_pause_transition_prio_0",
- "rx_pause_prio_1", "rx_pause_duration_prio_1",
- "rx_pause_transition_prio_1", "tx_pause_prio_1",
- "tx_pause_duration_prio_1", "tx_pause_transition_prio_1",
- "rx_pause_prio_2", "rx_pause_duration_prio_2",
- "rx_pause_transition_prio_2", "tx_pause_prio_2",
- "tx_pause_duration_prio_2", "tx_pause_transition_prio_2",
- "rx_pause_prio_3", "rx_pause_duration_prio_3",
- "rx_pause_transition_prio_3", "tx_pause_prio_3",
- "tx_pause_duration_prio_3", "tx_pause_transition_prio_3",
- "rx_pause_prio_4", "rx_pause_duration_prio_4",
- "rx_pause_transition_prio_4", "tx_pause_prio_4",
- "tx_pause_duration_prio_4", "tx_pause_transition_prio_4",
- "rx_pause_prio_5", "rx_pause_duration_prio_5",
- "rx_pause_transition_prio_5", "tx_pause_prio_5",
- "tx_pause_duration_prio_5", "tx_pause_transition_prio_5",
- "rx_pause_prio_6", "rx_pause_duration_prio_6",
- "rx_pause_transition_prio_6", "tx_pause_prio_6",
- "tx_pause_duration_prio_6", "tx_pause_transition_prio_6",
- "rx_pause_prio_7", "rx_pause_duration_prio_7",
- "rx_pause_transition_prio_7", "tx_pause_prio_7",
- "tx_pause_duration_prio_7", "tx_pause_transition_prio_7",
-
- /* VF statistics */
- "rx_packets",
- "rx_bytes",
- "rx_multicast_packets",
- "rx_broadcast_packets",
- "rx_errors",
- "rx_dropped",
- "tx_packets",
- "tx_bytes",
- "tx_multicast_packets",
- "tx_broadcast_packets",
- "tx_errors",
-
- /* VPort statistics */
- "vport_rx_unicast_packets",
- "vport_rx_unicast_bytes",
- "vport_rx_multicast_packets",
- "vport_rx_multicast_bytes",
- "vport_rx_broadcast_packets",
- "vport_rx_broadcast_bytes",
- "vport_rx_dropped",
- "vport_rx_errors",
- "vport_tx_unicast_packets",
- "vport_tx_unicast_bytes",
- "vport_tx_multicast_packets",
- "vport_tx_multicast_bytes",
- "vport_tx_broadcast_packets",
- "vport_tx_broadcast_bytes",
- "vport_tx_errors",
-
- /* port statistics */
- "tx_tso_packets",
- "tx_queue_stopped", "tx_wake_queue", "tx_timeout", "rx_alloc_failed",
- "rx_csum_good", "rx_csum_none", "tx_chksum_offload",
-};
-
-static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
- "Interrupt Test",
- "Link Test",
- "Speed Test",
- "Register Test",
- "Loopback Test",
-};
-
-static u32 mlx4_en_get_msglevel(struct net_device *dev)
-{
- return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
-}
-
-static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
-{
- ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;
-}
-
-static void mlx4_en_get_wol(struct net_device *netdev,
- struct ethtool_wolinfo *wol)
-{
- struct mlx4_en_priv *priv = netdev_priv(netdev);
- int err = 0;
- u64 config = 0;
- u64 mask;
-
- if ((priv->port < 1) || (priv->port > 2)) {
- en_err(priv, "Failed to get WoL information\n");
- return;
- }
-
- mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :
- MLX4_DEV_CAP_FLAG_WOL_PORT2;
-
- if (!(priv->mdev->dev->caps.flags & mask)) {
- wol->supported = 0;
- wol->wolopts = 0;
- return;
- }
-
- err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
- if (err) {
- en_err(priv, "Failed to get WoL information\n");
- return;
- }
-
- if (config & MLX4_EN_WOL_MAGIC)
- wol->supported = WAKE_MAGIC;
- else
- wol->supported = 0;
-
- if (config & MLX4_EN_WOL_ENABLED)
- wol->wolopts = WAKE_MAGIC;
- else
- wol->wolopts = 0;
-}
-
-static int mlx4_en_set_wol(struct net_device *netdev,
- struct ethtool_wolinfo *wol)
-{
- struct mlx4_en_priv *priv = netdev_priv(netdev);
- u64 config = 0;
- int err = 0;
- u64 mask;
-
- if ((priv->port < 1) || (priv->port > 2))
- return -EOPNOTSUPP;
-
- mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :
- MLX4_DEV_CAP_FLAG_WOL_PORT2;
-
- if (!(priv->mdev->dev->caps.flags & mask))
- return -EOPNOTSUPP;
-
- if (wol->supported & ~WAKE_MAGIC)
- return -EINVAL;
-
- err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
- if (err) {
- en_err(priv, "Failed to get WoL info, unable to modify\n");
- return err;
- }
-
- if (wol->wolopts & WAKE_MAGIC) {
- config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
- MLX4_EN_WOL_MAGIC;
- } else {
- config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
- config |= MLX4_EN_WOL_DO_MODIFY;
- }
-
- err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
- if (err)
- en_err(priv, "Failed to set WoL information\n");
-
- return err;
-}
-
-struct bitmap_sim_iterator {
- bool advance_array;
- unsigned long *stats_bitmap;
- unsigned int count;
- unsigned int j;
-};
-
-static inline void bitmap_sim_iterator_init(struct bitmap_sim_iterator *h,
- unsigned long *stats_bitmap,
- int count)
-{
- h->j = 0;
- h->advance_array = !bitmap_empty(stats_bitmap, count);
- h->count = h->advance_array ? bitmap_weight(stats_bitmap, count)
- : count;
- h->stats_bitmap = stats_bitmap;
-}
-
-static inline int bitmap_sim_iterator_test(struct bitmap_sim_iterator *h)
-{
- return !h->advance_array ? 1 : test_bit(h->j, h->stats_bitmap);
-}
-
-static inline int bitmap_sim_iterator_inc(struct bitmap_sim_iterator *h)
-{
- return h->j++;
-}
-
-static inline unsigned int bitmap_sim_iterator_count(
- struct bitmap_sim_iterator *h)
-{
- return h->count;
-}
-
-int mlx4_en_get_sset_count(struct net_device *dev, int sset)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct bitmap_sim_iterator it;
-
- int num_of_stats = NUM_ALL_STATS -
- ((priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
-
- bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
-
- switch (sset) {
- case ETH_SS_STATS:
- return bitmap_sim_iterator_count(&it) +
- (priv->tx_ring_num * 2) +
-#ifdef LL_EXTENDED_STATS
- (priv->rx_ring_num * 5);
-#else
- (priv->rx_ring_num * 2);
-#endif
- case ETH_SS_TEST:
- return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
- & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-void mlx4_en_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int index = 0;
- int i;
- struct bitmap_sim_iterator it;
-
- int num_of_stats = NUM_ALL_STATS -
- ((priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
-
- bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
-
- if (!data || !priv->port_up)
- return;
-
- spin_lock_bh(&priv->stats_lock);
-
- for (i = 0; i < NUM_PKT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- data[index++] =
- ((unsigned long *)&priv->pkstats)[i];
- for (i = 0; i < NUM_FLOW_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
- if (bitmap_sim_iterator_test(&it))
- data[index++] =
- ((u64 *)&priv->flowstats)[i];
- for (i = 0; i < NUM_VF_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- data[index++] =
- ((unsigned long *)&priv->vf_stats)[i];
- for (i = 0; i < NUM_VPORT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- data[index++] =
- ((unsigned long *)&priv->vport_stats)[i];
- for (i = 0; i < NUM_PORT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- data[index++] =
- ((unsigned long *)&priv->port_stats)[i];
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- data[index++] = priv->tx_ring[i]->packets;
- data[index++] = priv->tx_ring[i]->bytes;
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- data[index++] = priv->rx_ring[i]->packets;
- data[index++] = priv->rx_ring[i]->bytes;
-#ifdef LL_EXTENDED_STATS
- data[index++] = priv->rx_ring[i]->yields;
- data[index++] = priv->rx_ring[i]->misses;
- data[index++] = priv->rx_ring[i]->cleaned;
-#endif
- }
- spin_unlock_bh(&priv->stats_lock);
-
-}
-
-void mlx4_en_restore_ethtool_stats(struct mlx4_en_priv *priv, u64 *data)
-{
- int index = 0;
- int i;
- struct bitmap_sim_iterator it;
-
- int num_of_stats = NUM_ALL_STATS -
- ((priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
-
- bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
-
- if (!data || !priv->port_up)
- return;
-
- spin_lock_bh(&priv->stats_lock);
-
- for (i = 0; i < NUM_PKT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- ((unsigned long *)&priv->pkstats)[i] =
- data[index++];
- for (i = 0; i < NUM_FLOW_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
- if (bitmap_sim_iterator_test(&it))
- ((u64 *)&priv->flowstats)[i] =
- data[index++];
- for (i = 0; i < NUM_VF_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- ((unsigned long *)&priv->vf_stats)[i] =
- data[index++];
- for (i = 0; i < NUM_VPORT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- ((unsigned long *)&priv->vport_stats)[i] =
- data[index++];
- for (i = 0; i < NUM_PORT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- ((unsigned long *)&priv->port_stats)[i] =
- data[index++];
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_ring[i]->packets = data[index++];
- priv->tx_ring[i]->bytes = data[index++];
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_ring[i]->packets = data[index++];
- priv->rx_ring[i]->bytes = data[index++];
- }
- spin_unlock_bh(&priv->stats_lock);
-}
-
-static void mlx4_en_self_test(struct net_device *dev,
- struct ethtool_test *etest, u64 *buf)
-{
- mlx4_en_ex_selftest(dev, &etest->flags, buf);
-}
-
-static void mlx4_en_get_strings(struct net_device *dev,
- uint32_t stringset, uint8_t *data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int index = 0;
- int i, k;
- struct bitmap_sim_iterator it;
-
- int num_of_stats = NUM_ALL_STATS -
- ((priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
-
- bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
-
- switch (stringset) {
- case ETH_SS_TEST:
- for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
- strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
- if (priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK)
- for (; i < MLX4_EN_NUM_SELF_TEST; i++)
- strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
- break;
-
- case ETH_SS_STATS:
- /* Add main counters */
- for (i = 0; i < NUM_PKT_STATS; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i]);
-
- for (k = 0; k < NUM_FLOW_STATS; k++,
- bitmap_sim_iterator_inc(&it))
- if (priv->mdev->dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
- if (bitmap_sim_iterator_test(&it))
- strcpy(data + (index++) *
- ETH_GSTRING_LEN,
- main_strings[i + k]);
-
- for (; (i + k) < num_of_stats; i++,
- bitmap_sim_iterator_inc(&it))
- if (bitmap_sim_iterator_test(&it))
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + k]);
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_bytes", i);
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_bytes", i);
-#ifdef LL_EXTENDED_STATS
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_napi_yield", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_misses", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_cleaned", i);
-#endif
- }
- break;
- }
-}
-
-static u32 mlx4_en_autoneg_get(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- u32 autoneg = AUTONEG_DISABLE;
-
- if ((mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP) &&
- priv->port_state.autoneg) {
- autoneg = AUTONEG_ENABLE;
- }
-
- return autoneg;
-}
-
-static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int trans_type;
-
- /* SUPPORTED_1000baseT_Half isn't supported */
- cmd->supported = SUPPORTED_1000baseT_Full
- |SUPPORTED_10000baseT_Full;
-
- cmd->advertising = ADVERTISED_1000baseT_Full
- |ADVERTISED_10000baseT_Full;
-
- cmd->supported |= SUPPORTED_1000baseKX_Full
- |SUPPORTED_10000baseKX4_Full
- |SUPPORTED_10000baseKR_Full
- |SUPPORTED_10000baseR_FEC
- |SUPPORTED_40000baseKR4_Full
- |SUPPORTED_40000baseCR4_Full
- |SUPPORTED_40000baseSR4_Full
- |SUPPORTED_40000baseLR4_Full;
-
- /* ADVERTISED_1000baseT_Half isn't advertised */
- cmd->advertising |= ADVERTISED_1000baseKX_Full
- |ADVERTISED_10000baseKX4_Full
- |ADVERTISED_10000baseKR_Full
- |ADVERTISED_10000baseR_FEC
- |ADVERTISED_40000baseKR4_Full
- |ADVERTISED_40000baseCR4_Full
- |ADVERTISED_40000baseSR4_Full
- |ADVERTISED_40000baseLR4_Full;
-
- if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
- return -ENOMEM;
-
- cmd->autoneg = mlx4_en_autoneg_get(dev);
- if (cmd->autoneg == AUTONEG_ENABLE) {
- cmd->supported |= SUPPORTED_Autoneg;
- cmd->advertising |= ADVERTISED_Autoneg;
- }
-
- trans_type = priv->port_state.transciver;
- if (netif_carrier_ok(dev)) {
- ethtool_cmd_speed_set(cmd, priv->port_state.link_speed);
- cmd->duplex = DUPLEX_FULL;
- } else {
- ethtool_cmd_speed_set(cmd, -1);
- cmd->duplex = -1;
- }
-
- if (trans_type > 0 && trans_type <= 0xC) {
- cmd->port = PORT_FIBRE;
- cmd->transceiver = XCVR_EXTERNAL;
- cmd->supported |= SUPPORTED_FIBRE;
- cmd->advertising |= ADVERTISED_FIBRE;
- } else if (trans_type == 0x80 || trans_type == 0) {
- cmd->port = PORT_TP;
- cmd->transceiver = XCVR_INTERNAL;
- cmd->supported |= SUPPORTED_TP;
- cmd->advertising |= ADVERTISED_TP;
- } else {
- cmd->port = -1;
- cmd->transceiver = -1;
- }
- return 0;
-}
-
-static const char *mlx4_en_duplex_to_string(int duplex)
-{
- switch (duplex) {
- case DUPLEX_FULL:
- return "FULL";
- case DUPLEX_HALF:
- return "HALF";
- default:
- break;
- }
- return "UNKNOWN";
-}
-
-static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_port_state *port_state = &priv->port_state;
-
- if ((cmd->autoneg != port_state->autoneg) ||
- (ethtool_cmd_speed(cmd) != port_state->link_speed) ||
- (cmd->duplex != DUPLEX_FULL)) {
- en_info(priv, "Changing port state properties (auto-negotiation"
- " , speed/duplex) is not supported. Current:"
- " auto-negotiation=%d speed/duplex=%d/%s\n",
- port_state->autoneg, port_state->link_speed,
- mlx4_en_duplex_to_string(DUPLEX_FULL));
- return -EOPNOTSUPP;
- }
-
- /* User provided same port state properties that are currently set.
- * Nothing to change
- */
- return 0;
-}
-
-static int mlx4_en_get_coalesce(struct net_device *dev,
- struct ethtool_coalesce *coal)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- coal->tx_coalesce_usecs = priv->tx_usecs;
- coal->tx_max_coalesced_frames = priv->tx_frames;
- coal->rx_coalesce_usecs = priv->rx_usecs;
- coal->rx_max_coalesced_frames = priv->rx_frames;
-
- coal->pkt_rate_low = priv->pkt_rate_low;
- coal->rx_coalesce_usecs_low = priv->rx_usecs_low;
- coal->pkt_rate_high = priv->pkt_rate_high;
- coal->rx_coalesce_usecs_high = priv->rx_usecs_high;
- coal->rate_sample_interval = priv->sample_interval;
- coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;
- return 0;
-}
-
-static int mlx4_en_set_coalesce(struct net_device *dev,
- struct ethtool_coalesce *coal)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int err, i;
-
- priv->rx_frames = (coal->rx_max_coalesced_frames ==
- MLX4_EN_AUTO_CONF) ?
- MLX4_EN_RX_COAL_TARGET /
- priv->dev->mtu + 1 :
- coal->rx_max_coalesced_frames;
- priv->rx_usecs = (coal->rx_coalesce_usecs ==
- MLX4_EN_AUTO_CONF) ?
- MLX4_EN_RX_COAL_TIME :
- coal->rx_coalesce_usecs;
-
- /* Setting TX coalescing parameters */
- if (coal->tx_coalesce_usecs != priv->tx_usecs ||
- coal->tx_max_coalesced_frames != priv->tx_frames) {
- priv->tx_usecs = coal->tx_coalesce_usecs;
- priv->tx_frames = coal->tx_max_coalesced_frames;
- if (priv->port_up) {
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_cq[i]->moder_cnt = priv->tx_frames;
- priv->tx_cq[i]->moder_time = priv->tx_usecs;
- if (mlx4_en_set_cq_moder(priv, priv->tx_cq[i]))
- en_warn(priv, "Failed changing moderation for TX cq %d\n", i);
- }
- }
- }
-
- /* Set adaptive coalescing params */
- priv->pkt_rate_low = coal->pkt_rate_low;
- priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
- priv->pkt_rate_high = coal->pkt_rate_high;
- priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
- priv->sample_interval = coal->rate_sample_interval;
- priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
- if (priv->adaptive_rx_coal)
- return 0;
-
- if (priv->port_up) {
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i]->moder_cnt = priv->rx_frames;
- priv->rx_cq[i]->moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
- if (err)
- return err;
- }
- }
-
- return 0;
-}
-
-static int mlx4_en_set_pauseparam(struct net_device *dev,
- struct ethtool_pauseparam *pause)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
-
- if (pause->autoneg)
- return -EOPNOTSUPP;
-
- priv->prof->tx_pause = pause->tx_pause != 0;
- priv->prof->rx_pause = pause->rx_pause != 0;
- err = mlx4_SET_PORT_general(mdev->dev, priv->port,
- priv->rx_skb_size + ETH_FCS_LEN,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
- if (err)
- en_err(priv, "Failed setting pause params\n");
-
- return err;
-}
-
-static void mlx4_en_get_pauseparam(struct net_device *dev,
- struct ethtool_pauseparam *pause)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- pause->tx_pause = priv->prof->tx_pause;
- pause->rx_pause = priv->prof->rx_pause;
- pause->autoneg = mlx4_en_autoneg_get(dev);
-}
-
-/* rtnl lock must be taken before calling */
-int mlx4_en_pre_config(struct mlx4_en_priv *priv)
-{
-#ifdef CONFIG_RFS_ACCEL
- struct cpu_rmap *rmap;
-
- if (!priv->dev->rx_cpu_rmap)
- return 0;
-
- /* Disable RFS events
- * Must have all RFS jobs flushed before freeing resources
- */
- rmap = priv->dev->rx_cpu_rmap;
- priv->dev->rx_cpu_rmap = NULL;
-
- rtnl_unlock();
- free_irq_cpu_rmap(rmap);
- rtnl_lock();
-
- if (priv->dev->rx_cpu_rmap)
- return -EBUSY; /* another configuration completed while lock
- * was free
- */
-
- /* Make sure all currently running filter_work are being processed
- * Other work will return immediatly because of disable_rfs
- */
- flush_workqueue(priv->mdev->workqueue);
-
-#endif
-
- return 0;
-}
-
-static int mlx4_en_set_ringparam(struct net_device *dev,
- struct ethtool_ringparam *param)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- u32 rx_size, tx_size;
- int port_up = 0;
- int err = 0;
- int i, n_stats;
- u64 *data = NULL;
-
- if (!priv->port_up)
- return -ENOMEM;
-
- if (param->rx_jumbo_pending || param->rx_mini_pending)
- return -EINVAL;
-
- rx_size = roundup_pow_of_two(param->rx_pending);
- rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
- rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
- tx_size = roundup_pow_of_two(param->tx_pending);
- tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
- tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
-
- if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :
- priv->rx_ring[0]->size) &&
- tx_size == priv->tx_ring[0]->size)
- return 0;
- err = mlx4_en_pre_config(priv);
- if (err)
- return err;
-
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_stop_port(dev);
- }
-
- /* Cache port statistics */
- n_stats = mlx4_en_get_sset_count(dev, ETH_SS_STATS);
- if (n_stats > 0) {
- data = kmalloc(n_stats * sizeof(u64), GFP_KERNEL);
- if (data)
- mlx4_en_get_ethtool_stats(dev, NULL, data);
- }
-
- mlx4_en_free_resources(priv);
-
- priv->prof->tx_ring_size = tx_size;
- priv->prof->rx_ring_size = rx_size;
-
- err = mlx4_en_alloc_resources(priv);
- if (err) {
- en_err(priv, "Failed reallocating port resources\n");
- goto out;
- }
-
- /* Restore port statistics */
- if (n_stats > 0 && data)
- mlx4_en_restore_ethtool_stats(priv, data);
-
- if (port_up) {
- err = mlx4_en_start_port(dev);
- if (err) {
- en_err(priv, "Failed starting port\n");
- goto out;
- }
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i]->moder_cnt = priv->rx_frames;
- priv->rx_cq[i]->moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
- if (err)
- goto out;
- }
- }
-
-out:
- kfree(data);
- mutex_unlock(&mdev->state_lock);
- return err;
-}
-
-static void mlx4_en_get_ringparam(struct net_device *dev,
- struct ethtool_ringparam *param)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- if (!priv->port_up)
- return;
-
- memset(param, 0, sizeof(*param));
- param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
- param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
- param->rx_pending = priv->port_up ?
- priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;
- param->tx_pending = priv->tx_ring[0]->size;
-}
-
-static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- return priv->rx_ring_num;
-}
-
-static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_rss_map *rss_map = &priv->rss_map;
- int rss_rings;
- size_t n = priv->rx_ring_num;
- int err = 0;
-
- rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
- rss_rings = 1 << ilog2(rss_rings);
-
- while (n--) {
- ring_index[n] = rss_map->qps[n % rss_rings].qpn -
- rss_map->base_qpn;
- }
-
- return err;
-}
-
-static int mlx4_en_set_rxfh_indir(struct net_device *dev,
- const u32 *ring_index)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int port_up = 0;
- int err = 0;
- int i;
- int rss_rings = 0;
-
- /* Calculate RSS table size and make sure flows are spread evenly
- * between rings
- */
- for (i = 0; i < priv->rx_ring_num; i++) {
- if (i > 0 && !ring_index[i] && !rss_rings)
- rss_rings = i;
-
- if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
- return -EINVAL;
- }
-
- if (!rss_rings)
- rss_rings = priv->rx_ring_num;
-
- /* RSS table size must be an order of 2 */
- if (!is_power_of_2(rss_rings))
- return -EINVAL;
-
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_stop_port(dev);
- }
-
- priv->prof->rss_rings = rss_rings;
-
- if (port_up) {
- err = mlx4_en_start_port(dev);
- if (err)
- en_err(priv, "Failed starting port\n");
- }
-
- mutex_unlock(&mdev->state_lock);
- return err;
-}
-
-#define all_zeros_or_all_ones(field) \
- ((field) == 0 || (field) == (__force typeof(field))-1)
-
-static int mlx4_en_validate_flow(struct net_device *dev,
- struct mlx4_ethtool_rxnfc *cmd)
-{
- struct ethtool_usrip4_spec *l3_mask;
- struct ethtool_tcpip4_spec *l4_mask;
- struct ethhdr *eth_mask;
-
- if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)
- return -EINVAL;
-
- if (cmd->fs.flow_type & FLOW_MAC_EXT) {
- /* dest mac mask must be ff:ff:ff:ff:ff:ff */
- if (!is_broadcast_ether_addr(cmd->fs.m_ext.h_dest))
- return -EINVAL;
- }
-
- switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
- case TCP_V4_FLOW:
- case UDP_V4_FLOW:
- if (cmd->fs.m_u.tcp_ip4_spec.tos)
- return -EINVAL;
- l4_mask = &cmd->fs.m_u.tcp_ip4_spec;
- /* don't allow mask which isn't all 0 or 1 */
- if (!all_zeros_or_all_ones(l4_mask->ip4src) ||
- !all_zeros_or_all_ones(l4_mask->ip4dst) ||
- !all_zeros_or_all_ones(l4_mask->psrc) ||
- !all_zeros_or_all_ones(l4_mask->pdst))
- return -EINVAL;
- break;
- case IP_USER_FLOW:
- l3_mask = &cmd->fs.m_u.usr_ip4_spec;
- if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto ||
- cmd->fs.h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 ||
- (!l3_mask->ip4src && !l3_mask->ip4dst) ||
- !all_zeros_or_all_ones(l3_mask->ip4src) ||
- !all_zeros_or_all_ones(l3_mask->ip4dst))
- return -EINVAL;
- break;
- case ETHER_FLOW:
- eth_mask = &cmd->fs.m_u.ether_spec;
- /* source mac mask must not be set */
- if (!is_zero_ether_addr(eth_mask->h_source))
- return -EINVAL;
-
- /* dest mac mask must be ff:ff:ff:ff:ff:ff */
- if (!is_broadcast_ether_addr(eth_mask->h_dest))
- return -EINVAL;
-
- if (!all_zeros_or_all_ones(eth_mask->h_proto))
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
-
- if ((cmd->fs.flow_type & FLOW_EXT)) {
- if (cmd->fs.m_ext.vlan_etype ||
- !(cmd->fs.m_ext.vlan_tci == 0 ||
- cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff)))
- return -EINVAL;
- if (cmd->fs.m_ext.vlan_tci) {
- if (be16_to_cpu(cmd->fs.h_ext.vlan_tci) <
- VLAN_MIN_VALUE ||
- be16_to_cpu(cmd->fs.h_ext.vlan_tci) >
- VLAN_MAX_VALUE)
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int mlx4_en_ethtool_add_mac_rule(struct mlx4_ethtool_rxnfc *cmd,
- struct list_head *rule_list_h,
- struct mlx4_spec_list *spec_l2,
- unsigned char *mac)
-{
- int err = 0;
- __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
-
- spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH;
- memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN);
- memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN);
-
- if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) {
- spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci;
- spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff);
- }
-
- list_add_tail(&spec_l2->list, rule_list_h);
-
- return err;
-}
-
-static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv,
- struct mlx4_ethtool_rxnfc *cmd,
- struct list_head *rule_list_h,
- struct mlx4_spec_list *spec_l2,
- __be32 ipv4_dst)
-{
- unsigned char mac[ETH_ALEN];
-
- if (!ipv4_is_multicast(ipv4_dst)) {
- if (cmd->fs.flow_type & FLOW_MAC_EXT)
- memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN);
- else
- memcpy(&mac, priv->dev->dev_addr, ETH_ALEN);
- } else {
- ip_eth_mc_map(ipv4_dst, mac);
- }
-
- return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]);
-}
-
-static int add_ip_rule(struct mlx4_en_priv *priv,
- struct mlx4_ethtool_rxnfc *cmd,
- struct list_head *list_h)
-{
- struct mlx4_spec_list *spec_l2 = NULL;
- struct mlx4_spec_list *spec_l3 = NULL;
- struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec;
-
- spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
- spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
- if (!spec_l2 || !spec_l3) {
- en_err(priv, "Fail to alloc ethtool rule.\n");
- kfree(spec_l2);
- kfree(spec_l3);
- return -ENOMEM;
- }
-
- mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2,
- cmd->fs.h_u.
- usr_ip4_spec.ip4dst);
- spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
- spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src;
- if (l3_mask->ip4src)
- spec_l3->ipv4.src_ip_msk = MLX4_BE_WORD_MASK;
- spec_l3->ipv4.dst_ip = cmd->fs.h_u.usr_ip4_spec.ip4dst;
- if (l3_mask->ip4dst)
- spec_l3->ipv4.dst_ip_msk = MLX4_BE_WORD_MASK;
- list_add_tail(&spec_l3->list, list_h);
-
- return 0;
-}
-
-static int add_tcp_udp_rule(struct mlx4_en_priv *priv,
- struct mlx4_ethtool_rxnfc *cmd,
- struct list_head *list_h, int proto)
-{
- struct mlx4_spec_list *spec_l2 = NULL;
- struct mlx4_spec_list *spec_l3 = NULL;
- struct mlx4_spec_list *spec_l4 = NULL;
- struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec;
-
- spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
- spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
- spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL);
- if (!spec_l2 || !spec_l3 || !spec_l4) {
- en_err(priv, "Fail to alloc ethtool rule.\n");
- kfree(spec_l2);
- kfree(spec_l3);
- kfree(spec_l4);
- return -ENOMEM;
- }
-
- spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
-
- if (proto == TCP_V4_FLOW) {
- mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
- spec_l2,
- cmd->fs.h_u.
- tcp_ip4_spec.ip4dst);
- spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP;
- spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src;
- spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst;
- spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc;
- spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst;
- } else {
- mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
- spec_l2,
- cmd->fs.h_u.
- udp_ip4_spec.ip4dst);
- spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP;
- spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src;
- spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst;
- spec_l4->tcp_udp.src_port = cmd->fs.h_u.udp_ip4_spec.psrc;
- spec_l4->tcp_udp.dst_port = cmd->fs.h_u.udp_ip4_spec.pdst;
- }
-
- if (l4_mask->ip4src)
- spec_l3->ipv4.src_ip_msk = MLX4_BE_WORD_MASK;
- if (l4_mask->ip4dst)
- spec_l3->ipv4.dst_ip_msk = MLX4_BE_WORD_MASK;
-
- if (l4_mask->psrc)
- spec_l4->tcp_udp.src_port_msk = MLX4_BE_SHORT_MASK;
- if (l4_mask->pdst)
- spec_l4->tcp_udp.dst_port_msk = MLX4_BE_SHORT_MASK;
-
- list_add_tail(&spec_l3->list, list_h);
- list_add_tail(&spec_l4->list, list_h);
-
- return 0;
-}
-
-static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
- struct mlx4_ethtool_rxnfc *cmd,
- struct list_head *rule_list_h)
-{
- int err;
- struct ethhdr *eth_spec;
- struct mlx4_spec_list *spec_l2;
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- err = mlx4_en_validate_flow(dev, cmd);
- if (err)
- return err;
-
- switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
- case ETHER_FLOW:
- spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
- if (!spec_l2)
- return -ENOMEM;
-
- eth_spec = &cmd->fs.h_u.ether_spec;
- mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, ð_spec->h_dest[0]);
- spec_l2->eth.ether_type = eth_spec->h_proto;
- if (eth_spec->h_proto)
- spec_l2->eth.ether_type_enable = 1;
- break;
- case IP_USER_FLOW:
- err = add_ip_rule(priv, cmd, rule_list_h);
- break;
- case TCP_V4_FLOW:
- err = add_tcp_udp_rule(priv, cmd, rule_list_h, TCP_V4_FLOW);
- break;
- case UDP_V4_FLOW:
- err = add_tcp_udp_rule(priv, cmd, rule_list_h, UDP_V4_FLOW);
- break;
- }
-
- return err;
-}
-
-static int mlx4_en_flow_replace(struct net_device *dev,
- struct mlx4_ethtool_rxnfc *cmd)
-{
- int err;
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct ethtool_flow_id *loc_rule;
- struct mlx4_spec_list *spec, *tmp_spec;
- u32 qpn;
- u64 reg_id;
-
- struct mlx4_net_trans_rule rule = {
- .queue_mode = MLX4_NET_TRANS_Q_FIFO,
- .exclusive = 0,
- .allow_loopback = 1,
- .promisc_mode = MLX4_FS_REGULAR,
- };
-
- rule.port = priv->port;
- rule.priority = MLX4_DOMAIN_ETHTOOL | cmd->fs.location;
- INIT_LIST_HEAD(&rule.list);
-
- /* Allow direct QP attaches if the EN_ETHTOOL_QP_ATTACH flag is set */
- if (cmd->fs.ring_cookie == RX_CLS_FLOW_DISC)
- qpn = priv->drop_qp.qpn;
- else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
- qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
- } else {
- if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
- en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist.\n",
- cmd->fs.ring_cookie);
- return -EINVAL;
- }
- qpn = priv->rss_map.qps[cmd->fs.ring_cookie].qpn;
- if (!qpn) {
- en_warn(priv, "rxnfc: RX ring (%llu) is inactive.\n",
- cmd->fs.ring_cookie);
- return -EINVAL;
- }
- }
- rule.qpn = qpn;
- err = mlx4_en_ethtool_to_net_trans_rule(dev, cmd, &rule.list);
- if (err)
- goto out_free_list;
-
- mutex_lock(&mdev->state_lock);
- loc_rule = &priv->ethtool_rules[cmd->fs.location];
- if (loc_rule->id) {
- err = mlx4_flow_detach(priv->mdev->dev, loc_rule->id);
- if (err) {
- en_err(priv, "Fail to detach network rule at location %d. registration id = %llx\n",
- cmd->fs.location, loc_rule->id);
- goto unlock;
- }
- loc_rule->id = 0;
- memset(&loc_rule->flow_spec, 0,
- sizeof(struct ethtool_rx_flow_spec));
- list_del(&loc_rule->list);
- }
- err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id);
- if (err) {
- en_err(priv, "Fail to attach network rule at location %d.\n",
- cmd->fs.location);
- goto unlock;
- }
- loc_rule->id = reg_id;
- memcpy(&loc_rule->flow_spec, &cmd->fs,
- sizeof(struct ethtool_rx_flow_spec));
- list_add_tail(&loc_rule->list, &priv->ethtool_list);
-
-unlock:
- mutex_unlock(&mdev->state_lock);
-out_free_list:
- list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) {
- list_del(&spec->list);
- kfree(spec);
- }
- return err;
-}
-
-static int mlx4_en_flow_detach(struct net_device *dev,
- struct mlx4_ethtool_rxnfc *cmd)
-{
- int err = 0;
- struct ethtool_flow_id *rule;
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
-
- if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)
- return -EINVAL;
-
- mutex_lock(&mdev->state_lock);
- rule = &priv->ethtool_rules[cmd->fs.location];
- if (!rule->id) {
- err = -ENOENT;
- goto out;
- }
-
- err = mlx4_flow_detach(priv->mdev->dev, rule->id);
- if (err) {
- en_err(priv, "Fail to detach network rule at location %d. registration id = 0x%llx\n",
- cmd->fs.location, rule->id);
- goto out;
- }
- rule->id = 0;
- memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec));
-
- list_del(&rule->list);
-out:
- mutex_unlock(&mdev->state_lock);
- return err;
-
-}
-
-static int mlx4_en_get_flow(struct net_device *dev, struct mlx4_ethtool_rxnfc *cmd,
- int loc)
-{
- int err = 0;
- struct ethtool_flow_id *rule;
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- if (loc < 0 || loc >= MAX_NUM_OF_FS_RULES)
- return -EINVAL;
-
- rule = &priv->ethtool_rules[loc];
- if (rule->id)
- memcpy(&cmd->fs, &rule->flow_spec,
- sizeof(struct ethtool_rx_flow_spec));
- else
- err = -ENOENT;
-
- return err;
-}
-
-static int mlx4_en_get_num_flows(struct mlx4_en_priv *priv)
-{
-
- int i, res = 0;
- for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) {
- if (priv->ethtool_rules[i].id)
- res++;
- }
- return res;
-
-}
-
-static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *c,
- u32 *rule_locs)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err = 0;
- int i = 0, priority = 0;
- struct mlx4_ethtool_rxnfc *cmd = (struct mlx4_ethtool_rxnfc *)c;
-
- if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT ||
- cmd->cmd == ETHTOOL_GRXCLSRULE ||
- cmd->cmd == ETHTOOL_GRXCLSRLALL) &&
- (mdev->dev->caps.steering_mode !=
- MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up))
- return -EINVAL;
-
- switch (cmd->cmd) {
- case ETHTOOL_GRXRINGS:
- cmd->data = priv->rx_ring_num;
- break;
- case ETHTOOL_GRXCLSRLCNT:
- cmd->rule_cnt = mlx4_en_get_num_flows(priv);
- break;
- case ETHTOOL_GRXCLSRULE:
- err = mlx4_en_get_flow(dev, cmd, cmd->fs.location);
- break;
- case ETHTOOL_GRXCLSRLALL:
- while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) {
- err = mlx4_en_get_flow(dev, cmd, i);
- if (!err)
- rule_locs[priority++] = i;
- i++;
- }
- err = 0;
- break;
- default:
- err = -EOPNOTSUPP;
- break;
- }
-
- return err;
-}
-
-static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *c)
-{
- int err = 0;
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_ethtool_rxnfc *cmd = (struct mlx4_ethtool_rxnfc *)c;
-
- if (mdev->dev->caps.steering_mode !=
- MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up)
- return -EINVAL;
-
- switch (cmd->cmd) {
- case ETHTOOL_SRXCLSRLINS:
- err = mlx4_en_flow_replace(dev, cmd);
- break;
- case ETHTOOL_SRXCLSRLDEL:
- err = mlx4_en_flow_detach(dev, cmd);
- break;
- default:
- en_warn(priv, "Unsupported ethtool command. (%d)\n", cmd->cmd);
- return -EINVAL;
- }
-
- return err;
-}
-
-static void mlx4_en_get_channels(struct net_device *dev,
- struct ethtool_channels *channel)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- memset(channel, 0, sizeof(*channel));
-
- channel->max_rx = MAX_RX_RINGS;
- channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
-
- channel->rx_count = priv->rx_ring_num;
- channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
-}
-
-static int mlx4_en_set_channels(struct net_device *dev,
- struct ethtool_channels *channel)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int port_up = 0;
- int i;
- int err = 0;
-
- if (channel->other_count || channel->combined_count ||
- channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
- channel->rx_count > MAX_RX_RINGS ||
- !channel->tx_count || !channel->rx_count)
- return -EINVAL;
-
- err = mlx4_en_pre_config(priv);
- if (err)
- return err;
-
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_stop_port(dev);
- }
-
- mlx4_en_free_resources(priv);
-
- priv->num_tx_rings_p_up = channel->tx_count;
- priv->tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
- priv->rx_ring_num = channel->rx_count;
-
- err = mlx4_en_alloc_resources(priv);
- if (err) {
- en_err(priv, "Failed reallocating port resources\n");
- goto out;
- }
-
- netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
- netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
-
- mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
-
- en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
- en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
-
- if (port_up) {
- err = mlx4_en_start_port(dev);
- if (err)
- en_err(priv, "Failed starting port\n");
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i]->moder_cnt = priv->rx_frames;
- priv->rx_cq[i]->moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
- if (err)
- goto out;
- }
- }
-
-out:
- mutex_unlock(&mdev->state_lock);
- return err;
-}
-
-static int mlx4_en_get_ts_info(struct net_device *dev,
- struct ethtool_ts_info *info)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int ret;
-
- ret = ethtool_op_get_ts_info(dev, info);
- if (ret)
- return ret;
-
- if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
- info->so_timestamping |=
- SOF_TIMESTAMPING_TX_HARDWARE |
- SOF_TIMESTAMPING_RX_HARDWARE |
- SOF_TIMESTAMPING_RAW_HARDWARE;
-
- info->tx_types =
- (1 << HWTSTAMP_TX_OFF) |
- (1 << HWTSTAMP_TX_ON);
-
- info->rx_filters =
- (1 << HWTSTAMP_FILTER_NONE) |
- (1 << HWTSTAMP_FILTER_ALL);
- }
-
- return ret;
-}
-
-const struct ethtool_ops mlx4_en_ethtool_ops = {
- .get_drvinfo = mlx4_en_get_drvinfo,
- .get_settings = mlx4_en_get_settings,
- .set_settings = mlx4_en_set_settings,
- .get_link = ethtool_op_get_link,
- .get_strings = mlx4_en_get_strings,
- .get_sset_count = mlx4_en_get_sset_count,
- .get_ethtool_stats = mlx4_en_get_ethtool_stats,
- .self_test = mlx4_en_self_test,
- .get_wol = mlx4_en_get_wol,
- .set_wol = mlx4_en_set_wol,
- .get_msglevel = mlx4_en_get_msglevel,
- .set_msglevel = mlx4_en_set_msglevel,
- .get_coalesce = mlx4_en_get_coalesce,
- .set_coalesce = mlx4_en_set_coalesce,
- .get_pauseparam = mlx4_en_get_pauseparam,
- .set_pauseparam = mlx4_en_set_pauseparam,
- .get_ringparam = mlx4_en_get_ringparam,
- .set_ringparam = mlx4_en_set_ringparam,
- .get_rxnfc = mlx4_en_get_rxnfc,
- .set_rxnfc = mlx4_en_set_rxnfc,
- .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
- .get_rxfh_indir = mlx4_en_get_rxfh_indir,
- .set_rxfh_indir = mlx4_en_set_rxfh_indir,
- .get_channels = mlx4_en_get_channels,
- .set_channels = mlx4_en_set_channels,
- .get_ts_info = mlx4_en_get_ts_info,
-};
-
-
-
-
-
Index: head/sys/ofed/drivers/net/mlx4/en_main.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_main.c
+++ head/sys/ofed/drivers/net/mlx4/en_main.c
@@ -42,16 +42,7 @@
#include "mlx4_en.h"
-MODULE_AUTHOR("Liran Liss, Yevgeny Petrilin");
-MODULE_DESCRIPTION("Mellanox ConnectX HCA Ethernet driver");
-MODULE_LICENSE("Dual BSD/GPL");
-#ifdef __linux__
-MODULE_VERSION(DRV_VERSION " ("DRV_RELDATE")");
-#endif
-
-static const char mlx4_en_version[] =
- DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v"
- DRV_VERSION " (" DRV_RELDATE ")\n";
+/* Mellanox ConnectX HCA Ethernet driver */
#define MLX4_EN_PARM_INT(X, def_val, desc) \
static unsigned int X = def_val;\
@@ -176,8 +167,6 @@
int i;
int err;
- printk_once(KERN_INFO "%s", mlx4_en_version);
-
mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
if (!mdev) {
dev_err(&dev->pdev->dev, "Device struct alloc failed, "
Index: head/sys/ofed/drivers/net/mlx4/en_netdev.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_netdev.c
+++ head/sys/ofed/drivers/net/mlx4/en_netdev.c
@@ -658,8 +658,10 @@
continue;
/* Make sure the list didn't grow. */
tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
- if (tmp == NULL)
+ if (tmp == NULL) {
+ en_err(priv, "Failed to allocate multicast list\n");
break;
+ }
memcpy(tmp->addr,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
list_add_tail(&tmp->list, &priv->mc_list);
@@ -970,12 +972,12 @@
if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
if (priv->port_state.link_state) {
priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
- /* Important note: the following call for if_link_state_change
- * is needed for interface up scenario (start port, link state
- * change) */
/* update netif baudrate */
priv->dev->if_baudrate =
IF_Mbps(priv->port_state.link_speed);
+ /* Important note: the following call for if_link_state_change
+ * is needed for interface up scenario (start port, link state
+ * change) */
if_link_state_change(priv->dev, LINK_STATE_UP);
en_dbg(HW, priv, "Link Up\n");
}
@@ -1195,8 +1197,8 @@
/* update netif baudrate */
priv->dev->if_baudrate = 0;
- /* make sure the port is up before notifying the OS.
- * This is tricky since we get here on INIT_PORT and
+ /* make sure the port is up before notifying the OS.
+ * This is tricky since we get here on INIT_PORT and
* in such case we can't tell the OS the port is up.
* To solve this there is a call to if_link_state_change
* in set_rx_mode.
@@ -1574,6 +1576,7 @@
priv->tx_ring[i]->bytes = 0;
priv->tx_ring[i]->packets = 0;
priv->tx_ring[i]->tx_csum = 0;
+ priv->tx_ring[i]->oversized_packets = 0;
}
for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_ring[i]->bytes = 0;
@@ -1643,8 +1646,6 @@
if (priv->sysctl)
sysctl_ctx_free(&priv->stat_ctx);
-
-
}
int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
@@ -1729,8 +1730,11 @@
EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
/* Unregister device - this will close the port if it was up */
- if (priv->registered)
+ if (priv->registered) {
+ mutex_lock(&mdev->state_lock);
ether_ifdetach(dev);
+ mutex_unlock(&mdev->state_lock);
+ }
if (priv->allocated)
mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
@@ -1808,13 +1812,6 @@
active = IFM_ETHER;
if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN)
return (active);
- /*
- * [ShaharK] mlx4_en_QUERY_PORT sleeps and cannot be called under a
- * non-sleepable lock.
- * I moved it to the periodic mlx4_en_do_get_stats.
- if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
- return (active);
- */
active |= IFM_FDX;
trans_type = priv->port_state.transciver;
/* XXX I don't know all of the transceiver values. */
@@ -1947,12 +1944,55 @@
case SIOCSIFCAP:
mutex_lock(&mdev->state_lock);
mask = ifr->ifr_reqcap ^ dev->if_capenable;
- if (mask & IFCAP_HWCSUM)
- dev->if_capenable ^= IFCAP_HWCSUM;
- if (mask & IFCAP_TSO4)
+ if (mask & IFCAP_TXCSUM) {
+ dev->if_capenable ^= IFCAP_TXCSUM;
+ dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
+
+ if (IFCAP_TSO4 & dev->if_capenable &&
+ !(IFCAP_TXCSUM & dev->if_capenable)) {
+ dev->if_capenable &= ~IFCAP_TSO4;
+ dev->if_hwassist &= ~CSUM_IP_TSO;
+ if_printf(dev,
+ "tso4 disabled due to -txcsum.\n");
+ }
+ }
+ if (mask & IFCAP_TXCSUM_IPV6) {
+ dev->if_capenable ^= IFCAP_TXCSUM_IPV6;
+ dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
+
+ if (IFCAP_TSO6 & dev->if_capenable &&
+ !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
+ dev->if_capenable &= ~IFCAP_TSO6;
+ dev->if_hwassist &= ~CSUM_IP6_TSO;
+ if_printf(dev,
+ "tso6 disabled due to -txcsum6.\n");
+ }
+ }
+ if (mask & IFCAP_RXCSUM)
+ dev->if_capenable ^= IFCAP_RXCSUM;
+ if (mask & IFCAP_RXCSUM_IPV6)
+ dev->if_capenable ^= IFCAP_RXCSUM_IPV6;
+
+ if (mask & IFCAP_TSO4) {
+ if (!(IFCAP_TSO4 & dev->if_capenable) &&
+ !(IFCAP_TXCSUM & dev->if_capenable)) {
+ if_printf(dev, "enable txcsum first.\n");
+ error = EAGAIN;
+ goto out;
+ }
dev->if_capenable ^= IFCAP_TSO4;
- if (mask & IFCAP_TSO6)
+ dev->if_hwassist ^= CSUM_IP_TSO;
+ }
+ if (mask & IFCAP_TSO6) {
+ if (!(IFCAP_TSO6 & dev->if_capenable) &&
+ !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
+ if_printf(dev, "enable txcsum6 first.\n");
+ error = EAGAIN;
+ goto out;
+ }
dev->if_capenable ^= IFCAP_TSO6;
+ dev->if_hwassist ^= CSUM_IP6_TSO;
+ }
if (mask & IFCAP_LRO)
dev->if_capenable ^= IFCAP_LRO;
if (mask & IFCAP_VLAN_HWTAGGING)
@@ -1963,9 +2003,11 @@
dev->if_capenable ^= IFCAP_WOL_MAGIC;
if (dev->if_drv_flags & IFF_DRV_RUNNING)
mlx4_en_start_port(dev);
+out:
mutex_unlock(&mdev->state_lock);
VLAN_CAPABILITIES(dev);
break;
+#if __FreeBSD_version >= 1100036
case SIOCGI2C: {
struct ifi2creq i2c;
@@ -1989,6 +2031,7 @@
error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
break;
}
+#endif
default:
error = ether_ioctl(dev, command, data);
break;
@@ -2088,7 +2131,6 @@
for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
INIT_HLIST_HEAD(&priv->mac_hash[i]);
-
/* Query for default mac and max mtu */
priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
priv->mac = mdev->dev->caps.def_mac[priv->port];
@@ -2104,8 +2146,6 @@
goto out;
}
-
-
priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
DS_SIZE);
@@ -2127,7 +2167,7 @@
/*
* Set driver features
*/
- dev->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM;
+ dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
@@ -2136,10 +2176,12 @@
if (mdev->LSO_support)
dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO;
+#if __FreeBSD_version >= 1100000
/* set TSO limits so that we don't have to drop TX packets */
- dev->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
- dev->if_hw_tsomaxsegcount = 16;
- dev->if_hw_tsomaxsegsize = 65536; /* XXX can do up to 4GByte */
+ dev->if_hw_tsomax = MLX4_EN_TX_MAX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) /* hdr */;
+ dev->if_hw_tsomaxsegcount = MLX4_EN_TX_MAX_MBUF_FRAGS - 1 /* hdr */;
+ dev->if_hw_tsomaxsegsize = MLX4_EN_TX_MAX_MBUF_SIZE;
+#endif
dev->if_capenable = dev->if_capabilities;
@@ -2148,6 +2190,8 @@
dev->if_hwassist |= CSUM_TSO;
if (dev->if_capenable & IFCAP_TXCSUM)
dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
+ if (dev->if_capenable & IFCAP_TXCSUM_IPV6)
+ dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
/* Register for VLAN events */
@@ -2210,8 +2254,6 @@
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY);
-
-
return 0;
out:
@@ -2293,6 +2335,162 @@
return (error);
}
+static int mlx4_en_get_module_info(struct net_device *dev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int ret;
+ u8 data[4];
+
+ /* Read first 2 bytes to get Module & REV ID */
+ ret = mlx4_get_module_info(mdev->dev, priv->port,
+ 0/*offset*/, 2/*size*/, data);
+
+ if (ret < 2) {
+ en_err(priv, "Failed to read eeprom module first two bytes, error: 0x%x\n", -ret);
+ return -EIO;
+ }
+
+ switch (data[0] /* identifier */) {
+ case MLX4_MODULE_ID_QSFP:
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+ break;
+ case MLX4_MODULE_ID_QSFP_PLUS:
+ if (data[1] >= 0x3) { /* revision id */
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+ }
+ break;
+ case MLX4_MODULE_ID_QSFP28:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
+ break;
+ case MLX4_MODULE_ID_SFP:
+ modinfo->type = ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+ break;
+ default:
+ en_err(priv, "mlx4_en_get_module_info : Not recognized cable type\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mlx4_en_get_module_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee,
+ u8 *data)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int offset = ee->offset;
+ int i = 0, ret;
+
+ if (ee->len == 0)
+ return -EINVAL;
+
+ memset(data, 0, ee->len);
+
+ while (i < ee->len) {
+ en_dbg(DRV, priv,
+ "mlx4_get_module_info i(%d) offset(%d) len(%d)\n",
+ i, offset, ee->len - i);
+
+ ret = mlx4_get_module_info(mdev->dev, priv->port,
+ offset, ee->len - i, data + i);
+
+ if (!ret) /* Done reading */
+ return 0;
+
+ if (ret < 0) {
+ en_err(priv,
+ "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",
+ i, offset, ee->len - i, ret);
+ return -1;
+ }
+
+ i += ret;
+ offset += ret;
+ }
+ return 0;
+}
+
+static void mlx4_en_print_eeprom(u8 *data, __u32 len)
+{
+ int i;
+ int j = 0;
+ int row = 0;
+ const int NUM_OF_BYTES = 16;
+
+ printf("\nOffset\t\tValues\n");
+ printf("------\t\t------\n");
+ while(row < len){
+ printf("0x%04x\t\t",row);
+ for(i=0; i < NUM_OF_BYTES; i++){
+ printf("%02x ", data[j]);
+ row++;
+ j++;
+ }
+ printf("\n");
+ }
+}
+
+/* Read cable EEPROM module information by first inspecting the first
+ * two bytes to get the length and then read the rest of the information.
+ * The information is printed to dmesg. */
+static int mlx4_en_read_eeprom(SYSCTL_HANDLER_ARGS)
+{
+
+ u8* data;
+ int error;
+ int result = 0;
+ struct mlx4_en_priv *priv;
+ struct net_device *dev;
+ struct ethtool_modinfo modinfo;
+ struct ethtool_eeprom ee;
+
+ error = sysctl_handle_int(oidp, &result, 0, req);
+ if (error || !req->newptr)
+ return (error);
+
+ if (result == 1) {
+ priv = arg1;
+ dev = priv->dev;
+ data = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+ error = mlx4_en_get_module_info(dev, &modinfo);
+ if (error) {
+ en_err(priv,
+ "mlx4_en_get_module_info returned with error - FAILED (0x%x)\n",
+ -error);
+ goto out;
+ }
+
+ ee.len = modinfo.eeprom_len;
+ ee.offset = 0;
+
+ error = mlx4_en_get_module_eeprom(dev, &ee, data);
+ if (error) {
+ en_err(priv,
+ "mlx4_en_get_module_eeprom returned with error - FAILED (0x%x)\n",
+ -error);
+ /* Continue printing partial information in case of an error */
+ }
+
+ /* EEPROM information will be printed in dmesg */
+ mlx4_en_print_eeprom(data, ee.len);
+out:
+ kfree(data);
+ }
+ /* Return zero to prevent sysctl failure. */
+ return (0);
+}
+
static int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS)
{
struct mlx4_en_priv *priv;
@@ -2418,7 +2616,7 @@
/* Add coalescer configuration. */
coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
"coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
- coal_list = SYSCTL_CHILDREN(node);
+ coal_list = SYSCTL_CHILDREN(coal);
SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
CTLFLAG_RW, &priv->pkt_rate_low, 0,
"Packets per-second for minimum delay");
@@ -2437,11 +2635,14 @@
SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
"Enable adaptive rx coalescing");
+ /* EEPROM support */
+ SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "eeprom_info",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
+ mlx4_en_read_eeprom, "I", "EEPROM information");
}
static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
{
- struct net_device *dev;
struct sysctl_ctx_list *ctx;
struct sysctl_oid *node;
struct sysctl_oid_list *node_list;
@@ -2452,8 +2653,6 @@
char namebuf[128];
int i;
- dev = priv->dev;
-
ctx = &priv->stat_ctx;
sysctl_ctx_init(ctx);
node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
@@ -2481,6 +2680,8 @@
&priv->port_stats.wake_queue, "Queue resumed after full");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD,
&priv->port_stats.tx_timeout, "Transmit timeouts");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD,
+ &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD,
&priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD,
@@ -2564,7 +2765,7 @@
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD,
&priv->pkstats.tx_packets, "TX packets");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD,
- &priv->pkstats.tx_packets, "TX Bytes");
+ &priv->pkstats.tx_bytes, "TX Bytes");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD,
&priv->pkstats.tx_multicast_packets, "TX Multicast Packets");
SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD,
@@ -2605,8 +2806,8 @@
CTLFLAG_RD, &tx_ring->packets, "TX packets");
SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
CTLFLAG_RD, &tx_ring->bytes, "TX bytes");
-
}
+
for (i = 0; i < priv->rx_ring_num; i++) {
rx_ring = priv->rx_ring[i];
snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i);
Index: head/sys/ofed/drivers/net/mlx4/en_port.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_port.c
+++ head/sys/ofed/drivers/net/mlx4/en_port.c
@@ -194,6 +194,7 @@
priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum;
priv->port_stats.queue_stopped += priv->tx_ring[i]->queue_stopped;
priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue;
+ priv->port_stats.oversized_packets += priv->tx_ring[i]->oversized_packets;
}
/* RX Statistics */
priv->pkstats.rx_packets = be64_to_cpu(mlx4_en_stats->RTOT_prio_0) +
@@ -546,8 +547,9 @@
}
if (!mlx4_is_mfunc(mdev->dev)) {
+/* netdevice stats format */
+#if __FreeBSD_version >= 1100000
if (reset == 0) {
- /* netdevice stats format */
dev = mdev->pndev[port];
if_inc_counter(dev, IFCOUNTER_IPACKETS,
priv->pkstats.rx_packets - priv->pkstats_last.rx_packets);
@@ -567,6 +569,18 @@
priv->pkstats.tx_multicast_packets - priv->pkstats_last.tx_multicast_packets);
}
priv->pkstats_last = priv->pkstats;
+#else
+ dev = mdev->pndev[port];
+ dev->if_ipackets = priv->pkstats.rx_packets;
+ dev->if_opackets = priv->pkstats.tx_packets;
+ dev->if_ibytes = priv->pkstats.rx_bytes;
+ dev->if_obytes = priv->pkstats.tx_bytes;
+ dev->if_ierrors = priv->pkstats.rx_errors;
+ dev->if_iqdrops = priv->pkstats.rx_dropped;
+ dev->if_imcasts = priv->pkstats.rx_multicast_packets;
+ dev->if_omcasts = priv->pkstats.tx_multicast_packets;
+ dev->if_collisions = 0;
+#endif
}
spin_unlock(&priv->stats_lock);
Index: head/sys/ofed/drivers/net/mlx4/en_rx.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_rx.c
+++ head/sys/ofed/drivers/net/mlx4/en_rx.c
@@ -49,7 +49,8 @@
struct mlx4_en_rx_ring *ring,
int index)
{
- struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index;
+ struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
+ (ring->buf + (ring->stride * index));
int possible_frags;
int i;
@@ -102,7 +103,8 @@
static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring, int index)
{
- struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
+ struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
+ (ring->buf + (index * ring->stride));
struct mbuf **mb_list = ring->rx_info + (index << priv->log_rx_info);
int i;
@@ -130,7 +132,8 @@
struct mlx4_en_frag_info *frag_info;
struct mlx4_en_dev *mdev = priv->mdev;
struct mbuf **mb_list;
- struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride);
+ struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
+ (ring->buf + (index << ring->log_stride));
dma_addr_t dma;
int nr;
@@ -574,7 +577,8 @@
while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
cons_index & size)) {
mb_list = ring->rx_info + (index << priv->log_rx_info);
- rx_desc = ring->buf + (index << ring->log_stride);
+ rx_desc = (struct mlx4_en_rx_desc *)
+ (ring->buf + (index << ring->log_stride));
/*
* make sure we read the CQE after we read the ownership bit
@@ -611,7 +615,8 @@
mb->m_pkthdr.ether_vtag = be16_to_cpu(cqe->sl_vid);
mb->m_flags |= M_VLANTAG;
}
- if (likely(dev->if_capabilities & IFCAP_RXCSUM) &&
+ if (likely(dev->if_capenable &
+ (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) &&
(cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
(cqe->checksum == cpu_to_be16(0xffff))) {
priv->port_stats.rx_chksum_good++;
@@ -692,6 +697,7 @@
// Because there is no NAPI in freeBSD
done = mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET);
if (priv->port_up && (done == MLX4_EN_RX_BUDGET) ) {
+ cq->curr_poll_rx_cpu_id = curcpu;
taskqueue_enqueue(cq->tq, &cq->cq_task);
}
else {
@@ -702,8 +708,15 @@
void mlx4_en_rx_que(void *context, int pending)
{
struct mlx4_en_cq *cq;
+ struct thread *td;
cq = context;
+ td = curthread;
+
+ thread_lock(td);
+ sched_bind(td, cq->curr_poll_rx_cpu_id);
+ thread_unlock(td);
+
while (mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET)
== MLX4_EN_RX_BUDGET);
mlx4_en_arm_cq(cq->dev->if_softc, cq);
@@ -841,8 +854,8 @@
else
rss_rings = priv->prof->rss_rings;
- ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
- + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
+ ptr = ((u8 *)&context) + offsetof(struct mlx4_qp_context, pri_path) +
+ MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
rss_context = ptr;
rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
(rss_map->base_qpn));
Index: head/sys/ofed/drivers/net/mlx4/en_selftest.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_selftest.c
+++ head/sys/ofed/drivers/net/mlx4/en_selftest.c
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/mlx4/driver.h>
-
-#include "mlx4_en.h"
-
-
-static int mlx4_en_test_registers(struct mlx4_en_priv *priv)
-{
- return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
-{
- struct sk_buff *skb;
- struct ethhdr *ethh;
- unsigned char *packet;
- unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;
- unsigned int i;
- int err;
-
-
- /* build the pkt before xmit */
- skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
- if (!skb) {
- en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
- return -ENOMEM;
- }
- skb_reserve(skb, NET_IP_ALIGN);
-
- ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
- packet = (unsigned char *)skb_put(skb, packet_size);
- memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
- memset(ethh->h_source, 0, ETH_ALEN);
- ethh->h_proto = htons(ETH_P_ARP);
- skb_set_mac_header(skb, 0);
- for (i = 0; i < packet_size; ++i) /* fill our packet */
- packet[i] = (unsigned char)(i & 0xff);
-
- /* xmit the pkt */
- err = mlx4_en_xmit(skb, priv->dev);
- return err;
-}
-
-static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
-{
- u32 loopback_ok = 0;
- int i;
-
-
- priv->loopback_ok = 0;
- priv->validate_loopback = 1;
-
- mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
-
- /* xmit */
- if (mlx4_en_test_loopback_xmit(priv)) {
- en_err(priv, "Transmitting loopback packet failed\n");
- goto mlx4_en_test_loopback_exit;
- }
-
- /* polling for result */
- for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) {
- msleep(MLX4_EN_LOOPBACK_TIMEOUT);
- if (priv->loopback_ok) {
- loopback_ok = 1;
- break;
- }
- }
- if (!loopback_ok)
- en_err(priv, "Loopback packet didn't arrive\n");
-
-mlx4_en_test_loopback_exit:
-
- priv->validate_loopback = 0;
- mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
- return !loopback_ok;
-}
-
-
-static int mlx4_en_test_link(struct mlx4_en_priv *priv)
-{
- if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
- return -ENOMEM;
- if (priv->port_state.link_state == 1)
- return 0;
- else
- return 1;
-}
-
-static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
-{
-
- if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
- return -ENOMEM;
-
- /* The device supports 1G, 10G and 40G speed */
- if (priv->port_state.link_speed != MLX4_EN_LINK_SPEED_1G &&
- priv->port_state.link_speed != MLX4_EN_LINK_SPEED_10G &&
- priv->port_state.link_speed != MLX4_EN_LINK_SPEED_40G)
- return priv->port_state.link_speed;
- return 0;
-}
-
-
-void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int i, carrier_ok;
-
- memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
-
- if (*flags & ETH_TEST_FL_OFFLINE) {
- /* disable the interface */
- carrier_ok = netif_carrier_ok(dev);
-
- netif_carrier_off(dev);
- /* Wait until all tx queues are empty.
- * there should not be any additional incoming traffic
- * since we turned the carrier off */
- msleep(200);
-
- if (priv->mdev->dev->caps.flags &
- MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
- buf[3] = mlx4_en_test_registers(priv);
- if (priv->port_up)
- buf[4] = mlx4_en_test_loopback(priv);
- }
-
- if (carrier_ok)
- netif_carrier_on(dev);
-
- }
- buf[0] = mlx4_test_interrupts(mdev->dev);
- buf[1] = mlx4_en_test_link(priv);
- buf[2] = mlx4_en_test_speed(priv);
-
- for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) {
- if (buf[i])
- *flags |= ETH_TEST_FL_FAILED;
- }
-}
Index: head/sys/ofed/drivers/net/mlx4/en_tx.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/en_tx.c
+++ head/sys/ofed/drivers/net/mlx4/en_tx.c
@@ -249,7 +249,8 @@
int index, u8 owner)
{
struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
- struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
+ struct mlx4_en_tx_desc *tx_desc = (struct mlx4_en_tx_desc *)
+ (ring->buf + index * TXBB_SIZE);
void *end = ring->buf + ring->buf_size;
__be32 *ptr = (__be32 *)tx_desc;
__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
@@ -268,7 +269,7 @@
*ptr = stamp;
ptr += STAMP_DWORDS;
if ((void *)ptr >= end) {
- ptr = ring->buf;
+ ptr = (__be32 *)ring->buf;
stamp ^= cpu_to_be32(0x80000000);
}
}
@@ -280,7 +281,8 @@
{
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
- struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
+ struct mlx4_en_tx_desc *tx_desc = (struct mlx4_en_tx_desc *)
+ (ring->buf + index * TXBB_SIZE);
struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset;
struct mbuf *mb = tx_info->mb;
void *end = ring->buf + ring->buf_size;
@@ -307,7 +309,8 @@
} else {
if (!tx_info->inl) {
if ((void *) data >= end) {
- data = ring->buf + ((void *)data - end);
+ data = (struct mlx4_wqe_data_seg *)
+ (ring->buf + ((void *)data - end));
}
if (tx_info->linear) {
@@ -321,7 +324,7 @@
for (i = 0; i < frags; i++) {
/* Check for wraparound before unmapping */
if ((void *) data >= end)
- data = ring->buf;
+ data = (struct mlx4_wqe_data_seg *)ring->buf;
pci_unmap_single(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
data->byte_count, PCI_DMA_TODEVICE);
@@ -522,7 +525,7 @@
}
/* Return real descriptor location */
- return ring->buf + index * TXBB_SIZE;
+ return (struct mlx4_en_tx_desc *)(ring->buf + index * TXBB_SIZE);
}
static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
@@ -723,18 +726,14 @@
up = (vlan_tag >> 13) % MLX4_EN_NUM_UP;
}
#endif
- /* check if flowid is set */
- if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE)
- queue_index = mb->m_pkthdr.flowid;
- else
- queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom);
+ queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom);
return ((queue_index % rings_p_up) + (up * rings_p_up));
}
-static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
+static void mlx4_bf_copy(void __iomem *dst, volatile unsigned long *src, unsigned bytecnt)
{
- __iowrite64_copy(dst, src, bytecnt / 8);
+ __iowrite64_copy(dst, __DEVOLATILE(void *, src), bytecnt / 8);
}
static u64 mlx4_en_mac_to_u64(u8 *addr)
@@ -843,7 +842,7 @@
/* See if we have enough space for whole descriptor TXBB for setting
* SW ownership on next descriptor; if not, use a bounce buffer. */
if (likely(index + nr_txbb <= ring_size))
- tx_desc = ring->buf + index * TXBB_SIZE;
+ tx_desc = (struct mlx4_en_tx_desc *)(ring->buf + index * TXBB_SIZE);
else {
tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
bounce = true;
@@ -1018,10 +1017,13 @@
}
enqueued = 0;
- if (m != NULL) {
- if ((err = drbr_enqueue(dev, ring->br, m)) != 0)
- return (err);
- }
+ if (m != NULL)
+ /*
+ * If we can't insert mbuf into drbr, try to xmit anyway.
+ * We keep the error we got so we could return that after xmit.
+ */
+ err = drbr_enqueue(dev, ring->br, m);
+
/* Process the queue */
while ((next = drbr_peek(dev, ring->br)) != NULL) {
if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) {
@@ -1075,10 +1077,14 @@
int i, err = 0;
/* Compute which queue to use */
- i = mlx4_en_select_queue(dev, m);
+ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
+ i = m->m_pkthdr.flowid % priv->tx_ring_num;
+ }
+ else {
+ i = mlx4_en_select_queue(dev, m);
+ }
ring = priv->tx_ring[i];
-
if (spin_trylock(&ring->tx_lock)) {
err = mlx4_en_transmit_locked(dev, i, m);
spin_unlock(&ring->tx_lock);
Index: head/sys/ofed/drivers/net/mlx4/main.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/main.c
+++ head/sys/ofed/drivers/net/mlx4/main.c
@@ -33,7 +33,7 @@
* SOFTWARE.
*/
-#include <linux/kmod.h>
+#include <linux/kmod.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -53,9 +53,7 @@
#include "icm.h"
#include "mlx4_stats.h"
-MODULE_AUTHOR("Roland Dreier");
-MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver");
-MODULE_LICENSE("Dual BSD/GPL");
+/* Mellanox ConnectX HCA low-level driver */
struct workqueue_struct *mlx4_wq;
@@ -173,7 +171,7 @@
#define PF_CONTEXT_BEHAVIOUR_MASK MLX4_FUNC_CAP_64B_EQE_CQE
static char mlx4_version[] __devinitdata =
- DRV_NAME ": Mellanox ConnectX core driver v"
+ DRV_NAME ": Mellanox ConnectX VPI driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
static int log_num_mac = 7;
@@ -1295,6 +1293,43 @@
}
}
+static ssize_t
+show_board(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
+ board_attr);
+ struct mlx4_dev *mdev = info->dev;
+
+ return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN,
+ mdev->board_id);
+}
+
+static ssize_t
+show_hca(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
+ hca_attr);
+ struct mlx4_dev *mdev = info->dev;
+
+ return sprintf(buf, "MT%d\n", mdev->pdev->device);
+}
+
+static ssize_t
+show_firmware_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
+ firmware_attr);
+ struct mlx4_dev *mdev = info->dev;
+
+ return sprintf(buf, "%d.%d.%d\n", (int)(mdev->caps.fw_ver >> 32),
+ (int)(mdev->caps.fw_ver >> 16) & 0xffff,
+ (int)mdev->caps.fw_ver & 0xffff);
+}
+
static ssize_t show_port_ib_mtu(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -2937,6 +2972,30 @@
no_irq:
dev->caps.num_comp_vectors = 0;
dev->caps.comp_pool = 0;
+ return;
+}
+
+static void
+mlx4_init_hca_info(struct mlx4_dev *dev)
+{
+ struct mlx4_hca_info *info = &mlx4_priv(dev)->hca_info;
+
+ info->dev = dev;
+
+ info->firmware_attr = (struct device_attribute)__ATTR(fw_ver, S_IRUGO,
+ show_firmware_version, NULL);
+ if (device_create_file(&dev->pdev->dev, &info->firmware_attr))
+ mlx4_err(dev, "Failed to add file firmware version");
+
+ info->hca_attr = (struct device_attribute)__ATTR(hca, S_IRUGO, show_hca,
+ NULL);
+ if (device_create_file(&dev->pdev->dev, &info->hca_attr))
+ mlx4_err(dev, "Failed to add file hca type");
+
+ info->board_attr = (struct device_attribute)__ATTR(board_id, S_IRUGO,
+ show_board, NULL);
+ if (device_create_file(&dev->pdev->dev, &info->board_attr))
+ mlx4_err(dev, "Failed to add file board id type");
}
static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
@@ -2990,6 +3049,14 @@
return err;
}
+static void
+mlx4_cleanup_hca_info(struct mlx4_hca_info *info)
+{
+ device_remove_file(&info->dev->pdev->dev, &info->firmware_attr);
+ device_remove_file(&info->dev->pdev->dev, &info->board_attr);
+ device_remove_file(&info->dev->pdev->dev, &info->hca_attr);
+}
+
static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
{
if (info->port < 0)
@@ -3347,6 +3414,7 @@
goto err_steer;
mlx4_init_quotas(dev);
+ mlx4_init_hca_info(dev);
for (port = 1; port <= dev->caps.num_ports; port++) {
err = mlx4_init_port_info(dev, port);
@@ -3439,8 +3507,7 @@
static int __devinit mlx4_init_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- printk_once(KERN_INFO "%s", mlx4_version);
-
+ device_set_desc(pdev->dev.bsddev, mlx4_version);
return __mlx4_init_one(pdev, id->driver_data);
}
@@ -3460,6 +3527,7 @@
mlx4_stop_sense(dev);
mlx4_unregister_device(dev);
+ mlx4_cleanup_hca_info(&priv->hca_info);
for (p = 1; p <= dev->caps.num_ports; p++) {
mlx4_cleanup_port_info(&priv->port[p]);
mlx4_CLOSE_PORT(dev, p);
Index: head/sys/ofed/drivers/net/mlx4/mlx4.h
===================================================================
--- head/sys/ofed/drivers/net/mlx4/mlx4.h
+++ head/sys/ofed/drivers/net/mlx4/mlx4.h
@@ -51,7 +51,7 @@
#define DRV_NAME "mlx4_core"
#define PFX DRV_NAME ": "
-#define DRV_VERSION "2.1"
+#define DRV_VERSION "2.1.6"
#define DRV_RELDATE __DATE__
#define DRV_STACK_NAME "Linux-MLNX_OFED"
@@ -755,6 +755,13 @@
__be32 mcast;
};
+struct mlx4_hca_info {
+ struct mlx4_dev *dev;
+ struct device_attribute firmware_attr;
+ struct device_attribute hca_attr;
+ struct device_attribute board_attr;
+};
+
struct mlx4_port_info {
struct mlx4_dev *dev;
int port;
@@ -845,6 +852,7 @@
struct mlx4_uar driver_uar;
void __iomem *kar;
struct mlx4_port_info port[MLX4_MAX_PORTS + 1];
+ struct mlx4_hca_info hca_info;
struct mlx4_sense sense;
struct mutex port_mutex;
struct mlx4_msix_ctl msix_ctl;
Index: head/sys/ofed/drivers/net/mlx4/mlx4_en.h
===================================================================
--- head/sys/ofed/drivers/net/mlx4/mlx4_en.h
+++ head/sys/ofed/drivers/net/mlx4/mlx4_en.h
@@ -59,8 +59,6 @@
#include "mlx4_stats.h"
#define DRV_NAME "mlx4_en"
-#define DRV_VERSION "2.1"
-#define DRV_RELDATE __DATE__
#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
@@ -154,7 +152,7 @@
#define MLX4_EN_NUM_UP 1
#define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \
- MLX4_EN_NUM_UP)
+ MLX4_EN_NUM_UP)
#define MLX4_EN_DEF_TX_RING_SIZE 1024
#define MLX4_EN_DEF_RX_RING_SIZE 1024
@@ -265,9 +263,16 @@
#define MLX4_EN_USE_SRQ 0x01000000
-#define MLX4_EN_TX_BUDGET 64*4 //Compensate for no NAPI in freeBSD - might need some fine tunning in the future.
#define MLX4_EN_RX_BUDGET 64
+#define MLX4_EN_TX_MAX_DESC_SIZE 512 /* bytes */
+#define MLX4_EN_TX_MAX_MBUF_SIZE 65536 /* bytes */
+#define MLX4_EN_TX_MAX_PAYLOAD_SIZE 65536 /* bytes */
+#define MLX4_EN_TX_MAX_MBUF_FRAGS \
+ ((MLX4_EN_TX_MAX_DESC_SIZE - 128) / DS_SIZE_ALIGNMENT) /* units */
+#define MLX4_EN_TX_WQE_MAX_WQEBBS \
+ (MLX4_EN_TX_MAX_DESC_SIZE / TXBB_SIZE) /* units */
+
#define MLX4_EN_CX3_LOW_ID 0x1000
#define MLX4_EN_CX3_HIGH_ID 0x1005
@@ -282,7 +287,7 @@
u32 cons;
u32 buf_size;
u32 doorbell_qpn;
- void *buf;
+ u8 *buf;
u16 poll_cnt;
int blocked;
struct mlx4_en_tx_info *tx_info;
@@ -300,6 +305,7 @@
unsigned long packets;
unsigned long tx_csum;
unsigned long queue_stopped;
+ unsigned long oversized_packets;
unsigned long wake_queue;
struct mlx4_bf bf;
bool bf_enabled;
@@ -339,7 +345,7 @@
u32 rx_buf_size;
u32 rx_mb_size;
int qpn;
- void *buf;
+ u8 *buf;
void *rx_info;
unsigned long errors;
unsigned long bytes;
@@ -400,6 +406,7 @@
#define MLX4_EN_OPCODE_ERROR 0x1e
u32 tot_rx;
u32 tot_tx;
+ u32 curr_poll_rx_cpu_id;
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int state;
@@ -641,7 +648,6 @@
unsigned long last_ifq_jiffies;
u64 if_counters_rx_errors;
u64 if_counters_rx_no_buffer;
-
};
enum mlx4_en_wol {
Index: head/sys/ofed/drivers/net/mlx4/mlx4_stats.h
===================================================================
--- head/sys/ofed/drivers/net/mlx4/mlx4_stats.h
+++ head/sys/ofed/drivers/net/mlx4/mlx4_stats.h
@@ -124,6 +124,7 @@
unsigned long queue_stopped;
unsigned long wake_queue;
unsigned long tx_timeout;
+ unsigned long oversized_packets;
unsigned long rx_alloc_failed;
unsigned long rx_chksum_good;
unsigned long rx_chksum_none;
Index: head/sys/ofed/drivers/net/mlx4/port.c
===================================================================
--- head/sys/ofed/drivers/net/mlx4/port.c
+++ head/sys/ofed/drivers/net/mlx4/port.c
@@ -1145,12 +1145,17 @@
size = MODULE_INFO_MAX_READ;
inbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(inbox))
+ if (IS_ERR(inbox)) {
+ mlx4_err(dev,
+ "mlx4_alloc_cmd_mailbox returned with error(%lx)", PTR_ERR(inbox));
return PTR_ERR(inbox);
+ }
outbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(outbox)) {
mlx4_free_cmd_mailbox(dev, inbox);
+ mlx4_err(dev,
+ "mlx4_alloc_cmd_mailbox returned with error(%lx)", PTR_ERR(outbox));
return PTR_ERR(outbox);
}
Index: head/sys/ofed/include/linux/mlx4/cq.h
===================================================================
--- head/sys/ofed/include/linux/mlx4/cq.h
+++ head/sys/ofed/include/linux/mlx4/cq.h
@@ -139,7 +139,7 @@
};
static inline void mlx4_cq_arm(struct mlx4_cq *cq, u32 cmd,
- void __iomem *uar_page,
+ u8 __iomem *uar_page,
spinlock_t *doorbell_lock)
{
__be32 doorbell[2];
Index: head/sys/ofed/include/linux/mlx4/device.h
===================================================================
--- head/sys/ofed/include/linux/mlx4/device.h
+++ head/sys/ofed/include/linux/mlx4/device.h
@@ -413,6 +413,13 @@
#define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \
MLX4_EQ_PORT_INFO_MSTR_SM_LID_CHANGE_MASK)
+enum mlx4_module_id {
+ MLX4_MODULE_ID_SFP = 0x3,
+ MLX4_MODULE_ID_QSFP = 0xC,
+ MLX4_MODULE_ID_QSFP_PLUS = 0xD,
+ MLX4_MODULE_ID_QSFP28 = 0x11,
+};
+
static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
{
return (major << 32) | (minor << 16) | subminor;
Index: head/sys/ofed/include/linux/mlx4/qp.h
===================================================================
--- head/sys/ofed/include/linux/mlx4/qp.h
+++ head/sys/ofed/include/linux/mlx4/qp.h
@@ -39,6 +39,12 @@
#define MLX4_INVALID_LKEY 0x100
+#define DS_SIZE_ALIGNMENT 16
+
+#define SET_BYTE_COUNT(byte_count) cpu_to_be32(byte_count)
+#define SET_LSO_MSS(mss_hdr_size) cpu_to_be32(mss_hdr_size)
+#define DS_BYTE_COUNT_MASK cpu_to_be32(0x7fffffff)
+
enum ib_m_qp_attr_mask {
IB_M_EXT_CLASS_1 = 1 << 28,
IB_M_EXT_CLASS_2 = 1 << 29,
@@ -266,7 +272,9 @@
#define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232)
enum {
+ MLX4_WQE_CTRL_OWN = 1 << 31,
MLX4_WQE_CTRL_NEC = 1 << 29,
+ MLX4_WQE_CTRL_RR = 1 << 6,
MLX4_WQE_CTRL_FENCE = 1 << 6,
MLX4_WQE_CTRL_CQ_UPDATE = 3 << 2,
MLX4_WQE_CTRL_SOLICITED = 1 << 1,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 19, 6:56 PM (16 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33325523
Default Alt Text
D4283.diff (83 KB)
Attached To
Mode
D4283: mlx4/mlxen: update version to 2.1.6
Attached
Detach File
Event Timeline
Log In to Comment