1465 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2005 - 2016 Broadcom4 * All rights reserved.5 *6 * Contact Information:7 * linux-drivers@emulex.com8 *9 * Emulex10 * 3333 Susan Street11 * Costa Mesa, CA 9262612 */13 14#include "be.h"15#include "be_cmds.h"16#include <linux/ethtool.h>17 18struct be_ethtool_stat {19 char desc[ETH_GSTRING_LEN];20 int type;21 int size;22 int offset;23};24 25enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};26#define FIELDINFO(_struct, field) sizeof_field(_struct, field), \27 offsetof(_struct, field)28#define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\29 FIELDINFO(struct be_tx_stats, field)30#define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\31 FIELDINFO(struct be_rx_stats, field)32#define DRVSTAT_INFO(field) #field, DRVSTAT,\33 FIELDINFO(struct be_drv_stats, field)34 35static const struct be_ethtool_stat et_stats[] = {36 {DRVSTAT_INFO(rx_crc_errors)},37 {DRVSTAT_INFO(rx_alignment_symbol_errors)},38 {DRVSTAT_INFO(rx_pause_frames)},39 {DRVSTAT_INFO(rx_control_frames)},40 /* Received packets dropped when the Ethernet length field41 * is not equal to the actual Ethernet data length.42 */43 {DRVSTAT_INFO(rx_in_range_errors)},44 /* Received packets dropped when their length field is >= 1501 bytes45 * and <= 1535 bytes.46 */47 {DRVSTAT_INFO(rx_out_range_errors)},48 /* Received packets dropped when they are longer than 9216 bytes */49 {DRVSTAT_INFO(rx_frame_too_long)},50 /* Received packets dropped when they don't pass the unicast or51 * multicast address filtering.52 */53 {DRVSTAT_INFO(rx_address_filtered)},54 /* Received packets dropped when IP packet length field is less than55 * the IP header length field.56 */57 {DRVSTAT_INFO(rx_dropped_too_small)},58 /* Received packets dropped when IP length field is greater than59 * the actual packet length.60 */61 {DRVSTAT_INFO(rx_dropped_too_short)},62 /* Received packets dropped when the IP header length field is less63 * than 5.64 */65 {DRVSTAT_INFO(rx_dropped_header_too_small)},66 /* Received packets dropped when the TCP header length field is less67 * than 5 or the TCP header length + IP header length is more68 * than IP packet length.69 */70 {DRVSTAT_INFO(rx_dropped_tcp_length)},71 {DRVSTAT_INFO(rx_dropped_runt)},72 /* Number of received packets dropped when a fifo for descriptors going73 * into the packet demux block overflows. In normal operation, this74 * fifo must never overflow.75 */76 {DRVSTAT_INFO(rxpp_fifo_overflow_drop)},77 /* Received packets dropped when the RX block runs out of space in78 * one of its input FIFOs. This could happen due a long burst of79 * minimum-sized (64b) frames in the receive path.80 * This counter may also be erroneously incremented rarely.81 */82 {DRVSTAT_INFO(rx_input_fifo_overflow_drop)},83 {DRVSTAT_INFO(rx_ip_checksum_errs)},84 {DRVSTAT_INFO(rx_tcp_checksum_errs)},85 {DRVSTAT_INFO(rx_udp_checksum_errs)},86 {DRVSTAT_INFO(tx_pauseframes)},87 {DRVSTAT_INFO(tx_controlframes)},88 {DRVSTAT_INFO(rx_priority_pause_frames)},89 {DRVSTAT_INFO(tx_priority_pauseframes)},90 /* Received packets dropped when an internal fifo going into91 * main packet buffer tank (PMEM) overflows.92 */93 {DRVSTAT_INFO(pmem_fifo_overflow_drop)},94 {DRVSTAT_INFO(jabber_events)},95 /* Received packets dropped due to lack of available HW packet buffers96 * used to temporarily hold the received packets.97 */98 {DRVSTAT_INFO(rx_drops_no_pbuf)},99 /* Received packets dropped due to input receive buffer100 * descriptor fifo overflowing.101 */102 {DRVSTAT_INFO(rx_drops_no_erx_descr)},103 /* Packets dropped because the internal FIFO to the offloaded TCP104 * receive processing block is full. This could happen only for105 * offloaded iSCSI or FCoE trarffic.106 */107 {DRVSTAT_INFO(rx_drops_no_tpre_descr)},108 /* Received packets dropped when they need more than 8109 * receive buffers. This cannot happen as the driver configures110 * 2048 byte receive buffers.111 */112 {DRVSTAT_INFO(rx_drops_too_many_frags)},113 {DRVSTAT_INFO(forwarded_packets)},114 /* Received packets dropped when the frame length115 * is more than 9018 bytes116 */117 {DRVSTAT_INFO(rx_drops_mtu)},118 /* Number of dma mapping errors */119 {DRVSTAT_INFO(dma_map_errors)},120 /* Number of packets dropped due to random early drop function */121 {DRVSTAT_INFO(eth_red_drops)},122 {DRVSTAT_INFO(rx_roce_bytes_lsd)},123 {DRVSTAT_INFO(rx_roce_bytes_msd)},124 {DRVSTAT_INFO(rx_roce_frames)},125 {DRVSTAT_INFO(roce_drops_payload_len)},126 {DRVSTAT_INFO(roce_drops_crc)}127};128 129#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)130 131/* Stats related to multi RX queues: get_stats routine assumes bytes, pkts132 * are first and second members respectively.133 */134static const struct be_ethtool_stat et_rx_stats[] = {135 {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */136 {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */137 {DRVSTAT_RX_INFO(rx_vxlan_offload_pkts)},138 {DRVSTAT_RX_INFO(rx_compl)},139 {DRVSTAT_RX_INFO(rx_compl_err)},140 {DRVSTAT_RX_INFO(rx_mcast_pkts)},141 /* Number of page allocation failures while posting receive buffers142 * to HW.143 */144 {DRVSTAT_RX_INFO(rx_post_fail)},145 /* Recevied packets dropped due to skb allocation failure */146 {DRVSTAT_RX_INFO(rx_drops_no_skbs)},147 /* Received packets dropped due to lack of available fetched buffers148 * posted by the driver.149 */150 {DRVSTAT_RX_INFO(rx_drops_no_frags)}151};152 153#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))154 155/* Stats related to multi TX queues: get_stats routine assumes compl is the156 * first member157 */158static const struct be_ethtool_stat et_tx_stats[] = {159 {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */160 /* This counter is incremented when the HW encounters an error while161 * parsing the packet header of an outgoing TX request. This counter is162 * applicable only for BE2, BE3 and Skyhawk based adapters.163 */164 {DRVSTAT_TX_INFO(tx_hdr_parse_err)},165 /* This counter is incremented when an error occurs in the DMA166 * operation associated with the TX request from the host to the device.167 */168 {DRVSTAT_TX_INFO(tx_dma_err)},169 /* This counter is incremented when MAC or VLAN spoof checking is170 * enabled on the interface and the TX request fails the spoof check171 * in HW.172 */173 {DRVSTAT_TX_INFO(tx_spoof_check_err)},174 /* This counter is incremented when the HW encounters an error while175 * performing TSO offload. This counter is applicable only for Lancer176 * adapters.177 */178 {DRVSTAT_TX_INFO(tx_tso_err)},179 /* This counter is incremented when the HW detects Q-in-Q style VLAN180 * tagging in a packet and such tagging is not expected on the outgoing181 * interface. This counter is applicable only for Lancer adapters.182 */183 {DRVSTAT_TX_INFO(tx_qinq_err)},184 /* This counter is incremented when the HW detects parity errors in the185 * packet data. This counter is applicable only for Lancer adapters.186 */187 {DRVSTAT_TX_INFO(tx_internal_parity_err)},188 {DRVSTAT_TX_INFO(tx_sge_err)},189 {DRVSTAT_TX_INFO(tx_bytes)},190 {DRVSTAT_TX_INFO(tx_pkts)},191 {DRVSTAT_TX_INFO(tx_vxlan_offload_pkts)},192 /* Number of skbs queued for trasmission by the driver */193 {DRVSTAT_TX_INFO(tx_reqs)},194 /* Number of times the TX queue was stopped due to lack195 * of spaces in the TXQ.196 */197 {DRVSTAT_TX_INFO(tx_stops)},198 /* Pkts dropped in the driver's transmit path */199 {DRVSTAT_TX_INFO(tx_drv_drops)}200};201 202#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))203 204static const char et_self_tests[][ETH_GSTRING_LEN] = {205 "MAC Loopback test",206 "PHY Loopback test",207 "External Loopback test",208 "DDR DMA test",209 "Link test"210};211 212#define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests)213#define BE_MAC_LOOPBACK 0x0214#define BE_PHY_LOOPBACK 0x1215#define BE_ONE_PORT_EXT_LOOPBACK 0x2216#define BE_NO_LOOPBACK 0xff217 218static void be_get_drvinfo(struct net_device *netdev,219 struct ethtool_drvinfo *drvinfo)220{221 struct be_adapter *adapter = netdev_priv(netdev);222 223 strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));224 if (!memcmp(adapter->fw_ver, adapter->fw_on_flash, FW_VER_LEN))225 strscpy(drvinfo->fw_version, adapter->fw_ver,226 sizeof(drvinfo->fw_version));227 else228 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),229 "%s [%s]", adapter->fw_ver, adapter->fw_on_flash);230 231 strscpy(drvinfo->bus_info, pci_name(adapter->pdev),232 sizeof(drvinfo->bus_info));233}234 235static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name)236{237 u32 data_read = 0, eof;238 u8 addn_status;239 struct be_dma_mem data_len_cmd;240 241 memset(&data_len_cmd, 0, sizeof(data_len_cmd));242 /* data_offset and data_size should be 0 to get reg len */243 lancer_cmd_read_object(adapter, &data_len_cmd, 0, 0, file_name,244 &data_read, &eof, &addn_status);245 246 return data_read;247}248 249static int be_get_dump_len(struct be_adapter *adapter)250{251 u32 dump_size = 0;252 253 if (lancer_chip(adapter))254 dump_size = lancer_cmd_get_file_len(adapter,255 LANCER_FW_DUMP_FILE);256 else257 dump_size = adapter->fat_dump_len;258 259 return dump_size;260}261 262static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,263 u32 buf_len, void *buf)264{265 struct be_dma_mem read_cmd;266 u32 read_len = 0, total_read_len = 0, chunk_size;267 u32 eof = 0;268 u8 addn_status;269 int status = 0;270 271 read_cmd.size = LANCER_READ_FILE_CHUNK;272 read_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, read_cmd.size,273 &read_cmd.dma, GFP_ATOMIC);274 275 if (!read_cmd.va) {276 dev_err(&adapter->pdev->dev,277 "Memory allocation failure while reading dump\n");278 return -ENOMEM;279 }280 281 while ((total_read_len < buf_len) && !eof) {282 chunk_size = min_t(u32, (buf_len - total_read_len),283 LANCER_READ_FILE_CHUNK);284 chunk_size = ALIGN(chunk_size, 4);285 status = lancer_cmd_read_object(adapter, &read_cmd, chunk_size,286 total_read_len, file_name,287 &read_len, &eof, &addn_status);288 if (!status) {289 memcpy(buf + total_read_len, read_cmd.va, read_len);290 total_read_len += read_len;291 eof &= LANCER_READ_FILE_EOF_MASK;292 } else {293 status = -EIO;294 break;295 }296 }297 dma_free_coherent(&adapter->pdev->dev, read_cmd.size, read_cmd.va,298 read_cmd.dma);299 300 return status;301}302 303static int be_read_dump_data(struct be_adapter *adapter, u32 dump_len,304 void *buf)305{306 int status = 0;307 308 if (lancer_chip(adapter))309 status = lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE,310 dump_len, buf);311 else312 status = be_cmd_get_fat_dump(adapter, dump_len, buf);313 314 return status;315}316 317static int be_get_coalesce(struct net_device *netdev,318 struct ethtool_coalesce *et,319 struct kernel_ethtool_coalesce *kernel_coal,320 struct netlink_ext_ack *extack)321{322 struct be_adapter *adapter = netdev_priv(netdev);323 struct be_aic_obj *aic = &adapter->aic_obj[0];324 325 et->rx_coalesce_usecs = aic->prev_eqd;326 et->rx_coalesce_usecs_high = aic->max_eqd;327 et->rx_coalesce_usecs_low = aic->min_eqd;328 329 et->tx_coalesce_usecs = aic->prev_eqd;330 et->tx_coalesce_usecs_high = aic->max_eqd;331 et->tx_coalesce_usecs_low = aic->min_eqd;332 333 et->use_adaptive_rx_coalesce = adapter->aic_enabled;334 et->use_adaptive_tx_coalesce = adapter->aic_enabled;335 336 return 0;337}338 339/* TX attributes are ignored. Only RX attributes are considered340 * eqd cmd is issued in the worker thread.341 */342static int be_set_coalesce(struct net_device *netdev,343 struct ethtool_coalesce *et,344 struct kernel_ethtool_coalesce *kernel_coal,345 struct netlink_ext_ack *extack)346{347 struct be_adapter *adapter = netdev_priv(netdev);348 struct be_aic_obj *aic = &adapter->aic_obj[0];349 struct be_eq_obj *eqo;350 int i;351 352 adapter->aic_enabled = et->use_adaptive_rx_coalesce;353 354 for_all_evt_queues(adapter, eqo, i) {355 aic->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD);356 aic->min_eqd = min(et->rx_coalesce_usecs_low, aic->max_eqd);357 aic->et_eqd = min(et->rx_coalesce_usecs, aic->max_eqd);358 aic->et_eqd = max(aic->et_eqd, aic->min_eqd);359 aic++;360 }361 362 /* For Skyhawk, the EQD setting happens via EQ_DB when AIC is enabled.363 * When AIC is disabled, persistently force set EQD value via the364 * FW cmd, so that we don't have to calculate the delay multiplier365 * encode value each time EQ_DB is rung366 */367 if (!et->use_adaptive_rx_coalesce && skyhawk_chip(adapter))368 be_eqd_update(adapter, true);369 370 return 0;371}372 373static void be_get_ethtool_stats(struct net_device *netdev,374 struct ethtool_stats *stats, uint64_t *data)375{376 struct be_adapter *adapter = netdev_priv(netdev);377 struct be_rx_obj *rxo;378 struct be_tx_obj *txo;379 void *p;380 unsigned int i, j, base = 0, start;381 382 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {383 p = (u8 *)&adapter->drv_stats + et_stats[i].offset;384 data[i] = *(u32 *)p;385 }386 base += ETHTOOL_STATS_NUM;387 388 for_all_rx_queues(adapter, rxo, j) {389 struct be_rx_stats *stats = rx_stats(rxo);390 391 do {392 start = u64_stats_fetch_begin(&stats->sync);393 data[base] = stats->rx_bytes;394 data[base + 1] = stats->rx_pkts;395 } while (u64_stats_fetch_retry(&stats->sync, start));396 397 for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {398 p = (u8 *)stats + et_rx_stats[i].offset;399 data[base + i] = *(u32 *)p;400 }401 base += ETHTOOL_RXSTATS_NUM;402 }403 404 for_all_tx_queues(adapter, txo, j) {405 struct be_tx_stats *stats = tx_stats(txo);406 407 do {408 start = u64_stats_fetch_begin(&stats->sync_compl);409 data[base] = stats->tx_compl;410 } while (u64_stats_fetch_retry(&stats->sync_compl, start));411 412 do {413 start = u64_stats_fetch_begin(&stats->sync);414 for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {415 p = (u8 *)stats + et_tx_stats[i].offset;416 data[base + i] =417 (et_tx_stats[i].size == sizeof(u64)) ?418 *(u64 *)p : *(u32 *)p;419 }420 } while (u64_stats_fetch_retry(&stats->sync, start));421 base += ETHTOOL_TXSTATS_NUM;422 }423}424 425static const char be_priv_flags[][ETH_GSTRING_LEN] = {426 "disable-tpe-recovery"427};428 429static void be_get_stat_strings(struct net_device *netdev, uint32_t stringset,430 uint8_t *data)431{432 struct be_adapter *adapter = netdev_priv(netdev);433 int i, j;434 435 switch (stringset) {436 case ETH_SS_STATS:437 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {438 memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);439 data += ETH_GSTRING_LEN;440 }441 for (i = 0; i < adapter->num_rx_qs; i++) {442 for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {443 sprintf(data, "rxq%d: %s", i,444 et_rx_stats[j].desc);445 data += ETH_GSTRING_LEN;446 }447 }448 for (i = 0; i < adapter->num_tx_qs; i++) {449 for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {450 sprintf(data, "txq%d: %s", i,451 et_tx_stats[j].desc);452 data += ETH_GSTRING_LEN;453 }454 }455 break;456 case ETH_SS_TEST:457 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {458 memcpy(data, et_self_tests[i], ETH_GSTRING_LEN);459 data += ETH_GSTRING_LEN;460 }461 break;462 case ETH_SS_PRIV_FLAGS:463 for (i = 0; i < ARRAY_SIZE(be_priv_flags); i++)464 strcpy(data + i * ETH_GSTRING_LEN, be_priv_flags[i]);465 break;466 }467}468 469static int be_get_sset_count(struct net_device *netdev, int stringset)470{471 struct be_adapter *adapter = netdev_priv(netdev);472 473 switch (stringset) {474 case ETH_SS_TEST:475 return ETHTOOL_TESTS_NUM;476 case ETH_SS_STATS:477 return ETHTOOL_STATS_NUM +478 adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +479 adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;480 case ETH_SS_PRIV_FLAGS:481 return ARRAY_SIZE(be_priv_flags);482 default:483 return -EINVAL;484 }485}486 487static u32 be_get_port_type(struct be_adapter *adapter)488{489 u32 port;490 491 switch (adapter->phy.interface_type) {492 case PHY_TYPE_BASET_1GB:493 case PHY_TYPE_BASEX_1GB:494 case PHY_TYPE_SGMII:495 port = PORT_TP;496 break;497 case PHY_TYPE_SFP_PLUS_10GB:498 if (adapter->phy.cable_type & SFP_PLUS_COPPER_CABLE)499 port = PORT_DA;500 else501 port = PORT_FIBRE;502 break;503 case PHY_TYPE_QSFP:504 if (adapter->phy.cable_type & QSFP_PLUS_CR4_CABLE)505 port = PORT_DA;506 else507 port = PORT_FIBRE;508 break;509 case PHY_TYPE_XFP_10GB:510 case PHY_TYPE_SFP_1GB:511 port = PORT_FIBRE;512 break;513 case PHY_TYPE_BASET_10GB:514 port = PORT_TP;515 break;516 default:517 port = PORT_OTHER;518 }519 520 return port;521}522 523static u32 convert_to_et_setting(struct be_adapter *adapter, u32 if_speeds)524{525 u32 val = 0;526 527 switch (adapter->phy.interface_type) {528 case PHY_TYPE_BASET_1GB:529 case PHY_TYPE_BASEX_1GB:530 case PHY_TYPE_SGMII:531 val |= SUPPORTED_TP;532 if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)533 val |= SUPPORTED_1000baseT_Full;534 if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)535 val |= SUPPORTED_100baseT_Full;536 if (if_speeds & BE_SUPPORTED_SPEED_10MBPS)537 val |= SUPPORTED_10baseT_Full;538 break;539 case PHY_TYPE_KX4_10GB:540 val |= SUPPORTED_Backplane;541 if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)542 val |= SUPPORTED_1000baseKX_Full;543 if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)544 val |= SUPPORTED_10000baseKX4_Full;545 break;546 case PHY_TYPE_KR2_20GB:547 val |= SUPPORTED_Backplane;548 if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)549 val |= SUPPORTED_10000baseKR_Full;550 if (if_speeds & BE_SUPPORTED_SPEED_20GBPS)551 val |= SUPPORTED_20000baseKR2_Full;552 break;553 case PHY_TYPE_KR_10GB:554 val |= SUPPORTED_Backplane |555 SUPPORTED_10000baseKR_Full;556 break;557 case PHY_TYPE_KR4_40GB:558 val |= SUPPORTED_Backplane;559 if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)560 val |= SUPPORTED_10000baseKR_Full;561 if (if_speeds & BE_SUPPORTED_SPEED_40GBPS)562 val |= SUPPORTED_40000baseKR4_Full;563 break;564 case PHY_TYPE_QSFP:565 if (if_speeds & BE_SUPPORTED_SPEED_40GBPS) {566 switch (adapter->phy.cable_type) {567 case QSFP_PLUS_CR4_CABLE:568 val |= SUPPORTED_40000baseCR4_Full;569 break;570 case QSFP_PLUS_LR4_CABLE:571 val |= SUPPORTED_40000baseLR4_Full;572 break;573 default:574 val |= SUPPORTED_40000baseSR4_Full;575 break;576 }577 }578 fallthrough;579 case PHY_TYPE_SFP_PLUS_10GB:580 case PHY_TYPE_XFP_10GB:581 case PHY_TYPE_SFP_1GB:582 val |= SUPPORTED_FIBRE;583 if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)584 val |= SUPPORTED_10000baseT_Full;585 if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)586 val |= SUPPORTED_1000baseT_Full;587 break;588 case PHY_TYPE_BASET_10GB:589 val |= SUPPORTED_TP;590 if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)591 val |= SUPPORTED_10000baseT_Full;592 if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)593 val |= SUPPORTED_1000baseT_Full;594 if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)595 val |= SUPPORTED_100baseT_Full;596 break;597 default:598 val |= SUPPORTED_TP;599 }600 601 return val;602}603 604bool be_pause_supported(struct be_adapter *adapter)605{606 return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB ||607 adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ?608 false : true;609}610 611static int be_get_link_ksettings(struct net_device *netdev,612 struct ethtool_link_ksettings *cmd)613{614 struct be_adapter *adapter = netdev_priv(netdev);615 u8 link_status;616 u16 link_speed = 0;617 int status;618 u32 auto_speeds;619 u32 fixed_speeds;620 u32 supported = 0, advertising = 0;621 622 if (adapter->phy.link_speed < 0) {623 status = be_cmd_link_status_query(adapter, &link_speed,624 &link_status, 0);625 if (!status)626 be_link_status_update(adapter, link_status);627 cmd->base.speed = link_speed;628 629 status = be_cmd_get_phy_info(adapter);630 if (!status) {631 auto_speeds = adapter->phy.auto_speeds_supported;632 fixed_speeds = adapter->phy.fixed_speeds_supported;633 634 be_cmd_query_cable_type(adapter);635 636 supported =637 convert_to_et_setting(adapter,638 auto_speeds |639 fixed_speeds);640 advertising =641 convert_to_et_setting(adapter, auto_speeds);642 643 cmd->base.port = be_get_port_type(adapter);644 645 if (adapter->phy.auto_speeds_supported) {646 supported |= SUPPORTED_Autoneg;647 cmd->base.autoneg = AUTONEG_ENABLE;648 advertising |= ADVERTISED_Autoneg;649 }650 651 supported |= SUPPORTED_Pause;652 if (be_pause_supported(adapter))653 advertising |= ADVERTISED_Pause;654 } else {655 cmd->base.port = PORT_OTHER;656 cmd->base.autoneg = AUTONEG_DISABLE;657 }658 659 /* Save for future use */660 adapter->phy.link_speed = cmd->base.speed;661 adapter->phy.port_type = cmd->base.port;662 adapter->phy.autoneg = cmd->base.autoneg;663 adapter->phy.advertising = advertising;664 adapter->phy.supported = supported;665 } else {666 cmd->base.speed = adapter->phy.link_speed;667 cmd->base.port = adapter->phy.port_type;668 cmd->base.autoneg = adapter->phy.autoneg;669 advertising = adapter->phy.advertising;670 supported = adapter->phy.supported;671 }672 673 cmd->base.duplex = netif_carrier_ok(netdev) ?674 DUPLEX_FULL : DUPLEX_UNKNOWN;675 cmd->base.phy_address = adapter->port_num;676 677 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,678 supported);679 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,680 advertising);681 682 return 0;683}684 685static void be_get_ringparam(struct net_device *netdev,686 struct ethtool_ringparam *ring,687 struct kernel_ethtool_ringparam *kernel_ring,688 struct netlink_ext_ack *extack)689{690 struct be_adapter *adapter = netdev_priv(netdev);691 692 ring->rx_max_pending = adapter->rx_obj[0].q.len;693 ring->rx_pending = adapter->rx_obj[0].q.len;694 ring->tx_max_pending = adapter->tx_obj[0].q.len;695 ring->tx_pending = adapter->tx_obj[0].q.len;696}697 698static void699be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)700{701 struct be_adapter *adapter = netdev_priv(netdev);702 703 be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);704 ecmd->autoneg = adapter->phy.fc_autoneg;705}706 707static int708be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)709{710 struct be_adapter *adapter = netdev_priv(netdev);711 int status;712 713 if (ecmd->autoneg != adapter->phy.fc_autoneg)714 return -EINVAL;715 716 status = be_cmd_set_flow_control(adapter, ecmd->tx_pause,717 ecmd->rx_pause);718 if (status) {719 dev_warn(&adapter->pdev->dev, "Pause param set failed\n");720 return be_cmd_status(status);721 }722 723 adapter->tx_fc = ecmd->tx_pause;724 adapter->rx_fc = ecmd->rx_pause;725 return 0;726}727 728static int be_set_phys_id(struct net_device *netdev,729 enum ethtool_phys_id_state state)730{731 struct be_adapter *adapter = netdev_priv(netdev);732 int status = 0;733 734 switch (state) {735 case ETHTOOL_ID_ACTIVE:736 status = be_cmd_get_beacon_state(adapter, adapter->hba_port_num,737 &adapter->beacon_state);738 if (status)739 return be_cmd_status(status);740 return 1; /* cycle on/off once per second */741 742 case ETHTOOL_ID_ON:743 status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num,744 0, 0, BEACON_STATE_ENABLED);745 break;746 747 case ETHTOOL_ID_OFF:748 status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num,749 0, 0, BEACON_STATE_DISABLED);750 break;751 752 case ETHTOOL_ID_INACTIVE:753 status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num,754 0, 0, adapter->beacon_state);755 }756 757 return be_cmd_status(status);758}759 760static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)761{762 struct be_adapter *adapter = netdev_priv(netdev);763 struct device *dev = &adapter->pdev->dev;764 int status;765 766 if (!lancer_chip(adapter) ||767 !check_privilege(adapter, MAX_PRIVILEGES))768 return -EOPNOTSUPP;769 770 switch (dump->flag) {771 case LANCER_INITIATE_FW_DUMP:772 status = lancer_initiate_dump(adapter);773 if (!status)774 dev_info(dev, "FW dump initiated successfully\n");775 break;776 case LANCER_DELETE_FW_DUMP:777 status = lancer_delete_dump(adapter);778 if (!status)779 dev_info(dev, "FW dump deleted successfully\n");780 break;781 default:782 dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);783 return -EINVAL;784 }785 return status;786}787 788static void be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)789{790 struct be_adapter *adapter = netdev_priv(netdev);791 792 if (adapter->wol_cap & BE_WOL_CAP) {793 wol->supported |= WAKE_MAGIC;794 if (adapter->wol_en)795 wol->wolopts |= WAKE_MAGIC;796 } else {797 wol->wolopts = 0;798 }799 memset(&wol->sopass, 0, sizeof(wol->sopass));800}801 802static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)803{804 struct be_adapter *adapter = netdev_priv(netdev);805 struct device *dev = &adapter->pdev->dev;806 struct be_dma_mem cmd;807 u8 mac[ETH_ALEN];808 bool enable;809 int status;810 811 if (wol->wolopts & ~WAKE_MAGIC)812 return -EOPNOTSUPP;813 814 if (!(adapter->wol_cap & BE_WOL_CAP)) {815 dev_warn(&adapter->pdev->dev, "WOL not supported\n");816 return -EOPNOTSUPP;817 }818 819 cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);820 cmd.va = dma_alloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);821 if (!cmd.va)822 return -ENOMEM;823 824 eth_zero_addr(mac);825 826 enable = wol->wolopts & WAKE_MAGIC;827 if (enable)828 ether_addr_copy(mac, adapter->netdev->dev_addr);829 830 status = be_cmd_enable_magic_wol(adapter, mac, &cmd);831 if (status) {832 dev_err(dev, "Could not set Wake-on-lan mac address\n");833 status = be_cmd_status(status);834 goto err;835 }836 837 pci_enable_wake(adapter->pdev, PCI_D3hot, enable);838 pci_enable_wake(adapter->pdev, PCI_D3cold, enable);839 840 adapter->wol_en = enable ? true : false;841 842err:843 dma_free_coherent(dev, cmd.size, cmd.va, cmd.dma);844 return status;845}846 847static int be_test_ddr_dma(struct be_adapter *adapter)848{849 int ret, i;850 struct be_dma_mem ddrdma_cmd;851 static const u64 pattern[2] = {852 0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL853 };854 855 ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);856 ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,857 ddrdma_cmd.size, &ddrdma_cmd.dma,858 GFP_KERNEL);859 if (!ddrdma_cmd.va)860 return -ENOMEM;861 862 for (i = 0; i < 2; i++) {863 ret = be_cmd_ddr_dma_test(adapter, pattern[i],864 4096, &ddrdma_cmd);865 if (ret != 0)866 goto err;867 }868 869err:870 dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,871 ddrdma_cmd.dma);872 return be_cmd_status(ret);873}874 875static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,876 u64 *status)877{878 int ret;879 880 ret = be_cmd_set_loopback(adapter, adapter->hba_port_num,881 loopback_type, 1);882 if (ret)883 return ret;884 885 *status = be_cmd_loopback_test(adapter, adapter->hba_port_num,886 loopback_type, 1500, 2, 0xabc);887 888 ret = be_cmd_set_loopback(adapter, adapter->hba_port_num,889 BE_NO_LOOPBACK, 1);890 if (ret)891 return ret;892 893 return *status;894}895 896static void be_self_test(struct net_device *netdev, struct ethtool_test *test,897 u64 *data)898{899 struct be_adapter *adapter = netdev_priv(netdev);900 int status, cnt;901 u8 link_status = 0;902 903 if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) {904 dev_err(&adapter->pdev->dev, "Self test not supported\n");905 test->flags |= ETH_TEST_FL_FAILED;906 return;907 }908 909 memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);910 911 /* check link status before offline tests */912 link_status = netif_carrier_ok(netdev);913 914 if (test->flags & ETH_TEST_FL_OFFLINE) {915 if (be_loopback_test(adapter, BE_MAC_LOOPBACK, &data[0]) != 0)916 test->flags |= ETH_TEST_FL_FAILED;917 918 if (be_loopback_test(adapter, BE_PHY_LOOPBACK, &data[1]) != 0)919 test->flags |= ETH_TEST_FL_FAILED;920 921 if (test->flags & ETH_TEST_FL_EXTERNAL_LB) {922 if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,923 &data[2]) != 0)924 test->flags |= ETH_TEST_FL_FAILED;925 test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;926 }927 }928 929 if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) {930 data[3] = 1;931 test->flags |= ETH_TEST_FL_FAILED;932 }933 934 /* link status was down prior to test */935 if (!link_status) {936 test->flags |= ETH_TEST_FL_FAILED;937 data[4] = 1;938 return;939 }940 941 for (cnt = 10; cnt; cnt--) {942 status = be_cmd_link_status_query(adapter, NULL, &link_status,943 0);944 if (status) {945 test->flags |= ETH_TEST_FL_FAILED;946 data[4] = -1;947 break;948 }949 950 if (link_status)951 break;952 953 msleep_interruptible(500);954 }955}956 957static int be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)958{959 struct be_adapter *adapter = netdev_priv(netdev);960 961 return be_load_fw(adapter, efl->data);962}963 964static int965be_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)966{967 struct be_adapter *adapter = netdev_priv(netdev);968 969 if (!check_privilege(adapter, MAX_PRIVILEGES))970 return -EOPNOTSUPP;971 972 dump->len = be_get_dump_len(adapter);973 dump->version = 1;974 dump->flag = 0x1; /* FW dump is enabled */975 return 0;976}977 978static int979be_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,980 void *buf)981{982 struct be_adapter *adapter = netdev_priv(netdev);983 int status;984 985 if (!check_privilege(adapter, MAX_PRIVILEGES))986 return -EOPNOTSUPP;987 988 status = be_read_dump_data(adapter, dump->len, buf);989 return be_cmd_status(status);990}991 992static int be_get_eeprom_len(struct net_device *netdev)993{994 struct be_adapter *adapter = netdev_priv(netdev);995 996 if (!check_privilege(adapter, MAX_PRIVILEGES))997 return 0;998 999 if (lancer_chip(adapter)) {1000 if (be_physfn(adapter))1001 return lancer_cmd_get_file_len(adapter,1002 LANCER_VPD_PF_FILE);1003 else1004 return lancer_cmd_get_file_len(adapter,1005 LANCER_VPD_VF_FILE);1006 } else {1007 return BE_READ_SEEPROM_LEN;1008 }1009}1010 1011static int be_read_eeprom(struct net_device *netdev,1012 struct ethtool_eeprom *eeprom, uint8_t *data)1013{1014 struct be_adapter *adapter = netdev_priv(netdev);1015 struct be_dma_mem eeprom_cmd;1016 struct be_cmd_resp_seeprom_read *resp;1017 int status;1018 1019 if (!eeprom->len)1020 return -EINVAL;1021 1022 if (lancer_chip(adapter)) {1023 if (be_physfn(adapter))1024 return lancer_cmd_read_file(adapter, LANCER_VPD_PF_FILE,1025 eeprom->len, data);1026 else1027 return lancer_cmd_read_file(adapter, LANCER_VPD_VF_FILE,1028 eeprom->len, data);1029 }1030 1031 eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16);1032 1033 memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));1034 eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);1035 eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,1036 eeprom_cmd.size, &eeprom_cmd.dma,1037 GFP_KERNEL);1038 1039 if (!eeprom_cmd.va)1040 return -ENOMEM;1041 1042 status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);1043 1044 if (!status) {1045 resp = eeprom_cmd.va;1046 memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);1047 }1048 dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,1049 eeprom_cmd.dma);1050 1051 return be_cmd_status(status);1052}1053 1054static u32 be_get_msg_level(struct net_device *netdev)1055{1056 struct be_adapter *adapter = netdev_priv(netdev);1057 1058 return adapter->msg_enable;1059}1060 1061static void be_set_msg_level(struct net_device *netdev, u32 level)1062{1063 struct be_adapter *adapter = netdev_priv(netdev);1064 1065 if (adapter->msg_enable == level)1066 return;1067 1068 if ((level & NETIF_MSG_HW) != (adapter->msg_enable & NETIF_MSG_HW))1069 if (BEx_chip(adapter))1070 be_cmd_set_fw_log_level(adapter, level & NETIF_MSG_HW ?1071 FW_LOG_LEVEL_DEFAULT :1072 FW_LOG_LEVEL_FATAL);1073 adapter->msg_enable = level;1074}1075 1076static u64 be_get_rss_hash_opts(struct be_adapter *adapter, u64 flow_type)1077{1078 u64 data = 0;1079 1080 switch (flow_type) {1081 case TCP_V4_FLOW:1082 if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV4)1083 data |= RXH_IP_DST | RXH_IP_SRC;1084 if (adapter->rss_info.rss_flags & RSS_ENABLE_TCP_IPV4)1085 data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;1086 break;1087 case UDP_V4_FLOW:1088 if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV4)1089 data |= RXH_IP_DST | RXH_IP_SRC;1090 if (adapter->rss_info.rss_flags & RSS_ENABLE_UDP_IPV4)1091 data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;1092 break;1093 case TCP_V6_FLOW:1094 if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV6)1095 data |= RXH_IP_DST | RXH_IP_SRC;1096 if (adapter->rss_info.rss_flags & RSS_ENABLE_TCP_IPV6)1097 data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;1098 break;1099 case UDP_V6_FLOW:1100 if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV6)1101 data |= RXH_IP_DST | RXH_IP_SRC;1102 if (adapter->rss_info.rss_flags & RSS_ENABLE_UDP_IPV6)1103 data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;1104 break;1105 }1106 1107 return data;1108}1109 1110static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,1111 u32 *rule_locs)1112{1113 struct be_adapter *adapter = netdev_priv(netdev);1114 1115 if (!be_multi_rxq(adapter)) {1116 dev_info(&adapter->pdev->dev,1117 "ethtool::get_rxnfc: RX flow hashing is disabled\n");1118 return -EINVAL;1119 }1120 1121 switch (cmd->cmd) {1122 case ETHTOOL_GRXFH:1123 cmd->data = be_get_rss_hash_opts(adapter, cmd->flow_type);1124 break;1125 case ETHTOOL_GRXRINGS:1126 cmd->data = adapter->num_rx_qs;1127 break;1128 default:1129 return -EINVAL;1130 }1131 1132 return 0;1133}1134 1135static int be_set_rss_hash_opts(struct be_adapter *adapter,1136 struct ethtool_rxnfc *cmd)1137{1138 int status;1139 u32 rss_flags = adapter->rss_info.rss_flags;1140 1141 if (cmd->data != L3_RSS_FLAGS &&1142 cmd->data != (L3_RSS_FLAGS | L4_RSS_FLAGS))1143 return -EINVAL;1144 1145 switch (cmd->flow_type) {1146 case TCP_V4_FLOW:1147 if (cmd->data == L3_RSS_FLAGS)1148 rss_flags &= ~RSS_ENABLE_TCP_IPV4;1149 else if (cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS))1150 rss_flags |= RSS_ENABLE_IPV4 |1151 RSS_ENABLE_TCP_IPV4;1152 break;1153 case TCP_V6_FLOW:1154 if (cmd->data == L3_RSS_FLAGS)1155 rss_flags &= ~RSS_ENABLE_TCP_IPV6;1156 else if (cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS))1157 rss_flags |= RSS_ENABLE_IPV6 |1158 RSS_ENABLE_TCP_IPV6;1159 break;1160 case UDP_V4_FLOW:1161 if ((cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS)) &&1162 BEx_chip(adapter))1163 return -EINVAL;1164 1165 if (cmd->data == L3_RSS_FLAGS)1166 rss_flags &= ~RSS_ENABLE_UDP_IPV4;1167 else if (cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS))1168 rss_flags |= RSS_ENABLE_IPV4 |1169 RSS_ENABLE_UDP_IPV4;1170 break;1171 case UDP_V6_FLOW:1172 if ((cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS)) &&1173 BEx_chip(adapter))1174 return -EINVAL;1175 1176 if (cmd->data == L3_RSS_FLAGS)1177 rss_flags &= ~RSS_ENABLE_UDP_IPV6;1178 else if (cmd->data == (L3_RSS_FLAGS | L4_RSS_FLAGS))1179 rss_flags |= RSS_ENABLE_IPV6 |1180 RSS_ENABLE_UDP_IPV6;1181 break;1182 default:1183 return -EINVAL;1184 }1185 1186 if (rss_flags == adapter->rss_info.rss_flags)1187 return 0;1188 1189 status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,1190 rss_flags, RSS_INDIR_TABLE_LEN,1191 adapter->rss_info.rss_hkey);1192 if (!status)1193 adapter->rss_info.rss_flags = rss_flags;1194 1195 return be_cmd_status(status);1196}1197 1198static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)1199{1200 struct be_adapter *adapter = netdev_priv(netdev);1201 int status = 0;1202 1203 if (!be_multi_rxq(adapter)) {1204 dev_err(&adapter->pdev->dev,1205 "ethtool::set_rxnfc: RX flow hashing is disabled\n");1206 return -EINVAL;1207 }1208 1209 switch (cmd->cmd) {1210 case ETHTOOL_SRXFH:1211 status = be_set_rss_hash_opts(adapter, cmd);1212 break;1213 default:1214 return -EINVAL;1215 }1216 1217 return status;1218}1219 1220static void be_get_channels(struct net_device *netdev,1221 struct ethtool_channels *ch)1222{1223 struct be_adapter *adapter = netdev_priv(netdev);1224 u16 num_rx_irqs = max_t(u16, adapter->num_rss_qs, 1);1225 1226 /* num_tx_qs is always same as the number of irqs used for TX */1227 ch->combined_count = min(adapter->num_tx_qs, num_rx_irqs);1228 ch->rx_count = num_rx_irqs - ch->combined_count;1229 ch->tx_count = adapter->num_tx_qs - ch->combined_count;1230 1231 ch->max_combined = be_max_qp_irqs(adapter);1232 /* The user must create atleast one combined channel */1233 ch->max_rx = be_max_rx_irqs(adapter) - 1;1234 ch->max_tx = be_max_tx_irqs(adapter) - 1;1235}1236 1237static int be_set_channels(struct net_device *netdev,1238 struct ethtool_channels *ch)1239{1240 struct be_adapter *adapter = netdev_priv(netdev);1241 int status;1242 1243 /* we support either only combined channels or a combination of1244 * combined and either RX-only or TX-only channels.1245 */1246 if (ch->other_count || !ch->combined_count ||1247 (ch->rx_count && ch->tx_count))1248 return -EINVAL;1249 1250 if (ch->combined_count > be_max_qp_irqs(adapter) ||1251 (ch->rx_count &&1252 (ch->rx_count + ch->combined_count) > be_max_rx_irqs(adapter)) ||1253 (ch->tx_count &&1254 (ch->tx_count + ch->combined_count) > be_max_tx_irqs(adapter)))1255 return -EINVAL;1256 1257 adapter->cfg_num_rx_irqs = ch->combined_count + ch->rx_count;1258 adapter->cfg_num_tx_irqs = ch->combined_count + ch->tx_count;1259 1260 status = be_update_queues(adapter);1261 return be_cmd_status(status);1262}1263 1264static u32 be_get_rxfh_indir_size(struct net_device *netdev)1265{1266 return RSS_INDIR_TABLE_LEN;1267}1268 1269static u32 be_get_rxfh_key_size(struct net_device *netdev)1270{1271 return RSS_HASH_KEY_LEN;1272}1273 1274static int be_get_rxfh(struct net_device *netdev,1275 struct ethtool_rxfh_param *rxfh)1276{1277 struct be_adapter *adapter = netdev_priv(netdev);1278 int i;1279 struct rss_info *rss = &adapter->rss_info;1280 1281 if (rxfh->indir) {1282 for (i = 0; i < RSS_INDIR_TABLE_LEN; i++)1283 rxfh->indir[i] = rss->rss_queue[i];1284 }1285 1286 if (rxfh->key)1287 memcpy(rxfh->key, rss->rss_hkey, RSS_HASH_KEY_LEN);1288 1289 rxfh->hfunc = ETH_RSS_HASH_TOP;1290 1291 return 0;1292}1293 1294static int be_set_rxfh(struct net_device *netdev,1295 struct ethtool_rxfh_param *rxfh,1296 struct netlink_ext_ack *extack)1297{1298 int rc = 0, i, j;1299 struct be_adapter *adapter = netdev_priv(netdev);1300 u8 *hkey = rxfh->key;1301 u8 rsstable[RSS_INDIR_TABLE_LEN];1302 1303 /* We do not allow change in unsupported parameters */1304 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&1305 rxfh->hfunc != ETH_RSS_HASH_TOP)1306 return -EOPNOTSUPP;1307 1308 if (rxfh->indir) {1309 struct be_rx_obj *rxo;1310 1311 for (i = 0; i < RSS_INDIR_TABLE_LEN; i++) {1312 j = rxfh->indir[i];1313 rxo = &adapter->rx_obj[j];1314 rsstable[i] = rxo->rss_id;1315 adapter->rss_info.rss_queue[i] = j;1316 }1317 } else {1318 memcpy(rsstable, adapter->rss_info.rsstable,1319 RSS_INDIR_TABLE_LEN);1320 }1321 1322 if (!hkey)1323 hkey = adapter->rss_info.rss_hkey;1324 1325 rc = be_cmd_rss_config(adapter, rsstable,1326 adapter->rss_info.rss_flags,1327 RSS_INDIR_TABLE_LEN, hkey);1328 if (rc) {1329 adapter->rss_info.rss_flags = RSS_ENABLE_NONE;1330 return -EIO;1331 }1332 memcpy(adapter->rss_info.rss_hkey, hkey, RSS_HASH_KEY_LEN);1333 memcpy(adapter->rss_info.rsstable, rsstable,1334 RSS_INDIR_TABLE_LEN);1335 return 0;1336}1337 1338static int be_get_module_info(struct net_device *netdev,1339 struct ethtool_modinfo *modinfo)1340{1341 struct be_adapter *adapter = netdev_priv(netdev);1342 u8 page_data[PAGE_DATA_LEN];1343 int status;1344 1345 if (!check_privilege(adapter, MAX_PRIVILEGES))1346 return -EOPNOTSUPP;1347 1348 status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,1349 0, PAGE_DATA_LEN, page_data);1350 if (!status) {1351 if (!page_data[SFP_PLUS_SFF_8472_COMP]) {1352 modinfo->type = ETH_MODULE_SFF_8079;1353 modinfo->eeprom_len = PAGE_DATA_LEN;1354 } else {1355 modinfo->type = ETH_MODULE_SFF_8472;1356 modinfo->eeprom_len = 2 * PAGE_DATA_LEN;1357 }1358 }1359 return be_cmd_status(status);1360}1361 1362static int be_get_module_eeprom(struct net_device *netdev,1363 struct ethtool_eeprom *eeprom, u8 *data)1364{1365 struct be_adapter *adapter = netdev_priv(netdev);1366 int status;1367 u32 begin, end;1368 1369 if (!check_privilege(adapter, MAX_PRIVILEGES))1370 return -EOPNOTSUPP;1371 1372 begin = eeprom->offset;1373 end = eeprom->offset + eeprom->len;1374 1375 if (begin < PAGE_DATA_LEN) {1376 status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, begin,1377 min_t(u32, end, PAGE_DATA_LEN) - begin,1378 data);1379 if (status)1380 goto err;1381 1382 data += PAGE_DATA_LEN - begin;1383 begin = PAGE_DATA_LEN;1384 }1385 1386 if (end > PAGE_DATA_LEN) {1387 status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A2,1388 begin - PAGE_DATA_LEN,1389 end - begin, data);1390 if (status)1391 goto err;1392 }1393err:1394 return be_cmd_status(status);1395}1396 1397static u32 be_get_priv_flags(struct net_device *netdev)1398{1399 struct be_adapter *adapter = netdev_priv(netdev);1400 1401 return adapter->priv_flags;1402}1403 1404static int be_set_priv_flags(struct net_device *netdev, u32 flags)1405{1406 struct be_adapter *adapter = netdev_priv(netdev);1407 bool tpe_old = !!(adapter->priv_flags & BE_DISABLE_TPE_RECOVERY);1408 bool tpe_new = !!(flags & BE_DISABLE_TPE_RECOVERY);1409 1410 if (tpe_old != tpe_new) {1411 if (tpe_new) {1412 adapter->priv_flags |= BE_DISABLE_TPE_RECOVERY;1413 dev_info(&adapter->pdev->dev,1414 "HW error recovery is disabled\n");1415 } else {1416 adapter->priv_flags &= ~BE_DISABLE_TPE_RECOVERY;1417 dev_info(&adapter->pdev->dev,1418 "HW error recovery is enabled\n");1419 }1420 }1421 1422 return 0;1423}1424 1425const struct ethtool_ops be_ethtool_ops = {1426 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |1427 ETHTOOL_COALESCE_USE_ADAPTIVE |1428 ETHTOOL_COALESCE_USECS_LOW_HIGH,1429 .get_drvinfo = be_get_drvinfo,1430 .get_wol = be_get_wol,1431 .set_wol = be_set_wol,1432 .get_link = ethtool_op_get_link,1433 .get_eeprom_len = be_get_eeprom_len,1434 .get_eeprom = be_read_eeprom,1435 .get_coalesce = be_get_coalesce,1436 .set_coalesce = be_set_coalesce,1437 .get_ringparam = be_get_ringparam,1438 .get_pauseparam = be_get_pauseparam,1439 .set_pauseparam = be_set_pauseparam,1440 .set_priv_flags = be_set_priv_flags,1441 .get_priv_flags = be_get_priv_flags,1442 .get_strings = be_get_stat_strings,1443 .set_phys_id = be_set_phys_id,1444 .set_dump = be_set_dump,1445 .get_msglevel = be_get_msg_level,1446 .set_msglevel = be_set_msg_level,1447 .get_sset_count = be_get_sset_count,1448 .get_ethtool_stats = be_get_ethtool_stats,1449 .flash_device = be_do_flash,1450 .self_test = be_self_test,1451 .get_rxnfc = be_get_rxnfc,1452 .set_rxnfc = be_set_rxnfc,1453 .get_rxfh_indir_size = be_get_rxfh_indir_size,1454 .get_rxfh_key_size = be_get_rxfh_key_size,1455 .get_rxfh = be_get_rxfh,1456 .set_rxfh = be_set_rxfh,1457 .get_dump_flag = be_get_dump_flag,1458 .get_dump_data = be_get_dump_data,1459 .get_channels = be_get_channels,1460 .set_channels = be_set_channels,1461 .get_module_info = be_get_module_info,1462 .get_module_eeprom = be_get_module_eeprom,1463 .get_link_ksettings = be_get_link_ksettings,1464};1465