2175 lines · c
1/*2 * Copyright (c) 2007 Mellanox Technologies. All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses. You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 * Redistribution and use in source and binary forms, with or11 * without modification, are permitted provided that the following12 * conditions are met:13 *14 * - Redistributions of source code must retain the above15 * copyright notice, this list of conditions and the following16 * disclaimer.17 *18 * - Redistributions in binary form must reproduce the above19 * copyright notice, this list of conditions and the following20 * disclaimer in the documentation and/or other materials21 * provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 *32 */33 34#include <linux/kernel.h>35#include <linux/ethtool.h>36#include <linux/netdevice.h>37#include <linux/mlx4/driver.h>38#include <linux/mlx4/device.h>39#include <linux/in.h>40#include <net/ip.h>41#include <linux/bitmap.h>42#include <linux/mii.h>43 44#include "mlx4_en.h"45#include "en_port.h"46 47#define EN_ETHTOOL_QP_ATTACH (1ull << 63)48#define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)49#define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff)50 51int mlx4_en_moderation_update(struct mlx4_en_priv *priv)52{53 int i, t;54 int err = 0;55 56 for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {57 for (i = 0; i < priv->tx_ring_num[t]; i++) {58 priv->tx_cq[t][i]->moder_cnt = priv->tx_frames;59 priv->tx_cq[t][i]->moder_time = priv->tx_usecs;60 if (priv->port_up) {61 err = mlx4_en_set_cq_moder(priv,62 priv->tx_cq[t][i]);63 if (err)64 return err;65 }66 }67 }68 69 if (priv->adaptive_rx_coal)70 return 0;71 72 for (i = 0; i < priv->rx_ring_num; i++) {73 priv->rx_cq[i]->moder_cnt = priv->rx_frames;74 priv->rx_cq[i]->moder_time = priv->rx_usecs;75 priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;76 if (priv->port_up) {77 err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);78 if (err)79 return err;80 }81 }82 83 return err;84}85 86static void87mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)88{89 struct mlx4_en_priv *priv = netdev_priv(dev);90 struct mlx4_en_dev *mdev = priv->mdev;91 92 strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));93 strscpy(drvinfo->version, DRV_VERSION,94 sizeof(drvinfo->version));95 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),96 "%d.%d.%d",97 (u16) (mdev->dev->caps.fw_ver >> 32),98 (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),99 (u16) (mdev->dev->caps.fw_ver & 0xffff));100 strscpy(drvinfo->bus_info, pci_name(mdev->dev->persist->pdev),101 sizeof(drvinfo->bus_info));102}103 104static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {105 "blueflame",106 "phv-bit"107};108 109static const char main_strings[][ETH_GSTRING_LEN] = {110 /* main statistics */111 "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",112 "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",113 "rx_length_errors", "rx_over_errors", "rx_crc_errors",114 "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",115 "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",116 "tx_heartbeat_errors", "tx_window_errors",117 118 /* port statistics */119 "tso_packets",120 "xmit_more",121 "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_pages",122 "rx_csum_good", "rx_csum_none", "rx_csum_complete", "tx_chksum_offload",123 124 /* pf statistics */125 "pf_rx_packets",126 "pf_rx_bytes",127 "pf_tx_packets",128 "pf_tx_bytes",129 130 /* priority flow control statistics rx */131 "rx_pause_prio_0", "rx_pause_duration_prio_0",132 "rx_pause_transition_prio_0",133 "rx_pause_prio_1", "rx_pause_duration_prio_1",134 "rx_pause_transition_prio_1",135 "rx_pause_prio_2", "rx_pause_duration_prio_2",136 "rx_pause_transition_prio_2",137 "rx_pause_prio_3", "rx_pause_duration_prio_3",138 "rx_pause_transition_prio_3",139 "rx_pause_prio_4", "rx_pause_duration_prio_4",140 "rx_pause_transition_prio_4",141 "rx_pause_prio_5", "rx_pause_duration_prio_5",142 "rx_pause_transition_prio_5",143 "rx_pause_prio_6", "rx_pause_duration_prio_6",144 "rx_pause_transition_prio_6",145 "rx_pause_prio_7", "rx_pause_duration_prio_7",146 "rx_pause_transition_prio_7",147 148 /* flow control statistics rx */149 "rx_pause", "rx_pause_duration", "rx_pause_transition",150 151 /* priority flow control statistics tx */152 "tx_pause_prio_0", "tx_pause_duration_prio_0",153 "tx_pause_transition_prio_0",154 "tx_pause_prio_1", "tx_pause_duration_prio_1",155 "tx_pause_transition_prio_1",156 "tx_pause_prio_2", "tx_pause_duration_prio_2",157 "tx_pause_transition_prio_2",158 "tx_pause_prio_3", "tx_pause_duration_prio_3",159 "tx_pause_transition_prio_3",160 "tx_pause_prio_4", "tx_pause_duration_prio_4",161 "tx_pause_transition_prio_4",162 "tx_pause_prio_5", "tx_pause_duration_prio_5",163 "tx_pause_transition_prio_5",164 "tx_pause_prio_6", "tx_pause_duration_prio_6",165 "tx_pause_transition_prio_6",166 "tx_pause_prio_7", "tx_pause_duration_prio_7",167 "tx_pause_transition_prio_7",168 169 /* flow control statistics tx */170 "tx_pause", "tx_pause_duration", "tx_pause_transition",171 172 /* packet statistics */173 "rx_multicast_packets",174 "rx_broadcast_packets",175 "rx_jabbers",176 "rx_in_range_length_error",177 "rx_out_range_length_error",178 "tx_multicast_packets",179 "tx_broadcast_packets",180 "rx_prio_0_packets", "rx_prio_0_bytes",181 "rx_prio_1_packets", "rx_prio_1_bytes",182 "rx_prio_2_packets", "rx_prio_2_bytes",183 "rx_prio_3_packets", "rx_prio_3_bytes",184 "rx_prio_4_packets", "rx_prio_4_bytes",185 "rx_prio_5_packets", "rx_prio_5_bytes",186 "rx_prio_6_packets", "rx_prio_6_bytes",187 "rx_prio_7_packets", "rx_prio_7_bytes",188 "rx_novlan_packets", "rx_novlan_bytes",189 "tx_prio_0_packets", "tx_prio_0_bytes",190 "tx_prio_1_packets", "tx_prio_1_bytes",191 "tx_prio_2_packets", "tx_prio_2_bytes",192 "tx_prio_3_packets", "tx_prio_3_bytes",193 "tx_prio_4_packets", "tx_prio_4_bytes",194 "tx_prio_5_packets", "tx_prio_5_bytes",195 "tx_prio_6_packets", "tx_prio_6_bytes",196 "tx_prio_7_packets", "tx_prio_7_bytes",197 "tx_novlan_packets", "tx_novlan_bytes",198 199 /* xdp statistics */200 "rx_xdp_drop",201 "rx_xdp_redirect",202 "rx_xdp_redirect_fail",203 "rx_xdp_tx",204 "rx_xdp_tx_full",205 206 /* phy statistics */207 "rx_packets_phy", "rx_bytes_phy",208 "tx_packets_phy", "tx_bytes_phy",209};210 211static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {212 "Interrupt Test",213 "Link Test",214 "Speed Test",215 "Register Test",216 "Loopback Test",217};218 219static u32 mlx4_en_get_msglevel(struct net_device *dev)220{221 return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;222}223 224static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)225{226 ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;227}228 229static void mlx4_en_get_wol(struct net_device *netdev,230 struct ethtool_wolinfo *wol)231{232 struct mlx4_en_priv *priv = netdev_priv(netdev);233 struct mlx4_caps *caps = &priv->mdev->dev->caps;234 int err = 0;235 u64 config = 0;236 u64 mask;237 238 if ((priv->port < 1) || (priv->port > 2)) {239 en_err(priv, "Failed to get WoL information\n");240 return;241 }242 243 mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :244 MLX4_DEV_CAP_FLAG_WOL_PORT2;245 246 if (!(caps->flags & mask)) {247 wol->supported = 0;248 wol->wolopts = 0;249 return;250 }251 252 if (caps->wol_port[priv->port])253 wol->supported = WAKE_MAGIC;254 else255 wol->supported = 0;256 257 err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);258 if (err) {259 en_err(priv, "Failed to get WoL information\n");260 return;261 }262 263 if ((config & MLX4_EN_WOL_ENABLED) && (config & MLX4_EN_WOL_MAGIC))264 wol->wolopts = WAKE_MAGIC;265 else266 wol->wolopts = 0;267}268 269static int mlx4_en_set_wol(struct net_device *netdev,270 struct ethtool_wolinfo *wol)271{272 struct mlx4_en_priv *priv = netdev_priv(netdev);273 u64 config = 0;274 int err = 0;275 u64 mask;276 277 if ((priv->port < 1) || (priv->port > 2))278 return -EOPNOTSUPP;279 280 mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :281 MLX4_DEV_CAP_FLAG_WOL_PORT2;282 283 if (!(priv->mdev->dev->caps.flags & mask))284 return -EOPNOTSUPP;285 286 if (wol->supported & ~WAKE_MAGIC)287 return -EINVAL;288 289 err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);290 if (err) {291 en_err(priv, "Failed to get WoL info, unable to modify\n");292 return err;293 }294 295 if (wol->wolopts & WAKE_MAGIC) {296 config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |297 MLX4_EN_WOL_MAGIC;298 } else {299 config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);300 config |= MLX4_EN_WOL_DO_MODIFY;301 }302 303 err = mlx4_wol_write(priv->mdev->dev, config, priv->port);304 if (err)305 en_err(priv, "Failed to set WoL information\n");306 307 return err;308}309 310struct bitmap_iterator {311 unsigned long *stats_bitmap;312 unsigned int count;313 unsigned int iterator;314 bool advance_array; /* if set, force no increments */315};316 317static inline void bitmap_iterator_init(struct bitmap_iterator *h,318 unsigned long *stats_bitmap,319 int count)320{321 h->iterator = 0;322 h->advance_array = !bitmap_empty(stats_bitmap, count);323 h->count = h->advance_array ? bitmap_weight(stats_bitmap, count)324 : count;325 h->stats_bitmap = stats_bitmap;326}327 328static inline int bitmap_iterator_test(struct bitmap_iterator *h)329{330 return !h->advance_array ? 1 : test_bit(h->iterator, h->stats_bitmap);331}332 333static inline int bitmap_iterator_inc(struct bitmap_iterator *h)334{335 return h->iterator++;336}337 338static inline unsigned int339bitmap_iterator_count(struct bitmap_iterator *h)340{341 return h->count;342}343 344static int mlx4_en_get_sset_count(struct net_device *dev, int sset)345{346 struct mlx4_en_priv *priv = netdev_priv(dev);347 struct bitmap_iterator it;348 349 bitmap_iterator_init(&it, priv->stats_bitmap.bitmap, NUM_ALL_STATS);350 351 switch (sset) {352 case ETH_SS_STATS:353 return bitmap_iterator_count(&it) +354 (priv->tx_ring_num[TX] * 2) +355 (priv->rx_ring_num * (3 + NUM_XDP_STATS));356 case ETH_SS_TEST:357 return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags358 & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;359 case ETH_SS_PRIV_FLAGS:360 return ARRAY_SIZE(mlx4_en_priv_flags);361 default:362 return -EOPNOTSUPP;363 }364}365 366static void mlx4_en_get_ethtool_stats(struct net_device *dev,367 struct ethtool_stats *stats, uint64_t *data)368{369 struct mlx4_en_priv *priv = netdev_priv(dev);370 int index = 0;371 int i;372 struct bitmap_iterator it;373 374 bitmap_iterator_init(&it, priv->stats_bitmap.bitmap, NUM_ALL_STATS);375 376 spin_lock_bh(&priv->stats_lock);377 378 mlx4_en_fold_software_stats(dev);379 380 for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))381 if (bitmap_iterator_test(&it))382 data[index++] = ((unsigned long *)&dev->stats)[i];383 384 for (i = 0; i < NUM_PORT_STATS; i++, bitmap_iterator_inc(&it))385 if (bitmap_iterator_test(&it))386 data[index++] = ((unsigned long *)&priv->port_stats)[i];387 388 for (i = 0; i < NUM_PF_STATS; i++, bitmap_iterator_inc(&it))389 if (bitmap_iterator_test(&it))390 data[index++] =391 ((unsigned long *)&priv->pf_stats)[i];392 393 for (i = 0; i < NUM_FLOW_PRIORITY_STATS_RX;394 i++, bitmap_iterator_inc(&it))395 if (bitmap_iterator_test(&it))396 data[index++] =397 ((u64 *)&priv->rx_priority_flowstats)[i];398 399 for (i = 0; i < NUM_FLOW_STATS_RX; i++, bitmap_iterator_inc(&it))400 if (bitmap_iterator_test(&it))401 data[index++] = ((u64 *)&priv->rx_flowstats)[i];402 403 for (i = 0; i < NUM_FLOW_PRIORITY_STATS_TX;404 i++, bitmap_iterator_inc(&it))405 if (bitmap_iterator_test(&it))406 data[index++] =407 ((u64 *)&priv->tx_priority_flowstats)[i];408 409 for (i = 0; i < NUM_FLOW_STATS_TX; i++, bitmap_iterator_inc(&it))410 if (bitmap_iterator_test(&it))411 data[index++] = ((u64 *)&priv->tx_flowstats)[i];412 413 for (i = 0; i < NUM_PKT_STATS; i++, bitmap_iterator_inc(&it))414 if (bitmap_iterator_test(&it))415 data[index++] = ((unsigned long *)&priv->pkstats)[i];416 417 for (i = 0; i < NUM_XDP_STATS; i++, bitmap_iterator_inc(&it))418 if (bitmap_iterator_test(&it))419 data[index++] = ((unsigned long *)&priv->xdp_stats)[i];420 421 for (i = 0; i < NUM_PHY_STATS; i++, bitmap_iterator_inc(&it))422 if (bitmap_iterator_test(&it))423 data[index++] = ((unsigned long *)&priv->phy_stats)[i];424 425 for (i = 0; i < priv->tx_ring_num[TX]; i++) {426 data[index++] = priv->tx_ring[TX][i]->packets;427 data[index++] = priv->tx_ring[TX][i]->bytes;428 }429 for (i = 0; i < priv->rx_ring_num; i++) {430 data[index++] = priv->rx_ring[i]->packets;431 data[index++] = priv->rx_ring[i]->bytes;432 data[index++] = priv->rx_ring[i]->dropped;433 data[index++] = priv->rx_ring[i]->xdp_drop;434 data[index++] = priv->rx_ring[i]->xdp_redirect;435 data[index++] = priv->rx_ring[i]->xdp_redirect_fail;436 data[index++] = priv->rx_ring[i]->xdp_tx;437 data[index++] = priv->rx_ring[i]->xdp_tx_full;438 }439 spin_unlock_bh(&priv->stats_lock);440 441}442 443static void mlx4_en_self_test(struct net_device *dev,444 struct ethtool_test *etest, u64 *buf)445{446 mlx4_en_ex_selftest(dev, &etest->flags, buf);447}448 449static void mlx4_en_get_strings(struct net_device *dev,450 uint32_t stringset, uint8_t *data)451{452 struct mlx4_en_priv *priv = netdev_priv(dev);453 int i, strings = 0;454 struct bitmap_iterator it;455 456 bitmap_iterator_init(&it, priv->stats_bitmap.bitmap, NUM_ALL_STATS);457 458 switch (stringset) {459 case ETH_SS_TEST:460 for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)461 ethtool_puts(&data, mlx4_en_test_names[i]);462 if (priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK)463 for (; i < MLX4_EN_NUM_SELF_TEST; i++)464 ethtool_puts(&data, mlx4_en_test_names[i]);465 break;466 467 case ETH_SS_STATS:468 /* Add main counters */469 for (i = 0; i < NUM_MAIN_STATS; i++, strings++,470 bitmap_iterator_inc(&it))471 if (bitmap_iterator_test(&it))472 ethtool_puts(&data, main_strings[strings]);473 474 for (i = 0; i < NUM_PORT_STATS; i++, strings++,475 bitmap_iterator_inc(&it))476 if (bitmap_iterator_test(&it))477 ethtool_puts(&data, main_strings[strings]);478 479 for (i = 0; i < NUM_PF_STATS; i++, strings++,480 bitmap_iterator_inc(&it))481 if (bitmap_iterator_test(&it))482 ethtool_puts(&data, main_strings[strings]);483 484 for (i = 0; i < NUM_FLOW_STATS; i++, strings++,485 bitmap_iterator_inc(&it))486 if (bitmap_iterator_test(&it))487 ethtool_puts(&data, main_strings[strings]);488 489 for (i = 0; i < NUM_PKT_STATS; i++, strings++,490 bitmap_iterator_inc(&it))491 if (bitmap_iterator_test(&it))492 ethtool_puts(&data, main_strings[strings]);493 494 for (i = 0; i < NUM_XDP_STATS; i++, strings++,495 bitmap_iterator_inc(&it))496 if (bitmap_iterator_test(&it))497 ethtool_puts(&data, main_strings[strings]);498 499 for (i = 0; i < NUM_PHY_STATS; i++, strings++,500 bitmap_iterator_inc(&it))501 if (bitmap_iterator_test(&it))502 ethtool_puts(&data, main_strings[strings]);503 504 for (i = 0; i < priv->tx_ring_num[TX]; i++) {505 ethtool_sprintf(&data, "tx%d_packets", i);506 ethtool_sprintf(&data, "tx%d_bytes", i);507 }508 for (i = 0; i < priv->rx_ring_num; i++) {509 ethtool_sprintf(&data, "rx%d_packets", i);510 ethtool_sprintf(&data, "rx%d_bytes", i);511 ethtool_sprintf(&data, "rx%d_dropped", i);512 ethtool_sprintf(&data, "rx%d_xdp_drop", i);513 ethtool_sprintf(&data, "rx%d_xdp_redirect", i);514 ethtool_sprintf(&data, "rx%d_xdp_redirect_fail", i);515 ethtool_sprintf(&data, "rx%d_xdp_tx", i);516 ethtool_sprintf(&data, "rx%d_xdp_tx_full", i);517 }518 break;519 case ETH_SS_PRIV_FLAGS:520 for (i = 0; i < ARRAY_SIZE(mlx4_en_priv_flags); i++)521 ethtool_puts(&data, mlx4_en_priv_flags[i]);522 break;523 524 }525}526 527static u32 mlx4_en_autoneg_get(struct net_device *dev)528{529 struct mlx4_en_priv *priv = netdev_priv(dev);530 struct mlx4_en_dev *mdev = priv->mdev;531 u32 autoneg = AUTONEG_DISABLE;532 533 if ((mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP) &&534 (priv->port_state.flags & MLX4_EN_PORT_ANE))535 autoneg = AUTONEG_ENABLE;536 537 return autoneg;538}539 540static void ptys2ethtool_update_supported_port(unsigned long *mask,541 struct mlx4_ptys_reg *ptys_reg)542{543 u32 eth_proto = be32_to_cpu(ptys_reg->eth_proto_cap);544 545 if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_T)546 | MLX4_PROT_MASK(MLX4_1000BASE_T)547 | MLX4_PROT_MASK(MLX4_100BASE_TX))) {548 __set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask);549 } else if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_CR)550 | MLX4_PROT_MASK(MLX4_10GBASE_SR)551 | MLX4_PROT_MASK(MLX4_56GBASE_SR4)552 | MLX4_PROT_MASK(MLX4_40GBASE_CR4)553 | MLX4_PROT_MASK(MLX4_40GBASE_SR4)554 | MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII))) {555 __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, mask);556 } else if (eth_proto & (MLX4_PROT_MASK(MLX4_56GBASE_KR4)557 | MLX4_PROT_MASK(MLX4_40GBASE_KR4)558 | MLX4_PROT_MASK(MLX4_20GBASE_KR2)559 | MLX4_PROT_MASK(MLX4_10GBASE_KR)560 | MLX4_PROT_MASK(MLX4_10GBASE_KX4)561 | MLX4_PROT_MASK(MLX4_1000BASE_KX))) {562 __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, mask);563 }564}565 566static u32 ptys_get_active_port(struct mlx4_ptys_reg *ptys_reg)567{568 u32 eth_proto = be32_to_cpu(ptys_reg->eth_proto_oper);569 570 if (!eth_proto) /* link down */571 eth_proto = be32_to_cpu(ptys_reg->eth_proto_cap);572 573 if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_T)574 | MLX4_PROT_MASK(MLX4_1000BASE_T)575 | MLX4_PROT_MASK(MLX4_100BASE_TX))) {576 return PORT_TP;577 }578 579 if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_SR)580 | MLX4_PROT_MASK(MLX4_56GBASE_SR4)581 | MLX4_PROT_MASK(MLX4_40GBASE_SR4)582 | MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII))) {583 return PORT_FIBRE;584 }585 586 if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_CR)587 | MLX4_PROT_MASK(MLX4_56GBASE_CR4)588 | MLX4_PROT_MASK(MLX4_40GBASE_CR4))) {589 return PORT_DA;590 }591 592 if (eth_proto & (MLX4_PROT_MASK(MLX4_56GBASE_KR4)593 | MLX4_PROT_MASK(MLX4_40GBASE_KR4)594 | MLX4_PROT_MASK(MLX4_20GBASE_KR2)595 | MLX4_PROT_MASK(MLX4_10GBASE_KR)596 | MLX4_PROT_MASK(MLX4_10GBASE_KX4)597 | MLX4_PROT_MASK(MLX4_1000BASE_KX))) {598 return PORT_NONE;599 }600 return PORT_OTHER;601}602 603#define MLX4_LINK_MODES_SZ \604 (sizeof_field(struct mlx4_ptys_reg, eth_proto_cap) * 8)605 606enum ethtool_report {607 SUPPORTED = 0,608 ADVERTISED = 1,609};610 611struct ptys2ethtool_config {612 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);613 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);614 u32 speed;615};616 617static unsigned long *ptys2ethtool_link_mode(struct ptys2ethtool_config *cfg,618 enum ethtool_report report)619{620 switch (report) {621 case SUPPORTED:622 return cfg->supported;623 case ADVERTISED:624 return cfg->advertised;625 }626 return NULL;627}628 629#define MLX4_BUILD_PTYS2ETHTOOL_CONFIG(reg_, speed_, ...) \630 ({ \631 struct ptys2ethtool_config *cfg; \632 static const unsigned int modes[] = { __VA_ARGS__ }; \633 unsigned int i; \634 cfg = &ptys2ethtool_map[reg_]; \635 cfg->speed = speed_; \636 linkmode_zero(cfg->supported); \637 linkmode_zero(cfg->advertised); \638 for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \639 __set_bit(modes[i], cfg->supported); \640 __set_bit(modes[i], cfg->advertised); \641 } \642 })643 644/* Translates mlx4 link mode to equivalent ethtool Link modes/speed */645static struct ptys2ethtool_config ptys2ethtool_map[MLX4_LINK_MODES_SZ];646 647void __init mlx4_en_init_ptys2ethtool_map(void)648{649 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_100BASE_TX, SPEED_100,650 ETHTOOL_LINK_MODE_100baseT_Full_BIT);651 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000,652 ETHTOOL_LINK_MODE_1000baseT_Full_BIT);653 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000,654 ETHTOOL_LINK_MODE_1000baseX_Full_BIT);655 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000,656 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);657 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000,658 ETHTOOL_LINK_MODE_10000baseT_Full_BIT);659 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CX4, SPEED_10000,660 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);661 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KX4, SPEED_10000,662 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT);663 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000,664 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);665 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000,666 ETHTOOL_LINK_MODE_10000baseCR_Full_BIT);667 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000,668 ETHTOOL_LINK_MODE_10000baseSR_Full_BIT);669 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000,670 ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,671 ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT);672 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_40GBASE_CR4, SPEED_40000,673 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT);674 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_40GBASE_KR4, SPEED_40000,675 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT);676 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_40GBASE_SR4, SPEED_40000,677 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT);678 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_56GBASE_KR4, SPEED_56000,679 ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT);680 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_56GBASE_CR4, SPEED_56000,681 ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT);682 MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_56GBASE_SR4, SPEED_56000,683 ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT);684};685 686static void ptys2ethtool_update_link_modes(unsigned long *link_modes,687 u32 eth_proto,688 enum ethtool_report report)689{690 int i;691 for (i = 0; i < MLX4_LINK_MODES_SZ; i++) {692 if (eth_proto & MLX4_PROT_MASK(i))693 linkmode_or(link_modes, link_modes,694 ptys2ethtool_link_mode(&ptys2ethtool_map[i], report));695 }696}697 698static u32 ethtool2ptys_link_modes(const unsigned long *link_modes,699 enum ethtool_report report)700{701 int i;702 u32 ptys_modes = 0;703 704 for (i = 0; i < MLX4_LINK_MODES_SZ; i++) {705 ulong *map_mode = ptys2ethtool_link_mode(&ptys2ethtool_map[i],706 report);707 if (linkmode_intersects(map_mode, link_modes))708 ptys_modes |= 1 << i;709 }710 return ptys_modes;711}712 713/* Convert actual speed (SPEED_XXX) to ptys link modes */714static u32 speed2ptys_link_modes(u32 speed)715{716 int i;717 u32 ptys_modes = 0;718 719 for (i = 0; i < MLX4_LINK_MODES_SZ; i++) {720 if (ptys2ethtool_map[i].speed == speed)721 ptys_modes |= 1 << i;722 }723 return ptys_modes;724}725 726static int727ethtool_get_ptys_link_ksettings(struct net_device *dev,728 struct ethtool_link_ksettings *link_ksettings)729{730 struct mlx4_en_priv *priv = netdev_priv(dev);731 struct mlx4_ptys_reg ptys_reg;732 u32 eth_proto;733 int ret;734 735 memset(&ptys_reg, 0, sizeof(ptys_reg));736 ptys_reg.local_port = priv->port;737 ptys_reg.proto_mask = MLX4_PTYS_EN;738 ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev,739 MLX4_ACCESS_REG_QUERY, &ptys_reg);740 if (ret) {741 en_warn(priv, "Failed to run mlx4_ACCESS_PTYS_REG status(%x)",742 ret);743 return ret;744 }745 en_dbg(DRV, priv, "ptys_reg.proto_mask %x\n",746 ptys_reg.proto_mask);747 en_dbg(DRV, priv, "ptys_reg.eth_proto_cap %x\n",748 be32_to_cpu(ptys_reg.eth_proto_cap));749 en_dbg(DRV, priv, "ptys_reg.eth_proto_admin %x\n",750 be32_to_cpu(ptys_reg.eth_proto_admin));751 en_dbg(DRV, priv, "ptys_reg.eth_proto_oper %x\n",752 be32_to_cpu(ptys_reg.eth_proto_oper));753 en_dbg(DRV, priv, "ptys_reg.eth_proto_lp_adv %x\n",754 be32_to_cpu(ptys_reg.eth_proto_lp_adv));755 756 /* reset supported/advertising masks */757 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);758 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);759 760 ptys2ethtool_update_supported_port(link_ksettings->link_modes.supported,761 &ptys_reg);762 763 eth_proto = be32_to_cpu(ptys_reg.eth_proto_cap);764 ptys2ethtool_update_link_modes(link_ksettings->link_modes.supported,765 eth_proto, SUPPORTED);766 767 eth_proto = be32_to_cpu(ptys_reg.eth_proto_admin);768 ptys2ethtool_update_link_modes(link_ksettings->link_modes.advertising,769 eth_proto, ADVERTISED);770 771 ethtool_link_ksettings_add_link_mode(link_ksettings, supported,772 Pause);773 ethtool_link_ksettings_add_link_mode(link_ksettings, supported,774 Asym_Pause);775 776 if (priv->prof->tx_pause)777 ethtool_link_ksettings_add_link_mode(link_ksettings,778 advertising, Pause);779 if (priv->prof->tx_pause ^ priv->prof->rx_pause)780 ethtool_link_ksettings_add_link_mode(link_ksettings,781 advertising, Asym_Pause);782 783 link_ksettings->base.port = ptys_get_active_port(&ptys_reg);784 785 if (mlx4_en_autoneg_get(dev)) {786 ethtool_link_ksettings_add_link_mode(link_ksettings,787 supported, Autoneg);788 ethtool_link_ksettings_add_link_mode(link_ksettings,789 advertising, Autoneg);790 }791 792 link_ksettings->base.autoneg793 = (priv->port_state.flags & MLX4_EN_PORT_ANC) ?794 AUTONEG_ENABLE : AUTONEG_DISABLE;795 796 eth_proto = be32_to_cpu(ptys_reg.eth_proto_lp_adv);797 798 ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising);799 ptys2ethtool_update_link_modes(800 link_ksettings->link_modes.lp_advertising,801 eth_proto, ADVERTISED);802 if (priv->port_state.flags & MLX4_EN_PORT_ANC)803 ethtool_link_ksettings_add_link_mode(link_ksettings,804 lp_advertising, Autoneg);805 806 link_ksettings->base.phy_address = 0;807 link_ksettings->base.mdio_support = 0;808 link_ksettings->base.eth_tp_mdix = ETH_TP_MDI_INVALID;809 link_ksettings->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;810 811 return ret;812}813 814static void815ethtool_get_default_link_ksettings(816 struct net_device *dev, struct ethtool_link_ksettings *link_ksettings)817{818 struct mlx4_en_priv *priv = netdev_priv(dev);819 int trans_type;820 821 link_ksettings->base.autoneg = AUTONEG_DISABLE;822 823 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);824 ethtool_link_ksettings_add_link_mode(link_ksettings, supported,825 10000baseT_Full);826 827 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);828 ethtool_link_ksettings_add_link_mode(link_ksettings, advertising,829 10000baseT_Full);830 831 trans_type = priv->port_state.transceiver;832 if (trans_type > 0 && trans_type <= 0xC) {833 link_ksettings->base.port = PORT_FIBRE;834 ethtool_link_ksettings_add_link_mode(link_ksettings,835 supported, FIBRE);836 ethtool_link_ksettings_add_link_mode(link_ksettings,837 advertising, FIBRE);838 } else if (trans_type == 0x80 || trans_type == 0) {839 link_ksettings->base.port = PORT_TP;840 ethtool_link_ksettings_add_link_mode(link_ksettings,841 supported, TP);842 ethtool_link_ksettings_add_link_mode(link_ksettings,843 advertising, TP);844 } else {845 link_ksettings->base.port = -1;846 }847}848 849static int850mlx4_en_get_link_ksettings(struct net_device *dev,851 struct ethtool_link_ksettings *link_ksettings)852{853 struct mlx4_en_priv *priv = netdev_priv(dev);854 int ret = -EINVAL;855 856 if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))857 return -ENOMEM;858 859 en_dbg(DRV, priv, "query port state.flags ANC(%x) ANE(%x)\n",860 priv->port_state.flags & MLX4_EN_PORT_ANC,861 priv->port_state.flags & MLX4_EN_PORT_ANE);862 863 if (priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL)864 ret = ethtool_get_ptys_link_ksettings(dev, link_ksettings);865 if (ret) /* ETH PROT CRTL is not supported or PTYS CMD failed */866 ethtool_get_default_link_ksettings(dev, link_ksettings);867 868 if (netif_carrier_ok(dev)) {869 link_ksettings->base.speed = priv->port_state.link_speed;870 link_ksettings->base.duplex = DUPLEX_FULL;871 } else {872 link_ksettings->base.speed = SPEED_UNKNOWN;873 link_ksettings->base.duplex = DUPLEX_UNKNOWN;874 }875 return 0;876}877 878/* Calculate PTYS admin according ethtool speed (SPEED_XXX) */879static __be32 speed_set_ptys_admin(struct mlx4_en_priv *priv, u32 speed,880 __be32 proto_cap)881{882 __be32 proto_admin = 0;883 884 if (!speed) { /* Speed = 0 ==> Reset Link modes */885 proto_admin = proto_cap;886 en_info(priv, "Speed was set to 0, Reset advertised Link Modes to default (%x)\n",887 be32_to_cpu(proto_cap));888 } else {889 u32 ptys_link_modes = speed2ptys_link_modes(speed);890 891 proto_admin = cpu_to_be32(ptys_link_modes) & proto_cap;892 en_info(priv, "Setting Speed to %d\n", speed);893 }894 return proto_admin;895}896 897static int898mlx4_en_set_link_ksettings(struct net_device *dev,899 const struct ethtool_link_ksettings *link_ksettings)900{901 struct mlx4_en_priv *priv = netdev_priv(dev);902 struct mlx4_ptys_reg ptys_reg;903 __be32 proto_admin;904 u8 cur_autoneg;905 int ret;906 907 u32 ptys_adv = ethtool2ptys_link_modes(908 link_ksettings->link_modes.advertising, ADVERTISED);909 const int speed = link_ksettings->base.speed;910 911 en_dbg(DRV, priv,912 "Set Speed=%d adv={%*pbl} autoneg=%d duplex=%d\n",913 speed, __ETHTOOL_LINK_MODE_MASK_NBITS,914 link_ksettings->link_modes.advertising,915 link_ksettings->base.autoneg,916 link_ksettings->base.duplex);917 918 if (!(priv->mdev->dev->caps.flags2 &919 MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL) ||920 (link_ksettings->base.duplex == DUPLEX_HALF))921 return -EINVAL;922 923 memset(&ptys_reg, 0, sizeof(ptys_reg));924 ptys_reg.local_port = priv->port;925 ptys_reg.proto_mask = MLX4_PTYS_EN;926 ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev,927 MLX4_ACCESS_REG_QUERY, &ptys_reg);928 if (ret) {929 en_warn(priv, "Failed to QUERY mlx4_ACCESS_PTYS_REG status(%x)\n",930 ret);931 return 0;932 }933 934 cur_autoneg = ptys_reg.flags & MLX4_PTYS_AN_DISABLE_ADMIN ?935 AUTONEG_DISABLE : AUTONEG_ENABLE;936 937 if (link_ksettings->base.autoneg == AUTONEG_DISABLE) {938 proto_admin = speed_set_ptys_admin(priv, speed,939 ptys_reg.eth_proto_cap);940 if ((be32_to_cpu(proto_admin) &941 (MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII) |942 MLX4_PROT_MASK(MLX4_1000BASE_KX))) &&943 (ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP))944 ptys_reg.flags |= MLX4_PTYS_AN_DISABLE_ADMIN;945 } else {946 proto_admin = cpu_to_be32(ptys_adv);947 ptys_reg.flags &= ~MLX4_PTYS_AN_DISABLE_ADMIN;948 }949 950 proto_admin &= ptys_reg.eth_proto_cap;951 if (!proto_admin) {952 en_warn(priv, "Not supported link mode(s) requested, check supported link modes.\n");953 return -EINVAL; /* nothing to change due to bad input */954 }955 956 if ((proto_admin == ptys_reg.eth_proto_admin) &&957 ((ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP) &&958 (link_ksettings->base.autoneg == cur_autoneg)))959 return 0; /* Nothing to change */960 961 en_dbg(DRV, priv, "mlx4_ACCESS_PTYS_REG SET: ptys_reg.eth_proto_admin = 0x%x\n",962 be32_to_cpu(proto_admin));963 964 ptys_reg.eth_proto_admin = proto_admin;965 ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev, MLX4_ACCESS_REG_WRITE,966 &ptys_reg);967 if (ret) {968 en_warn(priv, "Failed to write mlx4_ACCESS_PTYS_REG eth_proto_admin(0x%x) status(0x%x)",969 be32_to_cpu(ptys_reg.eth_proto_admin), ret);970 return ret;971 }972 973 mutex_lock(&priv->mdev->state_lock);974 if (priv->port_up) {975 en_warn(priv, "Port link mode changed, restarting port...\n");976 mlx4_en_stop_port(dev, 1);977 if (mlx4_en_start_port(dev))978 en_err(priv, "Failed restarting port %d\n", priv->port);979 }980 mutex_unlock(&priv->mdev->state_lock);981 return 0;982}983 984static int mlx4_en_get_coalesce(struct net_device *dev,985 struct ethtool_coalesce *coal,986 struct kernel_ethtool_coalesce *kernel_coal,987 struct netlink_ext_ack *extack)988{989 struct mlx4_en_priv *priv = netdev_priv(dev);990 991 coal->tx_coalesce_usecs = priv->tx_usecs;992 coal->tx_max_coalesced_frames = priv->tx_frames;993 coal->tx_max_coalesced_frames_irq = priv->tx_work_limit;994 995 coal->rx_coalesce_usecs = priv->rx_usecs;996 coal->rx_max_coalesced_frames = priv->rx_frames;997 998 coal->pkt_rate_low = priv->pkt_rate_low;999 coal->rx_coalesce_usecs_low = priv->rx_usecs_low;1000 coal->pkt_rate_high = priv->pkt_rate_high;1001 coal->rx_coalesce_usecs_high = priv->rx_usecs_high;1002 coal->rate_sample_interval = priv->sample_interval;1003 coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;1004 1005 return 0;1006}1007 1008static int mlx4_en_set_coalesce(struct net_device *dev,1009 struct ethtool_coalesce *coal,1010 struct kernel_ethtool_coalesce *kernel_coal,1011 struct netlink_ext_ack *extack)1012{1013 struct mlx4_en_priv *priv = netdev_priv(dev);1014 1015 if (!coal->tx_max_coalesced_frames_irq)1016 return -EINVAL;1017 1018 if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||1019 coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||1020 coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME ||1021 coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) {1022 netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n",1023 __func__, MLX4_EN_MAX_COAL_TIME);1024 return -ERANGE;1025 }1026 1027 if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS ||1028 coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) {1029 netdev_info(dev, "%s: maximum coalesced frames supported is %d\n",1030 __func__, MLX4_EN_MAX_COAL_PKTS);1031 return -ERANGE;1032 }1033 1034 priv->rx_frames = (coal->rx_max_coalesced_frames ==1035 MLX4_EN_AUTO_CONF) ?1036 MLX4_EN_RX_COAL_TARGET :1037 coal->rx_max_coalesced_frames;1038 priv->rx_usecs = (coal->rx_coalesce_usecs ==1039 MLX4_EN_AUTO_CONF) ?1040 MLX4_EN_RX_COAL_TIME :1041 coal->rx_coalesce_usecs;1042 1043 /* Setting TX coalescing parameters */1044 if (coal->tx_coalesce_usecs != priv->tx_usecs ||1045 coal->tx_max_coalesced_frames != priv->tx_frames) {1046 priv->tx_usecs = coal->tx_coalesce_usecs;1047 priv->tx_frames = coal->tx_max_coalesced_frames;1048 }1049 1050 /* Set adaptive coalescing params */1051 priv->pkt_rate_low = coal->pkt_rate_low;1052 priv->rx_usecs_low = coal->rx_coalesce_usecs_low;1053 priv->pkt_rate_high = coal->pkt_rate_high;1054 priv->rx_usecs_high = coal->rx_coalesce_usecs_high;1055 priv->sample_interval = coal->rate_sample_interval;1056 priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;1057 priv->tx_work_limit = coal->tx_max_coalesced_frames_irq;1058 1059 return mlx4_en_moderation_update(priv);1060}1061 1062static int mlx4_en_set_pauseparam(struct net_device *dev,1063 struct ethtool_pauseparam *pause)1064{1065 struct mlx4_en_priv *priv = netdev_priv(dev);1066 struct mlx4_en_dev *mdev = priv->mdev;1067 u8 tx_pause, tx_ppp, rx_pause, rx_ppp;1068 int err;1069 1070 if (pause->autoneg)1071 return -EINVAL;1072 1073 tx_pause = !!(pause->tx_pause);1074 rx_pause = !!(pause->rx_pause);1075 rx_ppp = (tx_pause || rx_pause) ? 0 : priv->prof->rx_ppp;1076 tx_ppp = (tx_pause || rx_pause) ? 0 : priv->prof->tx_ppp;1077 1078 err = mlx4_SET_PORT_general(mdev->dev, priv->port,1079 priv->rx_skb_size + ETH_FCS_LEN,1080 tx_pause, tx_ppp, rx_pause, rx_ppp);1081 if (err) {1082 en_err(priv, "Failed setting pause params, err = %d\n", err);1083 return err;1084 }1085 1086 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap,1087 rx_ppp, rx_pause, tx_ppp, tx_pause);1088 1089 priv->prof->tx_pause = tx_pause;1090 priv->prof->rx_pause = rx_pause;1091 priv->prof->tx_ppp = tx_ppp;1092 priv->prof->rx_ppp = rx_ppp;1093 1094 return err;1095}1096 1097static void mlx4_en_get_pause_stats(struct net_device *dev,1098 struct ethtool_pause_stats *stats)1099{1100 struct mlx4_en_priv *priv = netdev_priv(dev);1101 struct bitmap_iterator it;1102 1103 bitmap_iterator_init(&it, priv->stats_bitmap.bitmap, NUM_ALL_STATS);1104 1105 spin_lock_bh(&priv->stats_lock);1106 if (test_bit(FLOW_PRIORITY_STATS_IDX_TX_FRAMES,1107 priv->stats_bitmap.bitmap))1108 stats->tx_pause_frames = priv->tx_flowstats.tx_pause;1109 if (test_bit(FLOW_PRIORITY_STATS_IDX_RX_FRAMES,1110 priv->stats_bitmap.bitmap))1111 stats->rx_pause_frames = priv->rx_flowstats.rx_pause;1112 spin_unlock_bh(&priv->stats_lock);1113}1114 1115static void mlx4_en_get_pauseparam(struct net_device *dev,1116 struct ethtool_pauseparam *pause)1117{1118 struct mlx4_en_priv *priv = netdev_priv(dev);1119 1120 pause->tx_pause = priv->prof->tx_pause;1121 pause->rx_pause = priv->prof->rx_pause;1122}1123 1124static int mlx4_en_set_ringparam(struct net_device *dev,1125 struct ethtool_ringparam *param,1126 struct kernel_ethtool_ringparam *kernel_param,1127 struct netlink_ext_ack *extack)1128{1129 struct mlx4_en_priv *priv = netdev_priv(dev);1130 struct mlx4_en_dev *mdev = priv->mdev;1131 struct mlx4_en_port_profile new_prof;1132 struct mlx4_en_priv *tmp;1133 u32 rx_size, tx_size;1134 int port_up = 0;1135 int err = 0;1136 1137 if (param->rx_jumbo_pending || param->rx_mini_pending)1138 return -EINVAL;1139 1140 if (param->rx_pending < MLX4_EN_MIN_RX_SIZE) {1141 en_warn(priv, "%s: rx_pending (%d) < min (%d)\n",1142 __func__, param->rx_pending,1143 MLX4_EN_MIN_RX_SIZE);1144 return -EINVAL;1145 }1146 if (param->tx_pending < MLX4_EN_MIN_TX_SIZE) {1147 en_warn(priv, "%s: tx_pending (%d) < min (%lu)\n",1148 __func__, param->tx_pending,1149 MLX4_EN_MIN_TX_SIZE);1150 return -EINVAL;1151 }1152 1153 rx_size = roundup_pow_of_two(param->rx_pending);1154 tx_size = roundup_pow_of_two(param->tx_pending);1155 1156 if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :1157 priv->rx_ring[0]->size) &&1158 tx_size == priv->tx_ring[TX][0]->size)1159 return 0;1160 1161 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);1162 if (!tmp)1163 return -ENOMEM;1164 1165 mutex_lock(&mdev->state_lock);1166 memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));1167 new_prof.tx_ring_size = tx_size;1168 new_prof.rx_ring_size = rx_size;1169 err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);1170 if (err)1171 goto out;1172 1173 if (priv->port_up) {1174 port_up = 1;1175 mlx4_en_stop_port(dev, 1);1176 }1177 1178 mlx4_en_safe_replace_resources(priv, tmp);1179 1180 if (port_up) {1181 err = mlx4_en_start_port(dev);1182 if (err)1183 en_err(priv, "Failed starting port\n");1184 }1185 1186 err = mlx4_en_moderation_update(priv);1187out:1188 kfree(tmp);1189 mutex_unlock(&mdev->state_lock);1190 return err;1191}1192 1193static void mlx4_en_get_ringparam(struct net_device *dev,1194 struct ethtool_ringparam *param,1195 struct kernel_ethtool_ringparam *kernel_param,1196 struct netlink_ext_ack *extack)1197{1198 struct mlx4_en_priv *priv = netdev_priv(dev);1199 1200 memset(param, 0, sizeof(*param));1201 param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;1202 param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;1203 param->rx_pending = priv->port_up ?1204 priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;1205 param->tx_pending = priv->tx_ring[TX][0]->size;1206}1207 1208static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)1209{1210 struct mlx4_en_priv *priv = netdev_priv(dev);1211 1212 return rounddown_pow_of_two(priv->rx_ring_num);1213}1214 1215static u32 mlx4_en_get_rxfh_key_size(struct net_device *netdev)1216{1217 return MLX4_EN_RSS_KEY_SIZE;1218}1219 1220static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc)1221{1222 struct mlx4_en_priv *priv = netdev_priv(dev);1223 1224 /* check if requested function is supported by the device */1225 if (hfunc == ETH_RSS_HASH_TOP) {1226 if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP))1227 return -EINVAL;1228 if (!(dev->features & NETIF_F_RXHASH))1229 en_warn(priv, "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");1230 return 0;1231 } else if (hfunc == ETH_RSS_HASH_XOR) {1232 if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR))1233 return -EINVAL;1234 if (dev->features & NETIF_F_RXHASH)1235 en_warn(priv, "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");1236 return 0;1237 }1238 1239 return -EINVAL;1240}1241 1242static int mlx4_en_get_rxfh(struct net_device *dev,1243 struct ethtool_rxfh_param *rxfh)1244{1245 struct mlx4_en_priv *priv = netdev_priv(dev);1246 u32 n = mlx4_en_get_rxfh_indir_size(dev);1247 u32 i, rss_rings;1248 1249 rss_rings = priv->prof->rss_rings ?: n;1250 rss_rings = rounddown_pow_of_two(rss_rings);1251 1252 for (i = 0; i < n; i++) {1253 if (!rxfh->indir)1254 break;1255 rxfh->indir[i] = i % rss_rings;1256 }1257 if (rxfh->key)1258 memcpy(rxfh->key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE);1259 rxfh->hfunc = priv->rss_hash_fn;1260 return 0;1261}1262 1263static int mlx4_en_set_rxfh(struct net_device *dev,1264 struct ethtool_rxfh_param *rxfh,1265 struct netlink_ext_ack *extack)1266{1267 struct mlx4_en_priv *priv = netdev_priv(dev);1268 u32 n = mlx4_en_get_rxfh_indir_size(dev);1269 struct mlx4_en_dev *mdev = priv->mdev;1270 int port_up = 0;1271 int err = 0;1272 int i;1273 int rss_rings = 0;1274 1275 /* Calculate RSS table size and make sure flows are spread evenly1276 * between rings1277 */1278 for (i = 0; i < n; i++) {1279 if (!rxfh->indir)1280 break;1281 if (i > 0 && !rxfh->indir[i] && !rss_rings)1282 rss_rings = i;1283 1284 if (rxfh->indir[i] != (i % (rss_rings ?: n)))1285 return -EINVAL;1286 }1287 1288 if (!rss_rings)1289 rss_rings = n;1290 1291 /* RSS table size must be an order of 2 */1292 if (!is_power_of_2(rss_rings))1293 return -EINVAL;1294 1295 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE) {1296 err = mlx4_en_check_rxfh_func(dev, rxfh->hfunc);1297 if (err)1298 return err;1299 }1300 1301 mutex_lock(&mdev->state_lock);1302 if (priv->port_up) {1303 port_up = 1;1304 mlx4_en_stop_port(dev, 1);1305 }1306 1307 if (rxfh->indir)1308 priv->prof->rss_rings = rss_rings;1309 if (rxfh->key)1310 memcpy(priv->rss_key, rxfh->key, MLX4_EN_RSS_KEY_SIZE);1311 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE)1312 priv->rss_hash_fn = rxfh->hfunc;1313 1314 if (port_up) {1315 err = mlx4_en_start_port(dev);1316 if (err)1317 en_err(priv, "Failed starting port\n");1318 }1319 1320 mutex_unlock(&mdev->state_lock);1321 return err;1322}1323 1324#define all_zeros_or_all_ones(field) \1325 ((field) == 0 || (field) == (__force typeof(field))-1)1326 1327static int mlx4_en_validate_flow(struct net_device *dev,1328 struct ethtool_rxnfc *cmd)1329{1330 struct ethtool_usrip4_spec *l3_mask;1331 struct ethtool_tcpip4_spec *l4_mask;1332 struct ethhdr *eth_mask;1333 1334 if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)1335 return -EINVAL;1336 1337 if (cmd->fs.flow_type & FLOW_MAC_EXT) {1338 /* dest mac mask must be ff:ff:ff:ff:ff:ff */1339 if (!is_broadcast_ether_addr(cmd->fs.m_ext.h_dest))1340 return -EINVAL;1341 }1342 1343 switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {1344 case TCP_V4_FLOW:1345 case UDP_V4_FLOW:1346 if (cmd->fs.m_u.tcp_ip4_spec.tos)1347 return -EINVAL;1348 l4_mask = &cmd->fs.m_u.tcp_ip4_spec;1349 /* don't allow mask which isn't all 0 or 1 */1350 if (!all_zeros_or_all_ones(l4_mask->ip4src) ||1351 !all_zeros_or_all_ones(l4_mask->ip4dst) ||1352 !all_zeros_or_all_ones(l4_mask->psrc) ||1353 !all_zeros_or_all_ones(l4_mask->pdst))1354 return -EINVAL;1355 break;1356 case IP_USER_FLOW:1357 l3_mask = &cmd->fs.m_u.usr_ip4_spec;1358 if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto ||1359 cmd->fs.h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 ||1360 (!l3_mask->ip4src && !l3_mask->ip4dst) ||1361 !all_zeros_or_all_ones(l3_mask->ip4src) ||1362 !all_zeros_or_all_ones(l3_mask->ip4dst))1363 return -EINVAL;1364 break;1365 case ETHER_FLOW:1366 eth_mask = &cmd->fs.m_u.ether_spec;1367 /* source mac mask must not be set */1368 if (!is_zero_ether_addr(eth_mask->h_source))1369 return -EINVAL;1370 1371 /* dest mac mask must be ff:ff:ff:ff:ff:ff */1372 if (!is_broadcast_ether_addr(eth_mask->h_dest))1373 return -EINVAL;1374 1375 if (!all_zeros_or_all_ones(eth_mask->h_proto))1376 return -EINVAL;1377 break;1378 default:1379 return -EINVAL;1380 }1381 1382 if ((cmd->fs.flow_type & FLOW_EXT)) {1383 if (cmd->fs.m_ext.vlan_etype ||1384 !((cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) ==1385 0 ||1386 (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) ==1387 cpu_to_be16(VLAN_VID_MASK)))1388 return -EINVAL;1389 1390 if (cmd->fs.m_ext.vlan_tci) {1391 if (be16_to_cpu(cmd->fs.h_ext.vlan_tci) >= VLAN_N_VID)1392 return -EINVAL;1393 1394 }1395 }1396 1397 return 0;1398}1399 1400static int mlx4_en_ethtool_add_mac_rule(struct ethtool_rxnfc *cmd,1401 struct list_head *rule_list_h,1402 struct mlx4_spec_list *spec_l2,1403 unsigned char *mac)1404{1405 __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);1406 1407 spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH;1408 memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN);1409 memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN);1410 1411 if ((cmd->fs.flow_type & FLOW_EXT) &&1412 (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK))) {1413 spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci;1414 spec_l2->eth.vlan_id_msk = cpu_to_be16(VLAN_VID_MASK);1415 }1416 1417 list_add_tail(&spec_l2->list, rule_list_h);1418 1419 return 0;1420}1421 1422static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv,1423 struct ethtool_rxnfc *cmd,1424 struct list_head *rule_list_h,1425 struct mlx4_spec_list *spec_l2,1426 __be32 ipv4_dst)1427{1428#ifdef CONFIG_INET1429 unsigned char mac[ETH_ALEN];1430 1431 if (!ipv4_is_multicast(ipv4_dst)) {1432 if (cmd->fs.flow_type & FLOW_MAC_EXT)1433 memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN);1434 else1435 memcpy(&mac, priv->dev->dev_addr, ETH_ALEN);1436 } else {1437 ip_eth_mc_map(ipv4_dst, mac);1438 }1439 1440 return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]);1441#else1442 return -EINVAL;1443#endif1444}1445 1446static int add_ip_rule(struct mlx4_en_priv *priv,1447 struct ethtool_rxnfc *cmd,1448 struct list_head *list_h)1449{1450 int err;1451 struct mlx4_spec_list *spec_l2;1452 struct mlx4_spec_list *spec_l3;1453 struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec;1454 1455 spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);1456 spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);1457 if (!spec_l2 || !spec_l3) {1458 err = -ENOMEM;1459 goto free_spec;1460 }1461 1462 err = mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2,1463 cmd->fs.h_u.1464 usr_ip4_spec.ip4dst);1465 if (err)1466 goto free_spec;1467 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;1468 spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src;1469 if (l3_mask->ip4src)1470 spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK;1471 spec_l3->ipv4.dst_ip = cmd->fs.h_u.usr_ip4_spec.ip4dst;1472 if (l3_mask->ip4dst)1473 spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK;1474 list_add_tail(&spec_l3->list, list_h);1475 1476 return 0;1477 1478free_spec:1479 kfree(spec_l2);1480 kfree(spec_l3);1481 return err;1482}1483 1484static int add_tcp_udp_rule(struct mlx4_en_priv *priv,1485 struct ethtool_rxnfc *cmd,1486 struct list_head *list_h, int proto)1487{1488 int err;1489 struct mlx4_spec_list *spec_l2;1490 struct mlx4_spec_list *spec_l3;1491 struct mlx4_spec_list *spec_l4;1492 struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec;1493 1494 spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);1495 spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);1496 spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL);1497 if (!spec_l2 || !spec_l3 || !spec_l4) {1498 err = -ENOMEM;1499 goto free_spec;1500 }1501 1502 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;1503 1504 if (proto == TCP_V4_FLOW) {1505 err = mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,1506 spec_l2,1507 cmd->fs.h_u.1508 tcp_ip4_spec.ip4dst);1509 if (err)1510 goto free_spec;1511 spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP;1512 spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src;1513 spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst;1514 spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc;1515 spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst;1516 } else {1517 err = mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,1518 spec_l2,1519 cmd->fs.h_u.1520 udp_ip4_spec.ip4dst);1521 if (err)1522 goto free_spec;1523 spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP;1524 spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src;1525 spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst;1526 spec_l4->tcp_udp.src_port = cmd->fs.h_u.udp_ip4_spec.psrc;1527 spec_l4->tcp_udp.dst_port = cmd->fs.h_u.udp_ip4_spec.pdst;1528 }1529 1530 if (l4_mask->ip4src)1531 spec_l3->ipv4.src_ip_msk = EN_ETHTOOL_WORD_MASK;1532 if (l4_mask->ip4dst)1533 spec_l3->ipv4.dst_ip_msk = EN_ETHTOOL_WORD_MASK;1534 1535 if (l4_mask->psrc)1536 spec_l4->tcp_udp.src_port_msk = EN_ETHTOOL_SHORT_MASK;1537 if (l4_mask->pdst)1538 spec_l4->tcp_udp.dst_port_msk = EN_ETHTOOL_SHORT_MASK;1539 1540 list_add_tail(&spec_l3->list, list_h);1541 list_add_tail(&spec_l4->list, list_h);1542 1543 return 0;1544 1545free_spec:1546 kfree(spec_l2);1547 kfree(spec_l3);1548 kfree(spec_l4);1549 return err;1550}1551 1552static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,1553 struct ethtool_rxnfc *cmd,1554 struct list_head *rule_list_h)1555{1556 int err;1557 struct ethhdr *eth_spec;1558 struct mlx4_spec_list *spec_l2;1559 struct mlx4_en_priv *priv = netdev_priv(dev);1560 1561 err = mlx4_en_validate_flow(dev, cmd);1562 if (err)1563 return err;1564 1565 switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {1566 case ETHER_FLOW:1567 spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);1568 if (!spec_l2)1569 return -ENOMEM;1570 1571 eth_spec = &cmd->fs.h_u.ether_spec;1572 mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2,1573 ð_spec->h_dest[0]);1574 spec_l2->eth.ether_type = eth_spec->h_proto;1575 if (eth_spec->h_proto)1576 spec_l2->eth.ether_type_enable = 1;1577 break;1578 case IP_USER_FLOW:1579 err = add_ip_rule(priv, cmd, rule_list_h);1580 break;1581 case TCP_V4_FLOW:1582 err = add_tcp_udp_rule(priv, cmd, rule_list_h, TCP_V4_FLOW);1583 break;1584 case UDP_V4_FLOW:1585 err = add_tcp_udp_rule(priv, cmd, rule_list_h, UDP_V4_FLOW);1586 break;1587 }1588 1589 return err;1590}1591 1592static int mlx4_en_flow_replace(struct net_device *dev,1593 struct ethtool_rxnfc *cmd)1594{1595 int err;1596 struct mlx4_en_priv *priv = netdev_priv(dev);1597 struct ethtool_flow_id *loc_rule;1598 struct mlx4_spec_list *spec, *tmp_spec;1599 u32 qpn;1600 u64 reg_id;1601 1602 struct mlx4_net_trans_rule rule = {1603 .queue_mode = MLX4_NET_TRANS_Q_FIFO,1604 .exclusive = 0,1605 .allow_loopback = 1,1606 .promisc_mode = MLX4_FS_REGULAR,1607 };1608 1609 rule.port = priv->port;1610 rule.priority = MLX4_DOMAIN_ETHTOOL | cmd->fs.location;1611 INIT_LIST_HEAD(&rule.list);1612 1613 /* Allow direct QP attaches if the EN_ETHTOOL_QP_ATTACH flag is set */1614 if (cmd->fs.ring_cookie == RX_CLS_FLOW_DISC)1615 qpn = priv->drop_qp.qpn;1616 else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {1617 qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);1618 } else {1619 if (cmd->fs.ring_cookie >= priv->rx_ring_num) {1620 en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n",1621 cmd->fs.ring_cookie);1622 return -EINVAL;1623 }1624 qpn = priv->rss_map.qps[cmd->fs.ring_cookie].qpn;1625 if (!qpn) {1626 en_warn(priv, "rxnfc: RX ring (%llu) is inactive\n",1627 cmd->fs.ring_cookie);1628 return -EINVAL;1629 }1630 }1631 rule.qpn = qpn;1632 err = mlx4_en_ethtool_to_net_trans_rule(dev, cmd, &rule.list);1633 if (err)1634 goto out_free_list;1635 1636 loc_rule = &priv->ethtool_rules[cmd->fs.location];1637 if (loc_rule->id) {1638 err = mlx4_flow_detach(priv->mdev->dev, loc_rule->id);1639 if (err) {1640 en_err(priv, "Fail to detach network rule at location %d. registration id = %llx\n",1641 cmd->fs.location, loc_rule->id);1642 goto out_free_list;1643 }1644 loc_rule->id = 0;1645 memset(&loc_rule->flow_spec, 0,1646 sizeof(struct ethtool_rx_flow_spec));1647 list_del(&loc_rule->list);1648 }1649 err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id);1650 if (err) {1651 en_err(priv, "Fail to attach network rule at location %d\n",1652 cmd->fs.location);1653 goto out_free_list;1654 }1655 loc_rule->id = reg_id;1656 memcpy(&loc_rule->flow_spec, &cmd->fs,1657 sizeof(struct ethtool_rx_flow_spec));1658 list_add_tail(&loc_rule->list, &priv->ethtool_list);1659 1660out_free_list:1661 list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) {1662 list_del(&spec->list);1663 kfree(spec);1664 }1665 return err;1666}1667 1668static int mlx4_en_flow_detach(struct net_device *dev,1669 struct ethtool_rxnfc *cmd)1670{1671 int err = 0;1672 struct ethtool_flow_id *rule;1673 struct mlx4_en_priv *priv = netdev_priv(dev);1674 1675 if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)1676 return -EINVAL;1677 1678 rule = &priv->ethtool_rules[cmd->fs.location];1679 if (!rule->id) {1680 err = -ENOENT;1681 goto out;1682 }1683 1684 err = mlx4_flow_detach(priv->mdev->dev, rule->id);1685 if (err) {1686 en_err(priv, "Fail to detach network rule at location %d. registration id = 0x%llx\n",1687 cmd->fs.location, rule->id);1688 goto out;1689 }1690 rule->id = 0;1691 memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec));1692 list_del(&rule->list);1693out:1694 return err;1695 1696}1697 1698static int mlx4_en_get_flow(struct net_device *dev, struct ethtool_rxnfc *cmd,1699 int loc)1700{1701 int err = 0;1702 struct ethtool_flow_id *rule;1703 struct mlx4_en_priv *priv = netdev_priv(dev);1704 1705 if (loc < 0 || loc >= MAX_NUM_OF_FS_RULES)1706 return -EINVAL;1707 1708 rule = &priv->ethtool_rules[loc];1709 if (rule->id)1710 memcpy(&cmd->fs, &rule->flow_spec,1711 sizeof(struct ethtool_rx_flow_spec));1712 else1713 err = -ENOENT;1714 1715 return err;1716}1717 1718static int mlx4_en_get_num_flows(struct mlx4_en_priv *priv)1719{1720 1721 int i, res = 0;1722 for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) {1723 if (priv->ethtool_rules[i].id)1724 res++;1725 }1726 return res;1727 1728}1729 1730static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,1731 u32 *rule_locs)1732{1733 struct mlx4_en_priv *priv = netdev_priv(dev);1734 struct mlx4_en_dev *mdev = priv->mdev;1735 int err = 0;1736 int i = 0, priority = 0;1737 1738 if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT ||1739 cmd->cmd == ETHTOOL_GRXCLSRULE ||1740 cmd->cmd == ETHTOOL_GRXCLSRLALL) &&1741 (mdev->dev->caps.steering_mode !=1742 MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up))1743 return -EINVAL;1744 1745 switch (cmd->cmd) {1746 case ETHTOOL_GRXRINGS:1747 cmd->data = priv->rx_ring_num;1748 break;1749 case ETHTOOL_GRXCLSRLCNT:1750 cmd->rule_cnt = mlx4_en_get_num_flows(priv);1751 break;1752 case ETHTOOL_GRXCLSRULE:1753 err = mlx4_en_get_flow(dev, cmd, cmd->fs.location);1754 break;1755 case ETHTOOL_GRXCLSRLALL:1756 cmd->data = MAX_NUM_OF_FS_RULES;1757 while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) {1758 err = mlx4_en_get_flow(dev, cmd, i);1759 if (!err)1760 rule_locs[priority++] = i;1761 i++;1762 }1763 err = 0;1764 break;1765 default:1766 err = -EOPNOTSUPP;1767 break;1768 }1769 1770 return err;1771}1772 1773static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)1774{1775 int err = 0;1776 struct mlx4_en_priv *priv = netdev_priv(dev);1777 struct mlx4_en_dev *mdev = priv->mdev;1778 1779 if (mdev->dev->caps.steering_mode !=1780 MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up)1781 return -EINVAL;1782 1783 switch (cmd->cmd) {1784 case ETHTOOL_SRXCLSRLINS:1785 err = mlx4_en_flow_replace(dev, cmd);1786 break;1787 case ETHTOOL_SRXCLSRLDEL:1788 err = mlx4_en_flow_detach(dev, cmd);1789 break;1790 default:1791 en_warn(priv, "Unsupported ethtool command. (%d)\n", cmd->cmd);1792 return -EINVAL;1793 }1794 1795 return err;1796}1797 1798static int mlx4_en_get_max_num_rx_rings(struct net_device *dev)1799{1800 return min_t(int, num_online_cpus(), MAX_RX_RINGS);1801}1802 1803static void mlx4_en_get_channels(struct net_device *dev,1804 struct ethtool_channels *channel)1805{1806 struct mlx4_en_priv *priv = netdev_priv(dev);1807 1808 channel->max_rx = mlx4_en_get_max_num_rx_rings(dev);1809 channel->max_tx = priv->mdev->profile.max_num_tx_rings_p_up;1810 1811 channel->rx_count = priv->rx_ring_num;1812 channel->tx_count = priv->tx_ring_num[TX] /1813 priv->prof->num_up;1814}1815 1816static int mlx4_en_set_channels(struct net_device *dev,1817 struct ethtool_channels *channel)1818{1819 struct mlx4_en_priv *priv = netdev_priv(dev);1820 struct mlx4_en_dev *mdev = priv->mdev;1821 struct mlx4_en_port_profile new_prof;1822 struct mlx4_en_priv *tmp;1823 int total_tx_count;1824 int port_up = 0;1825 int xdp_count;1826 int err = 0;1827 u8 up;1828 1829 if (!channel->tx_count || !channel->rx_count)1830 return -EINVAL;1831 1832 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);1833 if (!tmp)1834 return -ENOMEM;1835 1836 mutex_lock(&mdev->state_lock);1837 xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0;1838 total_tx_count = channel->tx_count * priv->prof->num_up + xdp_count;1839 if (total_tx_count > MAX_TX_RINGS) {1840 err = -EINVAL;1841 en_err(priv,1842 "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n",1843 total_tx_count, MAX_TX_RINGS);1844 goto out;1845 }1846 1847 memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));1848 new_prof.num_tx_rings_p_up = channel->tx_count;1849 new_prof.tx_ring_num[TX] = channel->tx_count * priv->prof->num_up;1850 new_prof.tx_ring_num[TX_XDP] = xdp_count;1851 new_prof.rx_ring_num = channel->rx_count;1852 1853 err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);1854 if (err)1855 goto out;1856 1857 if (priv->port_up) {1858 port_up = 1;1859 mlx4_en_stop_port(dev, 1);1860 }1861 1862 mlx4_en_safe_replace_resources(priv, tmp);1863 1864 netif_set_real_num_rx_queues(dev, priv->rx_ring_num);1865 1866 up = (priv->prof->num_up == MLX4_EN_NUM_UP_LOW) ?1867 0 : priv->prof->num_up;1868 mlx4_en_setup_tc(dev, up);1869 1870 en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]);1871 en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);1872 1873 if (port_up) {1874 err = mlx4_en_start_port(dev);1875 if (err)1876 en_err(priv, "Failed starting port\n");1877 }1878 1879 err = mlx4_en_moderation_update(priv);1880out:1881 mutex_unlock(&mdev->state_lock);1882 kfree(tmp);1883 return err;1884}1885 1886static int mlx4_en_get_ts_info(struct net_device *dev,1887 struct kernel_ethtool_ts_info *info)1888{1889 struct mlx4_en_priv *priv = netdev_priv(dev);1890 struct mlx4_en_dev *mdev = priv->mdev;1891 int ret;1892 1893 ret = ethtool_op_get_ts_info(dev, info);1894 if (ret)1895 return ret;1896 1897 if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {1898 info->so_timestamping |=1899 SOF_TIMESTAMPING_TX_HARDWARE |1900 SOF_TIMESTAMPING_RX_HARDWARE |1901 SOF_TIMESTAMPING_RAW_HARDWARE;1902 1903 info->tx_types =1904 (1 << HWTSTAMP_TX_OFF) |1905 (1 << HWTSTAMP_TX_ON);1906 1907 info->rx_filters =1908 (1 << HWTSTAMP_FILTER_NONE) |1909 (1 << HWTSTAMP_FILTER_ALL);1910 1911 if (mdev->ptp_clock)1912 info->phc_index = ptp_clock_index(mdev->ptp_clock);1913 }1914 1915 return ret;1916}1917 1918static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)1919{1920 struct mlx4_en_priv *priv = netdev_priv(dev);1921 struct mlx4_en_dev *mdev = priv->mdev;1922 bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);1923 bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);1924 bool phv_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_PHV);1925 bool phv_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_PHV);1926 int i;1927 int ret = 0;1928 1929 if (bf_enabled_new != bf_enabled_old) {1930 int t;1931 1932 if (bf_enabled_new) {1933 bool bf_supported = true;1934 1935 for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)1936 for (i = 0; i < priv->tx_ring_num[t]; i++)1937 bf_supported &=1938 priv->tx_ring[t][i]->bf_alloced;1939 1940 if (!bf_supported) {1941 en_err(priv, "BlueFlame is not supported\n");1942 return -EINVAL;1943 }1944 1945 priv->pflags |= MLX4_EN_PRIV_FLAGS_BLUEFLAME;1946 } else {1947 priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;1948 }1949 1950 for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)1951 for (i = 0; i < priv->tx_ring_num[t]; i++)1952 priv->tx_ring[t][i]->bf_enabled =1953 bf_enabled_new;1954 1955 en_info(priv, "BlueFlame %s\n",1956 bf_enabled_new ? "Enabled" : "Disabled");1957 }1958 1959 if (phv_enabled_new != phv_enabled_old) {1960 ret = set_phv_bit(mdev->dev, priv->port, (int)phv_enabled_new);1961 if (ret)1962 return ret;1963 else if (phv_enabled_new)1964 priv->pflags |= MLX4_EN_PRIV_FLAGS_PHV;1965 else1966 priv->pflags &= ~MLX4_EN_PRIV_FLAGS_PHV;1967 en_info(priv, "PHV bit %s\n",1968 phv_enabled_new ? "Enabled" : "Disabled");1969 }1970 return 0;1971}1972 1973static u32 mlx4_en_get_priv_flags(struct net_device *dev)1974{1975 struct mlx4_en_priv *priv = netdev_priv(dev);1976 1977 return priv->pflags;1978}1979 1980static int mlx4_en_get_tunable(struct net_device *dev,1981 const struct ethtool_tunable *tuna,1982 void *data)1983{1984 const struct mlx4_en_priv *priv = netdev_priv(dev);1985 int ret = 0;1986 1987 switch (tuna->id) {1988 case ETHTOOL_TX_COPYBREAK:1989 *(u32 *)data = priv->prof->inline_thold;1990 break;1991 default:1992 ret = -EINVAL;1993 break;1994 }1995 1996 return ret;1997}1998 1999static int mlx4_en_set_tunable(struct net_device *dev,2000 const struct ethtool_tunable *tuna,2001 const void *data)2002{2003 struct mlx4_en_priv *priv = netdev_priv(dev);2004 int val, ret = 0;2005 2006 switch (tuna->id) {2007 case ETHTOOL_TX_COPYBREAK:2008 val = *(u32 *)data;2009 if (val < MIN_PKT_LEN || val > MAX_INLINE)2010 ret = -EINVAL;2011 else2012 priv->prof->inline_thold = val;2013 break;2014 default:2015 ret = -EINVAL;2016 break;2017 }2018 2019 return ret;2020}2021 2022static int mlx4_en_get_module_info(struct net_device *dev,2023 struct ethtool_modinfo *modinfo)2024{2025 struct mlx4_en_priv *priv = netdev_priv(dev);2026 struct mlx4_en_dev *mdev = priv->mdev;2027 int ret;2028 u8 data[4];2029 2030 /* Read first 2 bytes to get Module & REV ID */2031 ret = mlx4_get_module_info(mdev->dev, priv->port,2032 0/*offset*/, 2/*size*/, data);2033 if (ret < 2)2034 return -EIO;2035 2036 switch (data[0] /* identifier */) {2037 case MLX4_MODULE_ID_QSFP:2038 modinfo->type = ETH_MODULE_SFF_8436;2039 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;2040 break;2041 case MLX4_MODULE_ID_QSFP_PLUS:2042 if (data[1] >= 0x3) { /* revision id */2043 modinfo->type = ETH_MODULE_SFF_8636;2044 modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;2045 } else {2046 modinfo->type = ETH_MODULE_SFF_8436;2047 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;2048 }2049 break;2050 case MLX4_MODULE_ID_QSFP28:2051 modinfo->type = ETH_MODULE_SFF_8636;2052 modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;2053 break;2054 case MLX4_MODULE_ID_SFP:2055 modinfo->type = ETH_MODULE_SFF_8472;2056 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;2057 break;2058 default:2059 return -EINVAL;2060 }2061 2062 return 0;2063}2064 2065static int mlx4_en_get_module_eeprom(struct net_device *dev,2066 struct ethtool_eeprom *ee,2067 u8 *data)2068{2069 struct mlx4_en_priv *priv = netdev_priv(dev);2070 struct mlx4_en_dev *mdev = priv->mdev;2071 int offset = ee->offset;2072 int i = 0, ret;2073 2074 if (ee->len == 0)2075 return -EINVAL;2076 2077 memset(data, 0, ee->len);2078 2079 while (i < ee->len) {2080 en_dbg(DRV, priv,2081 "mlx4_get_module_info i(%d) offset(%d) len(%d)\n",2082 i, offset, ee->len - i);2083 2084 ret = mlx4_get_module_info(mdev->dev, priv->port,2085 offset, ee->len - i, data + i);2086 2087 if (!ret) /* Done reading */2088 return 0;2089 2090 if (ret < 0) {2091 en_err(priv,2092 "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",2093 i, offset, ee->len - i, ret);2094 return ret;2095 }2096 2097 i += ret;2098 offset += ret;2099 }2100 return 0;2101}2102 2103static int mlx4_en_set_phys_id(struct net_device *dev,2104 enum ethtool_phys_id_state state)2105{2106 int err;2107 u16 beacon_duration;2108 struct mlx4_en_priv *priv = netdev_priv(dev);2109 struct mlx4_en_dev *mdev = priv->mdev;2110 2111 if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_BEACON))2112 return -EOPNOTSUPP;2113 2114 switch (state) {2115 case ETHTOOL_ID_ACTIVE:2116 beacon_duration = PORT_BEACON_MAX_LIMIT;2117 break;2118 case ETHTOOL_ID_INACTIVE:2119 beacon_duration = 0;2120 break;2121 default:2122 return -EOPNOTSUPP;2123 }2124 2125 err = mlx4_SET_PORT_BEACON(mdev->dev, priv->port, beacon_duration);2126 return err;2127}2128 2129const struct ethtool_ops mlx4_en_ethtool_ops = {2130 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |2131 ETHTOOL_COALESCE_MAX_FRAMES |2132 ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |2133 ETHTOOL_COALESCE_PKT_RATE_RX_USECS,2134 .get_drvinfo = mlx4_en_get_drvinfo,2135 .get_link_ksettings = mlx4_en_get_link_ksettings,2136 .set_link_ksettings = mlx4_en_set_link_ksettings,2137 .get_link = ethtool_op_get_link,2138 .get_strings = mlx4_en_get_strings,2139 .get_sset_count = mlx4_en_get_sset_count,2140 .get_ethtool_stats = mlx4_en_get_ethtool_stats,2141 .self_test = mlx4_en_self_test,2142 .set_phys_id = mlx4_en_set_phys_id,2143 .get_wol = mlx4_en_get_wol,2144 .set_wol = mlx4_en_set_wol,2145 .get_msglevel = mlx4_en_get_msglevel,2146 .set_msglevel = mlx4_en_set_msglevel,2147 .get_coalesce = mlx4_en_get_coalesce,2148 .set_coalesce = mlx4_en_set_coalesce,2149 .get_pause_stats = mlx4_en_get_pause_stats,2150 .get_pauseparam = mlx4_en_get_pauseparam,2151 .set_pauseparam = mlx4_en_set_pauseparam,2152 .get_ringparam = mlx4_en_get_ringparam,2153 .set_ringparam = mlx4_en_set_ringparam,2154 .get_rxnfc = mlx4_en_get_rxnfc,2155 .set_rxnfc = mlx4_en_set_rxnfc,2156 .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,2157 .get_rxfh_key_size = mlx4_en_get_rxfh_key_size,2158 .get_rxfh = mlx4_en_get_rxfh,2159 .set_rxfh = mlx4_en_set_rxfh,2160 .get_channels = mlx4_en_get_channels,2161 .set_channels = mlx4_en_set_channels,2162 .get_ts_info = mlx4_en_get_ts_info,2163 .set_priv_flags = mlx4_en_set_priv_flags,2164 .get_priv_flags = mlx4_en_get_priv_flags,2165 .get_tunable = mlx4_en_get_tunable,2166 .set_tunable = mlx4_en_set_tunable,2167 .get_module_info = mlx4_en_get_module_info,2168 .get_module_eeprom = mlx4_en_get_module_eeprom2169};2170 2171 2172 2173 2174 2175