17268f33eSAlexander Lobakin // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver 3e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 4c4fad2a5SAlexander Lobakin * Copyright (c) 2019-2020 Marvell International Ltd. 5133fac0eSSudarsana Kalluru */ 67268f33eSAlexander Lobakin 7133fac0eSSudarsana Kalluru #include <linux/version.h> 8133fac0eSSudarsana Kalluru #include <linux/types.h> 9133fac0eSSudarsana Kalluru #include <linux/netdevice.h> 1016f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h> 11133fac0eSSudarsana Kalluru #include <linux/ethtool.h> 12133fac0eSSudarsana Kalluru #include <linux/string.h> 13133fac0eSSudarsana Kalluru #include <linux/pci.h> 14133fac0eSSudarsana Kalluru #include <linux/capability.h> 15f29ffdb6SMintz, Yuval #include <linux/vmalloc.h> 16bdb5d8ecSAlexander Lobakin #include <linux/phylink.h> 17bdb5d8ecSAlexander Lobakin 18133fac0eSSudarsana Kalluru #include "qede.h" 194c55215cSSudarsana Reddy Kalluru #include "qede_ptp.h" 20133fac0eSSudarsana Kalluru 21133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \ 22133fac0eSSudarsana Kalluru (offsetof(struct qede_rx_queue, stat_name)) 23133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name) 24133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \ 25133fac0eSSudarsana Kalluru {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} 2616f46bf0SSudarsana Reddy Kalluru 2716f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100 28d44a3cedSSudarsana Reddy Kalluru #define QEDE_DUMP_VERSION 0x1 29d44a3cedSSudarsana Reddy Kalluru #define QEDE_DUMP_NVM_ARG_COUNT 2 3016f46bf0SSudarsana Reddy Kalluru 31133fac0eSSudarsana Kalluru static const struct { 32133fac0eSSudarsana Kalluru u64 offset; 33133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 34133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = { 3568db9ec2SSudarsana Reddy Kalluru QEDE_RQSTAT(rcv_pkts), 36133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_hw_errors), 37133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_alloc_errors), 38c72a6125SManish Chopra QEDE_RQSTAT(rx_ip_frags), 39496e0517SMintz, Yuval QEDE_RQSTAT(xdp_no_pass), 40133fac0eSSudarsana Kalluru }; 41133fac0eSSudarsana Kalluru 42133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) 4368db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \ 4468db9ec2SSudarsana Reddy Kalluru (offsetof(struct qede_tx_queue, stat_name)) 4568db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name) 4668db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \ 4768db9ec2SSudarsana Reddy Kalluru {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)} 4868db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr) 4968db9ec2SSudarsana Reddy Kalluru static const struct { 5068db9ec2SSudarsana Reddy Kalluru u64 offset; 5168db9ec2SSudarsana Reddy Kalluru char string[ETH_GSTRING_LEN]; 5268db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = { 5368db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(xmit_pkts), 5468db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(stopped_cnt), 55dcc6abaeSMichael Shteinbok QEDE_TQSTAT(tx_mem_alloc_err), 5668db9ec2SSudarsana Reddy Kalluru }; 5768db9ec2SSudarsana Reddy Kalluru 589c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \ 599c79ddaaSMintz, Yuval (offsetof(type, stat_name) + (base)) 604dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name) (#stat_name) 619c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \ 629c79ddaaSMintz, Yuval {QEDE_STAT_OFFSET(stat_name, type, base), \ 639c79ddaaSMintz, Yuval QEDE_STAT_STRING(stat_name), \ 649c79ddaaSMintz, Yuval attr} 659c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \ 669c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0) 679c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \ 689c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, \ 699c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY)) 709c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \ 719c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_bb, \ 729c79ddaaSMintz, Yuval offsetof(struct qede_stats, bb), \ 739c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY)) 749c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \ 759c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_ah, \ 769c79ddaaSMintz, Yuval offsetof(struct qede_stats, ah), \ 779c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY)) 78133fac0eSSudarsana Kalluru static const struct { 79133fac0eSSudarsana Kalluru u64 offset; 80133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 819c79ddaaSMintz, Yuval unsigned long attr; 829c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY 0 839c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY 1 849c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY 2 85133fac0eSSudarsana Kalluru } qede_stats_arr[] = { 86133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes), 87133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes), 88133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes), 89133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts), 90133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts), 91133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts), 92133fac0eSSudarsana Kalluru 93133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes), 94133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes), 95133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes), 96133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts), 97133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts), 98133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts), 99133fac0eSSudarsana Kalluru 100133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets), 101d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets), 102d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets), 103d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets), 104d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets), 105d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets), 1069c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets), 1079c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets), 1089c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets), 1099c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets), 1109c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets), 1119c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets), 112133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets), 113133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets), 114133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets), 115133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets), 116133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets), 117133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets), 1189c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets), 1199c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets), 1209c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets), 1219c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets), 1229c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets), 123133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames), 124133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames), 125133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames), 126133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames), 127133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames), 128133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames), 129133fac0eSSudarsana Kalluru 130133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors), 131133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors), 132133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors), 133133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets), 134133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers), 135133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets), 136133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments), 1379c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_lpi_entry_count), 1389c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_total_collisions), 139133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates), 140133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards), 141133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards), 142133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards), 143133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards), 144608e00d0SManish Chopra QEDE_PF_STAT(gft_filter_drop), 145133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1461a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1471a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 148133fac0eSSudarsana Kalluru 149133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 150133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 151133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 152133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 153133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 15432d26a68SSudarsana Reddy Kalluru 15532d26a68SSudarsana Reddy Kalluru QEDE_STAT(link_change_count), 1569adebac3SSudarsana Reddy Kalluru QEDE_STAT(ptp_skip_txts), 157133fac0eSSudarsana Kalluru }; 158133fac0eSSudarsana Kalluru 159133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 1609c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \ 1619c79ddaaSMintz, Yuval test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr) 1629c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \ 1639c79ddaaSMintz, Yuval test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr) 1649c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \ 1659c79ddaaSMintz, Yuval test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr) 166133fac0eSSudarsana Kalluru 167f3e72109SYuval Mintz enum { 168f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 169f15cff04SSudarsana Reddy Kalluru QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */ 1707d9acd87SIgor Russkikh QEDE_PRI_FLAG_RECOVER_ON_ERROR, 171f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 172f3e72109SYuval Mintz }; 173f3e72109SYuval Mintz 174f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 175f3e72109SYuval Mintz "Coupled-Function", 176f15cff04SSudarsana Reddy Kalluru "SmartAN capable", 1777d9acd87SIgor Russkikh "Recover on error", 178f3e72109SYuval Mintz }; 179f3e72109SYuval Mintz 1803044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 18116f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 1823044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 1833044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 1843044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 1853044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 1867a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 1873044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 1883044a02eSSudarsana Reddy Kalluru }; 1893044a02eSSudarsana Reddy Kalluru 1903044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 19116f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 1923044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 1933044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 1943044a02eSSudarsana Reddy Kalluru "Register (online)\t", 1953044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 1967a4b21b7SMintz, Yuval "Nvram (online)\t\t", 1973044a02eSSudarsana Reddy Kalluru }; 1983044a02eSSudarsana Reddy Kalluru 1991d4e4eccSAlexander Lobakin /* Forced speed capabilities maps */ 2001d4e4eccSAlexander Lobakin 2011d4e4eccSAlexander Lobakin struct qede_forced_speed_map { 2021d4e4eccSAlexander Lobakin u32 speed; 2031d4e4eccSAlexander Lobakin __ETHTOOL_DECLARE_LINK_MODE_MASK(caps); 2041d4e4eccSAlexander Lobakin 2051d4e4eccSAlexander Lobakin const u32 *cap_arr; 2061d4e4eccSAlexander Lobakin u32 arr_size; 2071d4e4eccSAlexander Lobakin }; 2081d4e4eccSAlexander Lobakin 2091d4e4eccSAlexander Lobakin #define QEDE_FORCED_SPEED_MAP(value) \ 2101d4e4eccSAlexander Lobakin { \ 2111d4e4eccSAlexander Lobakin .speed = SPEED_##value, \ 2121d4e4eccSAlexander Lobakin .cap_arr = qede_forced_speed_##value, \ 2131d4e4eccSAlexander Lobakin .arr_size = ARRAY_SIZE(qede_forced_speed_##value), \ 2141d4e4eccSAlexander Lobakin } 2151d4e4eccSAlexander Lobakin 2161d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_1000[] __initconst = { 2171d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 2181d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 2191d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 2201d4e4eccSAlexander Lobakin }; 2211d4e4eccSAlexander Lobakin 2221d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_10000[] __initconst = { 2231d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 2241d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 2251d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 2261d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, 2271d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 2281d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 2291d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, 2301d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, 2311d4e4eccSAlexander Lobakin }; 2321d4e4eccSAlexander Lobakin 2331d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_20000[] __initconst = { 2341d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT, 2351d4e4eccSAlexander Lobakin }; 2361d4e4eccSAlexander Lobakin 2371d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_25000[] __initconst = { 2381d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 2391d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 2401d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 2411d4e4eccSAlexander Lobakin }; 2421d4e4eccSAlexander Lobakin 2431d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_40000[] __initconst = { 2441d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 2451d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 2461d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 2471d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 2481d4e4eccSAlexander Lobakin }; 2491d4e4eccSAlexander Lobakin 2501d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_50000[] __initconst = { 2511d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 2521d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 2531d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 2541d4e4eccSAlexander Lobakin }; 2551d4e4eccSAlexander Lobakin 2561d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_100000[] __initconst = { 2571d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 2581d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 2591d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 2601d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 2611d4e4eccSAlexander Lobakin }; 2621d4e4eccSAlexander Lobakin 2631d4e4eccSAlexander Lobakin static struct qede_forced_speed_map qede_forced_speed_maps[] __ro_after_init = { 2641d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(1000), 2651d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(10000), 2661d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(20000), 2671d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(25000), 2681d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(40000), 2691d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(50000), 2701d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(100000), 2711d4e4eccSAlexander Lobakin }; 2721d4e4eccSAlexander Lobakin 2731d4e4eccSAlexander Lobakin void __init qede_forced_speed_maps_init(void) 2741d4e4eccSAlexander Lobakin { 2751d4e4eccSAlexander Lobakin struct qede_forced_speed_map *map; 2761d4e4eccSAlexander Lobakin u32 i; 2771d4e4eccSAlexander Lobakin 2781d4e4eccSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) { 2791d4e4eccSAlexander Lobakin map = qede_forced_speed_maps + i; 2801d4e4eccSAlexander Lobakin 2811d4e4eccSAlexander Lobakin linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps); 2821d4e4eccSAlexander Lobakin map->cap_arr = NULL; 2831d4e4eccSAlexander Lobakin map->arr_size = 0; 2841d4e4eccSAlexander Lobakin } 2851d4e4eccSAlexander Lobakin } 2861d4e4eccSAlexander Lobakin 2871d4e4eccSAlexander Lobakin /* Ethtool callbacks */ 2881d4e4eccSAlexander Lobakin 2894dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev, 2904dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf) 2914dbcd640SMintz, Yuval { 2924dbcd640SMintz, Yuval int i; 2934dbcd640SMintz, Yuval 2944dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 295cb6aeb07SMintz, Yuval if (txq->is_xdp) 296cb6aeb07SMintz, Yuval sprintf(*buf, "%d [XDP]: %s", 297cb6aeb07SMintz, Yuval QEDE_TXQ_XDP_TO_IDX(edev, txq), 298cb6aeb07SMintz, Yuval qede_tqstats_arr[i].string); 299cb6aeb07SMintz, Yuval else 3005e7baf0fSManish Chopra sprintf(*buf, "%d_%d: %s", txq->index, txq->cos, 3014dbcd640SMintz, Yuval qede_tqstats_arr[i].string); 3024dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 3034dbcd640SMintz, Yuval } 3044dbcd640SMintz, Yuval } 3054dbcd640SMintz, Yuval 3064dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev, 3074dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf) 3084dbcd640SMintz, Yuval { 3094dbcd640SMintz, Yuval int i; 3104dbcd640SMintz, Yuval 3114dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 3124dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id, 3134dbcd640SMintz, Yuval qede_rqstats_arr[i].string); 3144dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 3154dbcd640SMintz, Yuval } 3164dbcd640SMintz, Yuval } 3174dbcd640SMintz, Yuval 3189c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index) 3199c79ddaaSMintz, Yuval { 3209c79ddaaSMintz, Yuval return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) || 3219c79ddaaSMintz, Yuval (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) || 3229c79ddaaSMintz, Yuval (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index)); 3239c79ddaaSMintz, Yuval } 3249c79ddaaSMintz, Yuval 325133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 326133fac0eSSudarsana Kalluru { 3274dbcd640SMintz, Yuval struct qede_fastpath *fp; 3284dbcd640SMintz, Yuval int i; 329133fac0eSSudarsana Kalluru 3304dbcd640SMintz, Yuval /* Account for queue statistics */ 3314dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 3324dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 33368db9ec2SSudarsana Reddy Kalluru 3344dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 3354dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf); 3364dbcd640SMintz, Yuval 337cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 338cb6aeb07SMintz, Yuval qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf); 339cb6aeb07SMintz, Yuval 3405e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 3415e7baf0fSManish Chopra int cos; 3425e7baf0fSManish Chopra 3435e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 3445e7baf0fSManish Chopra qede_get_strings_stats_txq(edev, 3455e7baf0fSManish Chopra &fp->txq[cos], &buf); 3465e7baf0fSManish Chopra } 347cbbf049aSMintz, Yuval } 348cbbf049aSMintz, Yuval 3494dbcd640SMintz, Yuval /* Account for non-queue statistics */ 3504dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 3519c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 352fefb0202SYuval Mintz continue; 3534dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string); 3544dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN; 355133fac0eSSudarsana Kalluru } 356133fac0eSSudarsana Kalluru } 357133fac0eSSudarsana Kalluru 358133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 359133fac0eSSudarsana Kalluru { 360133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 361133fac0eSSudarsana Kalluru 362133fac0eSSudarsana Kalluru switch (stringset) { 363133fac0eSSudarsana Kalluru case ETH_SS_STATS: 364133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 365133fac0eSSudarsana Kalluru break; 366f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 367f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 368f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 369f3e72109SYuval Mintz break; 3703044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 3713044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 3723044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 3733044a02eSSudarsana Reddy Kalluru break; 374133fac0eSSudarsana Kalluru default: 375133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 376133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 377133fac0eSSudarsana Kalluru } 378133fac0eSSudarsana Kalluru } 379133fac0eSSudarsana Kalluru 3804dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) 3814dbcd640SMintz, Yuval { 3824dbcd640SMintz, Yuval int i; 3834dbcd640SMintz, Yuval 3844dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 3854dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); 3864dbcd640SMintz, Yuval (*buf)++; 3874dbcd640SMintz, Yuval } 3884dbcd640SMintz, Yuval } 3894dbcd640SMintz, Yuval 3904dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) 3914dbcd640SMintz, Yuval { 3924dbcd640SMintz, Yuval int i; 3934dbcd640SMintz, Yuval 3944dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 3954dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); 3964dbcd640SMintz, Yuval (*buf)++; 3974dbcd640SMintz, Yuval } 3984dbcd640SMintz, Yuval } 3994dbcd640SMintz, Yuval 400133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 401133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 402133fac0eSSudarsana Kalluru { 403133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 4044dbcd640SMintz, Yuval struct qede_fastpath *fp; 4054dbcd640SMintz, Yuval int i; 406133fac0eSSudarsana Kalluru 407133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 408133fac0eSSudarsana Kalluru 409567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */ 410567b3c12SMintz, Yuval __qede_lock(edev); 411567b3c12SMintz, Yuval 4124dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 4134dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 414133fac0eSSudarsana Kalluru 4154dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 4164dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf); 41768db9ec2SSudarsana Reddy Kalluru 418cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 419cb6aeb07SMintz, Yuval qede_get_ethtool_stats_txq(fp->xdp_tx, &buf); 420cb6aeb07SMintz, Yuval 4215e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 4225e7baf0fSManish Chopra int cos; 4235e7baf0fSManish Chopra 4245e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 4255e7baf0fSManish Chopra qede_get_ethtool_stats_txq(&fp->txq[cos], &buf); 4265e7baf0fSManish Chopra } 42768db9ec2SSudarsana Reddy Kalluru } 42868db9ec2SSudarsana Reddy Kalluru 4294dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 4309c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 431fefb0202SYuval Mintz continue; 4324dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) + 4334dbcd640SMintz, Yuval qede_stats_arr[i].offset)); 4344dbcd640SMintz, Yuval 4354dbcd640SMintz, Yuval buf++; 436fefb0202SYuval Mintz } 437133fac0eSSudarsana Kalluru 438567b3c12SMintz, Yuval __qede_unlock(edev); 439133fac0eSSudarsana Kalluru } 440133fac0eSSudarsana Kalluru 441133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 442133fac0eSSudarsana Kalluru { 443133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 4449c79ddaaSMintz, Yuval int num_stats = QEDE_NUM_STATS, i; 445133fac0eSSudarsana Kalluru 446133fac0eSSudarsana Kalluru switch (stringset) { 447133fac0eSSudarsana Kalluru case ETH_SS_STATS: 448fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 4499c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 450fefb0202SYuval Mintz num_stats--; 4514dbcd640SMintz, Yuval 4524dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */ 4535e7baf0fSManish Chopra num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * 4545e7baf0fSManish Chopra edev->dev_info.num_tc; 4554dbcd640SMintz, Yuval 4564dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */ 4574dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; 4584dbcd640SMintz, Yuval 459cb6aeb07SMintz, Yuval /* Account for XDP statistics [if needed] */ 460cb6aeb07SMintz, Yuval if (edev->xdp_prog) 461cb6aeb07SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; 4624dbcd640SMintz, Yuval return num_stats; 4634dbcd640SMintz, Yuval 464f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 465f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 4663044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 4676ecb0a0cSYuval Mintz if (!IS_VF(edev)) 4683044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 4696ecb0a0cSYuval Mintz else 4706ecb0a0cSYuval Mintz return 0; 471133fac0eSSudarsana Kalluru default: 472133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 473133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 474133fac0eSSudarsana Kalluru return -EINVAL; 475133fac0eSSudarsana Kalluru } 476133fac0eSSudarsana Kalluru } 477133fac0eSSudarsana Kalluru 478f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 479f3e72109SYuval Mintz { 480f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 481f15cff04SSudarsana Reddy Kalluru u32 flags = 0; 482f3e72109SYuval Mintz 483f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) 484f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_CMT); 485f15cff04SSudarsana Reddy Kalluru 486f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.smart_an) 487f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT); 488f15cff04SSudarsana Reddy Kalluru 4897d9acd87SIgor Russkikh if (edev->err_flags & BIT(QEDE_ERR_IS_RECOVERABLE)) 4907d9acd87SIgor Russkikh flags |= BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR); 4917d9acd87SIgor Russkikh 492f15cff04SSudarsana Reddy Kalluru return flags; 493f3e72109SYuval Mintz } 494f3e72109SYuval Mintz 4957d9acd87SIgor Russkikh static int qede_set_priv_flags(struct net_device *dev, u32 flags) 4967d9acd87SIgor Russkikh { 4977d9acd87SIgor Russkikh struct qede_dev *edev = netdev_priv(dev); 4987d9acd87SIgor Russkikh u32 cflags = qede_get_priv_flags(dev); 4997d9acd87SIgor Russkikh u32 dflags = flags ^ cflags; 5007d9acd87SIgor Russkikh 5017d9acd87SIgor Russkikh /* can only change RECOVER_ON_ERROR flag */ 5027d9acd87SIgor Russkikh if (dflags & ~BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR)) 5037d9acd87SIgor Russkikh return -EINVAL; 5047d9acd87SIgor Russkikh 5057d9acd87SIgor Russkikh if (flags & BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR)) 5067d9acd87SIgor Russkikh set_bit(QEDE_ERR_IS_RECOVERABLE, &edev->err_flags); 5077d9acd87SIgor Russkikh else 5087d9acd87SIgor Russkikh clear_bit(QEDE_ERR_IS_RECOVERABLE, &edev->err_flags); 5097d9acd87SIgor Russkikh 5107d9acd87SIgor Russkikh return 0; 5117d9acd87SIgor Russkikh } 5127d9acd87SIgor Russkikh 513054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 514054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 515133fac0eSSudarsana Kalluru { 516bdb5d8ecSAlexander Lobakin typeof(cmd->link_modes) *link_modes = &cmd->link_modes; 517054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 518133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 519133fac0eSSudarsana Kalluru struct qed_link_output current_link; 520133fac0eSSudarsana Kalluru 521567b3c12SMintz, Yuval __qede_lock(edev); 522567b3c12SMintz, Yuval 523133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 524133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 525133fac0eSSudarsana Kalluru 526bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->supported, current_link.supported_caps); 527bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->advertising, current_link.advertised_caps); 528bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->lp_advertising, current_link.lp_caps); 529054c67d1SSudarsana Reddy Kalluru 530133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 531054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 532054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 533133fac0eSSudarsana Kalluru } else { 534054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 535054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 536133fac0eSSudarsana Kalluru } 537567b3c12SMintz, Yuval 538567b3c12SMintz, Yuval __qede_unlock(edev); 539567b3c12SMintz, Yuval 540054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 541054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 542133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 543133fac0eSSudarsana Kalluru 544133fac0eSSudarsana Kalluru return 0; 545133fac0eSSudarsana Kalluru } 546133fac0eSSudarsana Kalluru 547054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 548054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 549133fac0eSSudarsana Kalluru { 550054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 551133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 5521d4e4eccSAlexander Lobakin const struct qede_forced_speed_map *map; 553133fac0eSSudarsana Kalluru struct qed_link_output current_link; 554133fac0eSSudarsana Kalluru struct qed_link_params params; 5551d4e4eccSAlexander Lobakin u32 i; 556133fac0eSSudarsana Kalluru 557fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 558054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 559133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 560133fac0eSSudarsana Kalluru } 561133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 562133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 563133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 564133fac0eSSudarsana Kalluru 565133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 566133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 567bdb5d8ecSAlexander Lobakin 568054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 569bdb5d8ecSAlexander Lobakin if (!phylink_test(current_link.supported_caps, Autoneg)) { 570161adb04Ssudarsana.kalluru@cavium.com DP_INFO(edev, "Auto negotiation is not supported\n"); 571161adb04Ssudarsana.kalluru@cavium.com return -EOPNOTSUPP; 572161adb04Ssudarsana.kalluru@cavium.com } 573161adb04Ssudarsana.kalluru@cavium.com 574133fac0eSSudarsana Kalluru params.autoneg = true; 575133fac0eSSudarsana Kalluru params.forced_speed = 0; 576bdb5d8ecSAlexander Lobakin 577bdb5d8ecSAlexander Lobakin linkmode_copy(params.adv_speeds, cmd->link_modes.advertising); 578133fac0eSSudarsana Kalluru } else { /* forced speed */ 579133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 580133fac0eSSudarsana Kalluru params.autoneg = false; 581054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 582bdb5d8ecSAlexander Lobakin 5831d4e4eccSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) { 5841d4e4eccSAlexander Lobakin map = qede_forced_speed_maps + i; 585bdb5d8ecSAlexander Lobakin 5861d4e4eccSAlexander Lobakin if (base->speed != map->speed || 5871d4e4eccSAlexander Lobakin !linkmode_intersects(current_link.supported_caps, 5881d4e4eccSAlexander Lobakin map->caps)) 5891d4e4eccSAlexander Lobakin continue; 5901d4e4eccSAlexander Lobakin 5911d4e4eccSAlexander Lobakin linkmode_and(params.adv_speeds, 5921d4e4eccSAlexander Lobakin current_link.supported_caps, map->caps); 5931d4e4eccSAlexander Lobakin goto set_link; 5941d4e4eccSAlexander Lobakin } 5951d4e4eccSAlexander Lobakin 596054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 597133fac0eSSudarsana Kalluru return -EINVAL; 598133fac0eSSudarsana Kalluru } 599bdb5d8ecSAlexander Lobakin 6001d4e4eccSAlexander Lobakin set_link: 601133fac0eSSudarsana Kalluru params.link_up = true; 602133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 603133fac0eSSudarsana Kalluru 604133fac0eSSudarsana Kalluru return 0; 605133fac0eSSudarsana Kalluru } 606133fac0eSSudarsana Kalluru 607133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 608133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 609133fac0eSSudarsana Kalluru { 610133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 611133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 612a88381deSSudarsana Reddy Kalluru char mbi[ETHTOOL_FWVERS_LEN]; 613133fac0eSSudarsana Kalluru 614133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 615133fac0eSSudarsana Kalluru 616133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 617133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 618133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 619133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 620133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 621133fac0eSSudarsana Kalluru 622133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 623133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 624133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 625133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 626133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 627133fac0eSSudarsana Kalluru 62888ea96f8SShai Malin if ((strlen(storm) + strlen("[storm]")) < 629a88381deSSudarsana Reddy Kalluru sizeof(info->version)) 630a88381deSSudarsana Reddy Kalluru snprintf(info->version, sizeof(info->version), 63188ea96f8SShai Malin "[storm %s]", storm); 632a88381deSSudarsana Reddy Kalluru else 633a88381deSSudarsana Reddy Kalluru snprintf(info->version, sizeof(info->version), 63488ea96f8SShai Malin "%s", storm); 635a88381deSSudarsana Reddy Kalluru 636a88381deSSudarsana Reddy Kalluru if (edev->dev_info.common.mbi_version) { 637a88381deSSudarsana Reddy Kalluru snprintf(mbi, ETHTOOL_FWVERS_LEN, "%d.%d.%d", 638a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version & 639a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_2_MASK) >> QED_MBI_VERSION_2_OFFSET, 640a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version & 641a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_1_MASK) >> QED_MBI_VERSION_1_OFFSET, 642a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version & 643a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_0_MASK) >> QED_MBI_VERSION_0_OFFSET); 644133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 645a88381deSSudarsana Reddy Kalluru "mbi %s [mfw %s]", mbi, mfw); 646133fac0eSSudarsana Kalluru } else { 647133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 648a88381deSSudarsana Reddy Kalluru "mfw %s", mfw); 649133fac0eSSudarsana Kalluru } 650133fac0eSSudarsana Kalluru 651133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 652133fac0eSSudarsana Kalluru } 653133fac0eSSudarsana Kalluru 65414d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 65514d39648SMintz, Yuval { 65614d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 65714d39648SMintz, Yuval 65814d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 65914d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 66014d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 66114d39648SMintz, Yuval } 66214d39648SMintz, Yuval } 66314d39648SMintz, Yuval 66414d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 66514d39648SMintz, Yuval { 66614d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 66714d39648SMintz, Yuval bool wol_requested; 66814d39648SMintz, Yuval int rc; 66914d39648SMintz, Yuval 67014d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 67114d39648SMintz, Yuval DP_INFO(edev, 67214d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 67314d39648SMintz, Yuval return -EINVAL; 67414d39648SMintz, Yuval } 67514d39648SMintz, Yuval 67614d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 67714d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 67814d39648SMintz, Yuval return 0; 67914d39648SMintz, Yuval 68014d39648SMintz, Yuval /* Need to actually change configuration */ 68114d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 68214d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 68314d39648SMintz, Yuval return -EINVAL; 68414d39648SMintz, Yuval } 68514d39648SMintz, Yuval 68614d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 68714d39648SMintz, Yuval if (!rc) 68814d39648SMintz, Yuval edev->wol_enabled = wol_requested; 68914d39648SMintz, Yuval 69014d39648SMintz, Yuval return rc; 69114d39648SMintz, Yuval } 69214d39648SMintz, Yuval 693133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 694133fac0eSSudarsana Kalluru { 695133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 696133fac0eSSudarsana Kalluru 6971a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 698133fac0eSSudarsana Kalluru } 699133fac0eSSudarsana Kalluru 700133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 701133fac0eSSudarsana Kalluru { 702133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 703133fac0eSSudarsana Kalluru u32 dp_module = 0; 704133fac0eSSudarsana Kalluru u8 dp_level = 0; 705133fac0eSSudarsana Kalluru 706133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 707133fac0eSSudarsana Kalluru 708133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 709133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 710133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 711133fac0eSSudarsana Kalluru dp_module, dp_level); 712133fac0eSSudarsana Kalluru } 713133fac0eSSudarsana Kalluru 71432a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 71532a7a570SSudarsana Kalluru { 71632a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 71732a7a570SSudarsana Kalluru struct qed_link_output current_link; 71832a7a570SSudarsana Kalluru struct qed_link_params link_params; 71932a7a570SSudarsana Kalluru 720fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 7211a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 722fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 723fe7cd2bfSYuval Mintz } 724fe7cd2bfSYuval Mintz 72532a7a570SSudarsana Kalluru if (!netif_running(dev)) 72632a7a570SSudarsana Kalluru return 0; 72732a7a570SSudarsana Kalluru 72832a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 72932a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 73032a7a570SSudarsana Kalluru if (!current_link.link_up) 73132a7a570SSudarsana Kalluru return 0; 73232a7a570SSudarsana Kalluru 73332a7a570SSudarsana Kalluru /* Toggle the link */ 73432a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 73532a7a570SSudarsana Kalluru link_params.link_up = false; 73632a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 73732a7a570SSudarsana Kalluru link_params.link_up = true; 73832a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 73932a7a570SSudarsana Kalluru 74032a7a570SSudarsana Kalluru return 0; 74132a7a570SSudarsana Kalluru } 74232a7a570SSudarsana Kalluru 743133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 744133fac0eSSudarsana Kalluru { 745133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 746133fac0eSSudarsana Kalluru struct qed_link_output current_link; 747133fac0eSSudarsana Kalluru 748133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 749133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 750133fac0eSSudarsana Kalluru 751133fac0eSSudarsana Kalluru return current_link.link_up; 752133fac0eSSudarsana Kalluru } 753133fac0eSSudarsana Kalluru 754ccfa110cSSudarsana Reddy Kalluru static int qede_flash_device(struct net_device *dev, 755ccfa110cSSudarsana Reddy Kalluru struct ethtool_flash *flash) 756ccfa110cSSudarsana Reddy Kalluru { 757ccfa110cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 758ccfa110cSSudarsana Reddy Kalluru 759ccfa110cSSudarsana Reddy Kalluru return edev->ops->common->nvm_flash(edev->cdev, flash->data); 760ccfa110cSSudarsana Reddy Kalluru } 761ccfa110cSSudarsana Reddy Kalluru 762d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 763f3ccfda1SYufeng Mo struct ethtool_coalesce *coal, 764f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal, 765f3ccfda1SYufeng Mo struct netlink_ext_ack *extack) 766d552fa84SSudarsana Reddy Kalluru { 767bf5a94bfSRahul Verma void *rx_handle = NULL, *tx_handle = NULL; 768d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 769bf5a94bfSRahul Verma u16 rx_coal, tx_coal, i, rc = 0; 770bf5a94bfSRahul Verma struct qede_fastpath *fp; 771bf5a94bfSRahul Verma 772bf5a94bfSRahul Verma rx_coal = QED_DEFAULT_RX_USECS; 773bf5a94bfSRahul Verma tx_coal = QED_DEFAULT_TX_USECS; 774d552fa84SSudarsana Reddy Kalluru 775d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 776d2890deaSSudarsana Reddy Kalluru 777bf5a94bfSRahul Verma __qede_lock(edev); 778bf5a94bfSRahul Verma if (edev->state == QEDE_STATE_OPEN) { 779bf5a94bfSRahul Verma for_each_queue(i) { 780bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 781d552fa84SSudarsana Reddy Kalluru 782bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_RX) { 783bf5a94bfSRahul Verma rx_handle = fp->rxq->handle; 784bf5a94bfSRahul Verma break; 785bf5a94bfSRahul Verma } 786bf5a94bfSRahul Verma } 787bf5a94bfSRahul Verma 788bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle); 789bf5a94bfSRahul Verma if (rc) { 790bf5a94bfSRahul Verma DP_INFO(edev, "Read Rx coalesce error\n"); 791bf5a94bfSRahul Verma goto out; 792bf5a94bfSRahul Verma } 793bf5a94bfSRahul Verma 794bf5a94bfSRahul Verma for_each_queue(i) { 7955e7baf0fSManish Chopra struct qede_tx_queue *txq; 7965e7baf0fSManish Chopra 797bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 7985e7baf0fSManish Chopra 7995e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 8005e7baf0fSManish Chopra * coalescing value, so no need to iterate over 8015e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 8025e7baf0fSManish Chopra */ 803bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_TX) { 8045e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 8055e7baf0fSManish Chopra tx_handle = txq->handle; 806bf5a94bfSRahul Verma break; 807bf5a94bfSRahul Verma } 808bf5a94bfSRahul Verma } 809bf5a94bfSRahul Verma 810bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle); 811bf5a94bfSRahul Verma if (rc) 812bf5a94bfSRahul Verma DP_INFO(edev, "Read Tx coalesce error\n"); 813bf5a94bfSRahul Verma } 814bf5a94bfSRahul Verma 815bf5a94bfSRahul Verma out: 816bf5a94bfSRahul Verma __qede_unlock(edev); 817bf5a94bfSRahul Verma 818bf5a94bfSRahul Verma coal->rx_coalesce_usecs = rx_coal; 819bf5a94bfSRahul Verma coal->tx_coalesce_usecs = tx_coal; 820bf5a94bfSRahul Verma 821bf5a94bfSRahul Verma return rc; 822d552fa84SSudarsana Reddy Kalluru } 823d552fa84SSudarsana Reddy Kalluru 824f3ccfda1SYufeng Mo int qede_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal, 825f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal, 826f3ccfda1SYufeng Mo struct netlink_ext_ack *extack) 827d552fa84SSudarsana Reddy Kalluru { 828d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 829477f2d14SRahul Verma struct qede_fastpath *fp; 830d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 831477f2d14SRahul Verma u16 rxc, txc; 832d552fa84SSudarsana Reddy Kalluru 833d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 834d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 835d552fa84SSudarsana Reddy Kalluru return -EINVAL; 836d552fa84SSudarsana Reddy Kalluru } 837d552fa84SSudarsana Reddy Kalluru 838d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 839d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 840d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 841d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 842477f2d14SRahul Verma coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" : 843477f2d14SRahul Verma "tx", QED_COALESCE_MAX); 844d552fa84SSudarsana Reddy Kalluru return -EINVAL; 845d552fa84SSudarsana Reddy Kalluru } 846d552fa84SSudarsana Reddy Kalluru 847d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 848d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 8499a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 850477f2d14SRahul Verma fp = &edev->fp_array[i]; 851477f2d14SRahul Verma 852477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 853477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 854477f2d14SRahul Verma rxc, 0, 855477f2d14SRahul Verma fp->rxq->handle); 856d552fa84SSudarsana Reddy Kalluru if (rc) { 857477f2d14SRahul Verma DP_INFO(edev, 858477f2d14SRahul Verma "Set RX coalesce error, rc = %d\n", rc); 859d552fa84SSudarsana Reddy Kalluru return rc; 860d552fa84SSudarsana Reddy Kalluru } 861b0ec5489SBhaskar Upadhaya edev->coal_entry[i].rxc = rxc; 862b0ec5489SBhaskar Upadhaya edev->coal_entry[i].isvalid = true; 863d552fa84SSudarsana Reddy Kalluru } 864d552fa84SSudarsana Reddy Kalluru 865477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 8665e7baf0fSManish Chopra struct qede_tx_queue *txq; 8675e7baf0fSManish Chopra 8685e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 8695e7baf0fSManish Chopra * coalescing value, so no need to iterate over 8705e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 8715e7baf0fSManish Chopra */ 8725e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 8735e7baf0fSManish Chopra 874477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 875477f2d14SRahul Verma 0, txc, 8765e7baf0fSManish Chopra txq->handle); 877477f2d14SRahul Verma if (rc) { 878477f2d14SRahul Verma DP_INFO(edev, 879477f2d14SRahul Verma "Set TX coalesce error, rc = %d\n", rc); 880477f2d14SRahul Verma return rc; 881477f2d14SRahul Verma } 882b0ec5489SBhaskar Upadhaya edev->coal_entry[i].txc = txc; 883b0ec5489SBhaskar Upadhaya edev->coal_entry[i].isvalid = true; 884477f2d14SRahul Verma } 885477f2d14SRahul Verma } 886477f2d14SRahul Verma 887d552fa84SSudarsana Reddy Kalluru return rc; 888d552fa84SSudarsana Reddy Kalluru } 889d552fa84SSudarsana Reddy Kalluru 89001ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 891*74624944SHao Chen struct ethtool_ringparam *ering, 892*74624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering, 893*74624944SHao Chen struct netlink_ext_ack *extack) 89401ef7e05SSudarsana Kalluru { 89501ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 89601ef7e05SSudarsana Kalluru 89701ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 89801ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 89901ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 90001ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 90101ef7e05SSudarsana Kalluru } 90201ef7e05SSudarsana Kalluru 90301ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 904*74624944SHao Chen struct ethtool_ringparam *ering, 905*74624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering, 906*74624944SHao Chen struct netlink_ext_ack *extack) 90701ef7e05SSudarsana Kalluru { 90801ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 90901ef7e05SSudarsana Kalluru 91001ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 91101ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 91201ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 91301ef7e05SSudarsana Kalluru 91401ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 91501ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 91601ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 91701ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 91801ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 91901ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 92001ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 92101ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 92201ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 92301ef7e05SSudarsana Kalluru return -EINVAL; 92401ef7e05SSudarsana Kalluru } 92501ef7e05SSudarsana Kalluru 92601ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 92701ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 92801ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 92901ef7e05SSudarsana Kalluru 930567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 93101ef7e05SSudarsana Kalluru 93201ef7e05SSudarsana Kalluru return 0; 93301ef7e05SSudarsana Kalluru } 93401ef7e05SSudarsana Kalluru 9350f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 9360f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 9370f7db144SSudarsana Kalluru { 9380f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9390f7db144SSudarsana Kalluru struct qed_link_output current_link; 9400f7db144SSudarsana Kalluru 9410f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 9420f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 9430f7db144SSudarsana Kalluru 9440f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 9450f7db144SSudarsana Kalluru epause->autoneg = true; 9460f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 9470f7db144SSudarsana Kalluru epause->rx_pause = true; 9480f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 9490f7db144SSudarsana Kalluru epause->tx_pause = true; 9500f7db144SSudarsana Kalluru 9510f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 9520f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 9530f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 9540f7db144SSudarsana Kalluru epause->tx_pause); 9550f7db144SSudarsana Kalluru } 9560f7db144SSudarsana Kalluru 9570f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 9580f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 9590f7db144SSudarsana Kalluru { 9600f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9610f7db144SSudarsana Kalluru struct qed_link_params params; 9620f7db144SSudarsana Kalluru struct qed_link_output current_link; 9630f7db144SSudarsana Kalluru 964fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 9650f7db144SSudarsana Kalluru DP_INFO(edev, 966fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 9670f7db144SSudarsana Kalluru return -EOPNOTSUPP; 9680f7db144SSudarsana Kalluru } 9690f7db144SSudarsana Kalluru 9700f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 9710f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 9720f7db144SSudarsana Kalluru 9730f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 9740f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 975bdb5d8ecSAlexander Lobakin 9760f7db144SSudarsana Kalluru if (epause->autoneg) { 977bdb5d8ecSAlexander Lobakin if (!phylink_test(current_link.supported_caps, Autoneg)) { 9780f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 9790f7db144SSudarsana Kalluru return -EINVAL; 9800f7db144SSudarsana Kalluru } 981bdb5d8ecSAlexander Lobakin 9820f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 9830f7db144SSudarsana Kalluru } 984bdb5d8ecSAlexander Lobakin 9850f7db144SSudarsana Kalluru if (epause->rx_pause) 9860f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 9870f7db144SSudarsana Kalluru if (epause->tx_pause) 9880f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 9890f7db144SSudarsana Kalluru 9900f7db144SSudarsana Kalluru params.link_up = true; 9910f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 9920f7db144SSudarsana Kalluru 9930f7db144SSudarsana Kalluru return 0; 9940f7db144SSudarsana Kalluru } 9950f7db144SSudarsana Kalluru 996e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 997e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 998e0971c83STomer Tayar { 999e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 1000e0971c83STomer Tayar 1001e0971c83STomer Tayar regs->version = 0; 1002e0971c83STomer Tayar memset(buffer, 0, regs->len); 1003e0971c83STomer Tayar 1004e0971c83STomer Tayar if (edev->ops && edev->ops->common) 1005e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 1006e0971c83STomer Tayar } 1007e0971c83STomer Tayar 1008e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 1009e0971c83STomer Tayar { 1010e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 1011e0971c83STomer Tayar 1012e0971c83STomer Tayar if (edev->ops && edev->ops->common) 1013e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 1014e0971c83STomer Tayar else 1015e0971c83STomer Tayar return -EINVAL; 1016e0971c83STomer Tayar } 1017e0971c83STomer Tayar 1018567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev, 1019567b3c12SMintz, Yuval struct qede_reload_args *args) 1020133fac0eSSudarsana Kalluru { 1021567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu; 1022133fac0eSSudarsana Kalluru } 1023133fac0eSSudarsana Kalluru 1024133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 1025133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 1026133fac0eSSudarsana Kalluru { 1027133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 1028567b3c12SMintz, Yuval struct qede_reload_args args; 1029133fac0eSSudarsana Kalluru 1030133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 1031133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 1032133fac0eSSudarsana Kalluru 103318c602deSMichael Chan if (new_mtu > PAGE_SIZE) 103418c602deSMichael Chan ndev->features &= ~NETIF_F_GRO_HW; 103518c602deSMichael Chan 1036133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */ 1037567b3c12SMintz, Yuval args.u.mtu = new_mtu; 1038567b3c12SMintz, Yuval args.func = &qede_update_mtu; 1039567b3c12SMintz, Yuval qede_reload(edev, &args, false); 104097fb3e33SMichal Kalderon #if IS_ENABLED(CONFIG_QED_RDMA) 104197fb3e33SMichal Kalderon qede_rdma_event_change_mtu(edev); 104297fb3e33SMichal Kalderon #endif 1043567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu); 10440fefbfbaSSudarsana Kalluru 1045133fac0eSSudarsana Kalluru return 0; 1046133fac0eSSudarsana Kalluru } 1047133fac0eSSudarsana Kalluru 10488edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 10498edf049dSSudarsana Kalluru struct ethtool_channels *channels) 10508edf049dSSudarsana Kalluru { 10518edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10528edf049dSSudarsana Kalluru 10538edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 1054bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 1055bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 10569a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 10579a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 10589a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 10599a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 10608edf049dSSudarsana Kalluru } 10618edf049dSSudarsana Kalluru 10628edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 10638edf049dSSudarsana Kalluru struct ethtool_channels *channels) 10648edf049dSSudarsana Kalluru { 10658edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10669a4d7e86SSudarsana Reddy Kalluru u32 count; 10678edf049dSSudarsana Kalluru 10688edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10698edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 10708edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 10718edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 10728edf049dSSudarsana Kalluru 10739a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 10749a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 10759a4d7e86SSudarsana Reddy Kalluru 10769a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 10779a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 10788edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10798edf049dSSudarsana Kalluru "command parameters not supported\n"); 10808edf049dSSudarsana Kalluru return -EINVAL; 10818edf049dSSudarsana Kalluru } 10828edf049dSSudarsana Kalluru 10839a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 10849a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 10859a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10869a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 10879a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 10889a4d7e86SSudarsana Reddy Kalluru } 10899a4d7e86SSudarsana Reddy Kalluru 10909a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 10919a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10929a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 10939a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 10949a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 10959a4d7e86SSudarsana Reddy Kalluru } 10969a4d7e86SSudarsana Reddy Kalluru 10978edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 10989a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 10999a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 11009a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 11018edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 11028edf049dSSudarsana Kalluru "No change in active parameters\n"); 11038edf049dSSudarsana Kalluru return 0; 11048edf049dSSudarsana Kalluru } 11058edf049dSSudarsana Kalluru 11068edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 11079a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 11089a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 11099a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 11108edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 11119a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 11128edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 11138edf049dSSudarsana Kalluru return -EINVAL; 11148edf049dSSudarsana Kalluru } 11158edf049dSSudarsana Kalluru 11168edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 11179a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 11189a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 11199a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 1120ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 1121ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 1122ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 1123f29ffdb6SMintz, Yuval memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); 1124ed0dd915SSudarsana Reddy Kalluru } 1125ed0dd915SSudarsana Reddy Kalluru 1126567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 11278edf049dSSudarsana Kalluru 11288edf049dSSudarsana Kalluru return 0; 11298edf049dSSudarsana Kalluru } 11308edf049dSSudarsana Kalluru 11314c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev, 11324c55215cSSudarsana Reddy Kalluru struct ethtool_ts_info *info) 11334c55215cSSudarsana Reddy Kalluru { 11344c55215cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 11354c55215cSSudarsana Reddy Kalluru 11364c55215cSSudarsana Reddy Kalluru return qede_ptp_get_ts_info(edev, info); 11374c55215cSSudarsana Reddy Kalluru } 11384c55215cSSudarsana Reddy Kalluru 11393d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 11403d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 11413d971cbdSSudarsana Kalluru { 11423d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 11433d971cbdSSudarsana Kalluru u8 led_state = 0; 11443d971cbdSSudarsana Kalluru 11453d971cbdSSudarsana Kalluru switch (state) { 11463d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 11473d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 11483d971cbdSSudarsana Kalluru 11493d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 11503d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 11513d971cbdSSudarsana Kalluru break; 11523d971cbdSSudarsana Kalluru 11533d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 11543d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 11553d971cbdSSudarsana Kalluru break; 11563d971cbdSSudarsana Kalluru 11573d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 11583d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 11593d971cbdSSudarsana Kalluru break; 11603d971cbdSSudarsana Kalluru } 11613d971cbdSSudarsana Kalluru 11623d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 11633d971cbdSSudarsana Kalluru 11643d971cbdSSudarsana Kalluru return 0; 11653d971cbdSSudarsana Kalluru } 11663d971cbdSSudarsana Kalluru 1167961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1168961acdeaSSudarsana Reddy Kalluru { 1169961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 1170961acdeaSSudarsana Reddy Kalluru 1171961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1172961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1173961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1174961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1175961acdeaSSudarsana Reddy Kalluru break; 1176961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1177f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV4_UDP) 1178961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1179961acdeaSSudarsana Reddy Kalluru break; 1180961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1181f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV6_UDP) 1182961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1183961acdeaSSudarsana Reddy Kalluru break; 1184961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1185961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1186961acdeaSSudarsana Reddy Kalluru break; 1187961acdeaSSudarsana Reddy Kalluru default: 1188961acdeaSSudarsana Reddy Kalluru info->data = 0; 1189961acdeaSSudarsana Reddy Kalluru break; 1190961acdeaSSudarsana Reddy Kalluru } 1191961acdeaSSudarsana Reddy Kalluru 1192961acdeaSSudarsana Reddy Kalluru return 0; 1193961acdeaSSudarsana Reddy Kalluru } 1194961acdeaSSudarsana Reddy Kalluru 1195961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 1196ec9b8dbdSChopra, Manish u32 *rule_locs) 1197961acdeaSSudarsana Reddy Kalluru { 1198961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1199ec9b8dbdSChopra, Manish int rc = 0; 1200961acdeaSSudarsana Reddy Kalluru 1201961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1202961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 12039a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 1204ec9b8dbdSChopra, Manish break; 1205961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 1206ec9b8dbdSChopra, Manish rc = qede_get_rss_flags(edev, info); 1207ec9b8dbdSChopra, Manish break; 1208ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLCNT: 1209ec9b8dbdSChopra, Manish info->rule_cnt = qede_get_arfs_filter_count(edev); 1210ec9b8dbdSChopra, Manish info->data = QEDE_RFS_MAX_FLTR; 1211ec9b8dbdSChopra, Manish break; 1212ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRULE: 1213ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_entry(edev, info); 1214ec9b8dbdSChopra, Manish break; 1215ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLALL: 1216ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_all(edev, info, rule_locs); 1217ec9b8dbdSChopra, Manish break; 1218961acdeaSSudarsana Reddy Kalluru default: 1219961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 1220ec9b8dbdSChopra, Manish rc = -EOPNOTSUPP; 1221961acdeaSSudarsana Reddy Kalluru } 1222ec9b8dbdSChopra, Manish 1223ec9b8dbdSChopra, Manish return rc; 1224961acdeaSSudarsana Reddy Kalluru } 1225961acdeaSSudarsana Reddy Kalluru 1226961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1227961acdeaSSudarsana Reddy Kalluru { 1228f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1229961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 1230f29ffdb6SMintz, Yuval int rc = 0; 1231961acdeaSSudarsana Reddy Kalluru 1232961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1233961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 1234961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 1235961acdeaSSudarsana Reddy Kalluru 1236961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1237961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1238961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1239961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 1240961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 1241961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1242961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1243961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1244961acdeaSSudarsana Reddy Kalluru } 1245961acdeaSSudarsana Reddy Kalluru return 0; 1246961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1247961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1248961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1249961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1250961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 1251961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1252961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1253961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1254961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 1255961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1256961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1257961acdeaSSudarsana Reddy Kalluru } else { 1258961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1259961acdeaSSudarsana Reddy Kalluru } 1260961acdeaSSudarsana Reddy Kalluru break; 1261961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1262961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1263961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1264961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1265961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 1266961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1267961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1268961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1269961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 1270961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1271961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1272961acdeaSSudarsana Reddy Kalluru } else { 1273961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1274961acdeaSSudarsana Reddy Kalluru } 1275961acdeaSSudarsana Reddy Kalluru break; 1276961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1277961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1278961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 1279961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 1280961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1281961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1282961acdeaSSudarsana Reddy Kalluru } 1283961acdeaSSudarsana Reddy Kalluru return 0; 1284961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1285961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1286961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1287961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1288961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1289961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1290961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1291961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1292961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1293961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1294961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1295961acdeaSSudarsana Reddy Kalluru if (info->data) { 1296961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1297961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1298961acdeaSSudarsana Reddy Kalluru } 1299961acdeaSSudarsana Reddy Kalluru return 0; 1300961acdeaSSudarsana Reddy Kalluru default: 1301961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1302961acdeaSSudarsana Reddy Kalluru } 1303961acdeaSSudarsana Reddy Kalluru 1304961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1305f29ffdb6SMintz, Yuval if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) 1306961acdeaSSudarsana Reddy Kalluru return 0; 1307961acdeaSSudarsana Reddy Kalluru 1308961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1309f29ffdb6SMintz, Yuval edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); 1310961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1311961acdeaSSudarsana Reddy Kalluru 1312961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1313f29ffdb6SMintz, Yuval __qede_lock(edev); 1314f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1315f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1316f29ffdb6SMintz, Yuval if (!vport_update_params) { 1317f29ffdb6SMintz, Yuval __qede_unlock(edev); 1318f29ffdb6SMintz, Yuval return -ENOMEM; 1319961acdeaSSudarsana Reddy Kalluru } 1320f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1321f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1322f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1323f29ffdb6SMintz, Yuval vfree(vport_update_params); 1324f29ffdb6SMintz, Yuval } 1325f29ffdb6SMintz, Yuval __qede_unlock(edev); 1326961acdeaSSudarsana Reddy Kalluru 1327f29ffdb6SMintz, Yuval return rc; 1328961acdeaSSudarsana Reddy Kalluru } 1329961acdeaSSudarsana Reddy Kalluru 1330961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1331961acdeaSSudarsana Reddy Kalluru { 1332961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 13333f2a2b8bSChopra, Manish int rc; 1334961acdeaSSudarsana Reddy Kalluru 1335961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1336961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 13373f2a2b8bSChopra, Manish rc = qede_set_rss_flags(edev, info); 13383f2a2b8bSChopra, Manish break; 13393f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLINS: 13403f2a2b8bSChopra, Manish rc = qede_add_cls_rule(edev, info); 13413f2a2b8bSChopra, Manish break; 13423f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLDEL: 13432ce9c93eSManish Chopra rc = qede_delete_flow_filter(edev, info->fs.location); 13443f2a2b8bSChopra, Manish break; 1345961acdeaSSudarsana Reddy Kalluru default: 1346961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 13473f2a2b8bSChopra, Manish rc = -EOPNOTSUPP; 1348961acdeaSSudarsana Reddy Kalluru } 13493f2a2b8bSChopra, Manish 13503f2a2b8bSChopra, Manish return rc; 1351961acdeaSSudarsana Reddy Kalluru } 1352961acdeaSSudarsana Reddy Kalluru 1353961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1354961acdeaSSudarsana Reddy Kalluru { 1355961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1356961acdeaSSudarsana Reddy Kalluru } 1357961acdeaSSudarsana Reddy Kalluru 1358961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1359961acdeaSSudarsana Reddy Kalluru { 1360961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1361961acdeaSSudarsana Reddy Kalluru 1362f29ffdb6SMintz, Yuval return sizeof(edev->rss_key); 1363961acdeaSSudarsana Reddy Kalluru } 1364961acdeaSSudarsana Reddy Kalluru 1365961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1366961acdeaSSudarsana Reddy Kalluru { 1367961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1368961acdeaSSudarsana Reddy Kalluru int i; 1369961acdeaSSudarsana Reddy Kalluru 1370961acdeaSSudarsana Reddy Kalluru if (hfunc) 1371961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1372961acdeaSSudarsana Reddy Kalluru 1373961acdeaSSudarsana Reddy Kalluru if (!indir) 1374961acdeaSSudarsana Reddy Kalluru return 0; 1375961acdeaSSudarsana Reddy Kalluru 1376961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1377f29ffdb6SMintz, Yuval indir[i] = edev->rss_ind_table[i]; 1378961acdeaSSudarsana Reddy Kalluru 1379961acdeaSSudarsana Reddy Kalluru if (key) 1380f29ffdb6SMintz, Yuval memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev)); 1381961acdeaSSudarsana Reddy Kalluru 1382961acdeaSSudarsana Reddy Kalluru return 0; 1383961acdeaSSudarsana Reddy Kalluru } 1384961acdeaSSudarsana Reddy Kalluru 1385961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1386961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1387961acdeaSSudarsana Reddy Kalluru { 1388f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1389961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1390f29ffdb6SMintz, Yuval int i, rc = 0; 1391961acdeaSSudarsana Reddy Kalluru 1392ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1393ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1394ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1395ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1396ba300ce3SSudarsana Reddy Kalluru } 1397ba300ce3SSudarsana Reddy Kalluru 1398961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1399961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1400961acdeaSSudarsana Reddy Kalluru 1401961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1402961acdeaSSudarsana Reddy Kalluru return 0; 1403961acdeaSSudarsana Reddy Kalluru 1404961acdeaSSudarsana Reddy Kalluru if (indir) { 1405961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1406f29ffdb6SMintz, Yuval edev->rss_ind_table[i] = indir[i]; 1407961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1408961acdeaSSudarsana Reddy Kalluru } 1409961acdeaSSudarsana Reddy Kalluru 1410961acdeaSSudarsana Reddy Kalluru if (key) { 1411f29ffdb6SMintz, Yuval memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev)); 1412961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1413961acdeaSSudarsana Reddy Kalluru } 1414961acdeaSSudarsana Reddy Kalluru 1415f29ffdb6SMintz, Yuval __qede_lock(edev); 1416f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1417f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1418f29ffdb6SMintz, Yuval if (!vport_update_params) { 1419f29ffdb6SMintz, Yuval __qede_unlock(edev); 1420f29ffdb6SMintz, Yuval return -ENOMEM; 1421961acdeaSSudarsana Reddy Kalluru } 1422f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1423f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1424f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1425f29ffdb6SMintz, Yuval vfree(vport_update_params); 1426f29ffdb6SMintz, Yuval } 1427f29ffdb6SMintz, Yuval __qede_unlock(edev); 1428961acdeaSSudarsana Reddy Kalluru 1429f29ffdb6SMintz, Yuval return rc; 1430961acdeaSSudarsana Reddy Kalluru } 1431961acdeaSSudarsana Reddy Kalluru 143216f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 143316f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 143416f46bf0SSudarsana Reddy Kalluru { 143516f46bf0SSudarsana Reddy Kalluru int i; 143616f46bf0SSudarsana Reddy Kalluru 143716f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 143816f46bf0SSudarsana Reddy Kalluru return; 143916f46bf0SSudarsana Reddy Kalluru 14409a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 144116f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 144216f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 144316f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 144416f46bf0SSudarsana Reddy Kalluru } 144516f46bf0SSudarsana Reddy Kalluru } 144616f46bf0SSudarsana Reddy Kalluru 144716f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 144816f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 144916f46bf0SSudarsana Reddy Kalluru { 145016f46bf0SSudarsana Reddy Kalluru int i; 145116f46bf0SSudarsana Reddy Kalluru 14529a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 145316f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 145416f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 145516f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 145616f46bf0SSudarsana Reddy Kalluru } 145716f46bf0SSudarsana Reddy Kalluru } 145816f46bf0SSudarsana Reddy Kalluru 145916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 146016f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 146116f46bf0SSudarsana Reddy Kalluru { 14629a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 146316f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 146416f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 146548848a06SManish Chopra int i, idx; 146648848a06SManish Chopra u16 val; 146716f46bf0SSudarsana Reddy Kalluru 14689a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 14695e7baf0fSManish Chopra struct qede_fastpath *fp = &edev->fp_array[i]; 14705e7baf0fSManish Chopra 14715e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 14725e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 14739a4d7e86SSudarsana Reddy Kalluru break; 14749a4d7e86SSudarsana Reddy Kalluru } 14759a4d7e86SSudarsana Reddy Kalluru } 14769a4d7e86SSudarsana Reddy Kalluru 14779a4d7e86SSudarsana Reddy Kalluru if (!txq) { 14789a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 14799a4d7e86SSudarsana Reddy Kalluru return -1; 14809a4d7e86SSudarsana Reddy Kalluru } 14819a4d7e86SSudarsana Reddy Kalluru 148216f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 14835a052d62SSudarsana Reddy Kalluru idx = txq->sw_tx_prod; 1484cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = skb; 148516f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 148616f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 148716f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 148816f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1489351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 149048848a06SManish Chopra val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; 149148848a06SManish Chopra first_bd->data.bitfields |= cpu_to_le16(val); 149216f46bf0SSudarsana Reddy Kalluru 149316f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 149416f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 149516f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 149616f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 149716f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 149816f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 149916f46bf0SSudarsana Reddy Kalluru } 150016f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 150116f46bf0SSudarsana Reddy Kalluru 150216f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 150316f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 15045a052d62SSudarsana Reddy Kalluru txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; 150516f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 150648848a06SManish Chopra val = qed_chain_get_prod_idx(&txq->tx_pbl); 150748848a06SManish Chopra txq->tx_db.data.bd_prod = cpu_to_le16(val); 150816f46bf0SSudarsana Reddy Kalluru 150916f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 151016f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 151116f46bf0SSudarsana Reddy Kalluru */ 151216f46bf0SSudarsana Reddy Kalluru wmb(); 151316f46bf0SSudarsana Reddy Kalluru barrier(); 151416f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 151516f46bf0SSudarsana Reddy Kalluru 151616f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 151716f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 151816f46bf0SSudarsana Reddy Kalluru break; 151916f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 152016f46bf0SSudarsana Reddy Kalluru } 152116f46bf0SSudarsana Reddy Kalluru 152216f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 152316f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 152416f46bf0SSudarsana Reddy Kalluru return -1; 152516f46bf0SSudarsana Reddy Kalluru } 152616f46bf0SSudarsana Reddy Kalluru 152716f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1528fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 152916f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 15305a052d62SSudarsana Reddy Kalluru txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; 1531cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = NULL; 153216f46bf0SSudarsana Reddy Kalluru 153316f46bf0SSudarsana Reddy Kalluru return 0; 153416f46bf0SSudarsana Reddy Kalluru } 153516f46bf0SSudarsana Reddy Kalluru 153616f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 153716f46bf0SSudarsana Reddy Kalluru { 153810ee4b87SZheng Zengkai u16 sw_rx_index, len; 153916f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 15409a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 154116f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 154216f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1543afe981d6SSudarsana Reddy Kalluru int i, iter, rc = 0; 154416f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 154516f46bf0SSudarsana Reddy Kalluru 15469a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 15479a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 15489a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 15499a4d7e86SSudarsana Reddy Kalluru break; 15509a4d7e86SSudarsana Reddy Kalluru } 15519a4d7e86SSudarsana Reddy Kalluru } 15529a4d7e86SSudarsana Reddy Kalluru 15539a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 15549a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 15559a4d7e86SSudarsana Reddy Kalluru return -1; 15569a4d7e86SSudarsana Reddy Kalluru } 15579a4d7e86SSudarsana Reddy Kalluru 155816f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 155916f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 156016f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 156116f46bf0SSudarsana Reddy Kalluru */ 1562afe981d6SSudarsana Reddy Kalluru for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { 156316f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1564837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1565837d4eb6SSudarsana Reddy Kalluru continue; 156616f46bf0SSudarsana Reddy Kalluru } 156716f46bf0SSudarsana Reddy Kalluru 156816f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 156916f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 157016f46bf0SSudarsana Reddy Kalluru 157116f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 157216f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 157316f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 157416f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 157516f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 157616f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1577837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 15788a863397SManish Chopra sw_rx_data->page_offset + 15798a863397SManish Chopra rxq->rx_headroom); 1580837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1581837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1582837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 158316f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 158416f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1585837d4eb6SSudarsana Reddy Kalluru rc = -1; 1586837d4eb6SSudarsana Reddy Kalluru break; 158716f46bf0SSudarsana Reddy Kalluru } 158816f46bf0SSudarsana Reddy Kalluru 15899eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1590837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1591837d4eb6SSudarsana Reddy Kalluru break; 1592837d4eb6SSudarsana Reddy Kalluru } 159316f46bf0SSudarsana Reddy Kalluru 1594837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 15959eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1596837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1597837d4eb6SSudarsana Reddy Kalluru } 1598837d4eb6SSudarsana Reddy Kalluru 1599afe981d6SSudarsana Reddy Kalluru if (iter == QEDE_SELFTEST_POLL_COUNT) { 1600837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1601837d4eb6SSudarsana Reddy Kalluru return -1; 1602837d4eb6SSudarsana Reddy Kalluru } 1603837d4eb6SSudarsana Reddy Kalluru 1604837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1605837d4eb6SSudarsana Reddy Kalluru 1606837d4eb6SSudarsana Reddy Kalluru return rc; 160716f46bf0SSudarsana Reddy Kalluru } 160816f46bf0SSudarsana Reddy Kalluru 160916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 161016f46bf0SSudarsana Reddy Kalluru { 161116f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 161216f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 161316f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 161416f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 161516f46bf0SSudarsana Reddy Kalluru u8 *packet; 161616f46bf0SSudarsana Reddy Kalluru 161716f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 161816f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 161916f46bf0SSudarsana Reddy Kalluru return -EINVAL; 162016f46bf0SSudarsana Reddy Kalluru } 162116f46bf0SSudarsana Reddy Kalluru 162216f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 162316f46bf0SSudarsana Reddy Kalluru 162416f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 162516f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 162616f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 162716f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 162816f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 162916f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 163016f46bf0SSudarsana Reddy Kalluru 163116f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 163216f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 163316f46bf0SSudarsana Reddy Kalluru 1634b89869daSSudarsana Reddy Kalluru /* Setting max packet size to 1.5K to avoid data being split over 1635b89869daSSudarsana Reddy Kalluru * multiple BDs in cases where MTU > PAGE_SIZE. 1636b89869daSSudarsana Reddy Kalluru */ 1637b89869daSSudarsana Reddy Kalluru pkt_size = (((edev->ndev->mtu < ETH_DATA_LEN) ? 1638b89869daSSudarsana Reddy Kalluru edev->ndev->mtu : ETH_DATA_LEN) + ETH_HLEN); 163916f46bf0SSudarsana Reddy Kalluru 164016f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 164116f46bf0SSudarsana Reddy Kalluru if (!skb) { 164216f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 164316f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 164416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 164516f46bf0SSudarsana Reddy Kalluru } 164616f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 164716f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 164816f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 164916f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 165016f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 165116f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 165216f46bf0SSudarsana Reddy Kalluru 165316f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 165416f46bf0SSudarsana Reddy Kalluru if (rc) 165516f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 165616f46bf0SSudarsana Reddy Kalluru 165716f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 165816f46bf0SSudarsana Reddy Kalluru if (rc) 165916f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 166016f46bf0SSudarsana Reddy Kalluru 166116f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 166216f46bf0SSudarsana Reddy Kalluru 166316f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 166416f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 166516f46bf0SSudarsana Reddy Kalluru 166616f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 166716f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 166816f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 166916f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 167016f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 167116f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 167216f46bf0SSudarsana Reddy Kalluru 167316f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 167416f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 167516f46bf0SSudarsana Reddy Kalluru 167616f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 167716f46bf0SSudarsana Reddy Kalluru 167816f46bf0SSudarsana Reddy Kalluru return rc; 167916f46bf0SSudarsana Reddy Kalluru } 168016f46bf0SSudarsana Reddy Kalluru 16813044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 16823044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 16833044a02eSSudarsana Reddy Kalluru { 16843044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 16853044a02eSSudarsana Reddy Kalluru 16863044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 16873044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 16883044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 16893044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 16903044a02eSSudarsana Reddy Kalluru 16913044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 16923044a02eSSudarsana Reddy Kalluru 169316f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 169416f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 169516f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 169616f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 169716f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 169816f46bf0SSudarsana Reddy Kalluru } 169916f46bf0SSudarsana Reddy Kalluru } 170016f46bf0SSudarsana Reddy Kalluru 17013044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 17023044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 17033044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17043044a02eSSudarsana Reddy Kalluru } 17053044a02eSSudarsana Reddy Kalluru 17063044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 17073044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 17083044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17093044a02eSSudarsana Reddy Kalluru } 17103044a02eSSudarsana Reddy Kalluru 17113044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 17123044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 17133044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17143044a02eSSudarsana Reddy Kalluru } 17153044a02eSSudarsana Reddy Kalluru 17163044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 17173044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 17183044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17193044a02eSSudarsana Reddy Kalluru } 17207a4b21b7SMintz, Yuval 17217a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 17227a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 17237a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 17247a4b21b7SMintz, Yuval } 17253044a02eSSudarsana Reddy Kalluru } 17263044a02eSSudarsana Reddy Kalluru 17273d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 17283d789994SManish Chopra const struct ethtool_tunable *tuna, 17293d789994SManish Chopra const void *data) 17303d789994SManish Chopra { 17313d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 17323d789994SManish Chopra u32 val; 17333d789994SManish Chopra 17343d789994SManish Chopra switch (tuna->id) { 17353d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 17363d789994SManish Chopra val = *(u32 *)data; 17373d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 17383d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 17393d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 17403d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 17413d789994SManish Chopra return -EINVAL; 17423d789994SManish Chopra } 17433d789994SManish Chopra 17443d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 17453d789994SManish Chopra break; 17463d789994SManish Chopra default: 17473d789994SManish Chopra return -EOPNOTSUPP; 17483d789994SManish Chopra } 17493d789994SManish Chopra 17503d789994SManish Chopra return 0; 17513d789994SManish Chopra } 17523d789994SManish Chopra 17533d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 17543d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 17553d789994SManish Chopra { 17563d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 17573d789994SManish Chopra 17583d789994SManish Chopra switch (tuna->id) { 17593d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 17603d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 17613d789994SManish Chopra break; 17623d789994SManish Chopra default: 17633d789994SManish Chopra return -EOPNOTSUPP; 17643d789994SManish Chopra } 17653d789994SManish Chopra 17663d789994SManish Chopra return 0; 17673d789994SManish Chopra } 17683d789994SManish Chopra 1769c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata) 1770c3dc48f7SSudarsana Reddy Kalluru { 1771c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1772c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1773c3dc48f7SSudarsana Reddy Kalluru 1774c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1775c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1776c3dc48f7SSudarsana Reddy Kalluru 1777c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1778c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1779c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1780c3dc48f7SSudarsana Reddy Kalluru } 1781c3dc48f7SSudarsana Reddy Kalluru 1782c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_1G_ADV) 1783c3dc48f7SSudarsana Reddy Kalluru edata->advertised = ADVERTISED_1000baseT_Full; 1784c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_10G_ADV) 1785c3dc48f7SSudarsana Reddy Kalluru edata->advertised |= ADVERTISED_10000baseT_Full; 1786c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_1G_ADV) 1787c3dc48f7SSudarsana Reddy Kalluru edata->supported = ADVERTISED_1000baseT_Full; 1788c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_10G_ADV) 1789c3dc48f7SSudarsana Reddy Kalluru edata->supported |= ADVERTISED_10000baseT_Full; 1790c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV) 1791c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised = ADVERTISED_1000baseT_Full; 1792c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV) 1793c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised |= ADVERTISED_10000baseT_Full; 1794c3dc48f7SSudarsana Reddy Kalluru 1795c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_timer = current_link.eee.tx_lpi_timer; 1796c3dc48f7SSudarsana Reddy Kalluru edata->eee_enabled = current_link.eee.enable; 1797c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable; 1798c3dc48f7SSudarsana Reddy Kalluru edata->eee_active = current_link.eee_active; 1799c3dc48f7SSudarsana Reddy Kalluru 1800c3dc48f7SSudarsana Reddy Kalluru return 0; 1801c3dc48f7SSudarsana Reddy Kalluru } 1802c3dc48f7SSudarsana Reddy Kalluru 1803c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata) 1804c3dc48f7SSudarsana Reddy Kalluru { 1805c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1806c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1807c3dc48f7SSudarsana Reddy Kalluru struct qed_link_params params; 1808c3dc48f7SSudarsana Reddy Kalluru 1809c3dc48f7SSudarsana Reddy Kalluru if (!edev->ops->common->can_link_change(edev->cdev)) { 1810c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 1811c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1812c3dc48f7SSudarsana Reddy Kalluru } 1813c3dc48f7SSudarsana Reddy Kalluru 1814c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1815c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1816c3dc48f7SSudarsana Reddy Kalluru 1817c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1818c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1819c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1820c3dc48f7SSudarsana Reddy Kalluru } 1821c3dc48f7SSudarsana Reddy Kalluru 1822c3dc48f7SSudarsana Reddy Kalluru memset(¶ms, 0, sizeof(params)); 1823c3dc48f7SSudarsana Reddy Kalluru params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG; 1824c3dc48f7SSudarsana Reddy Kalluru 1825c3dc48f7SSudarsana Reddy Kalluru if (!(edata->advertised & (ADVERTISED_1000baseT_Full | 1826c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) || 1827c3dc48f7SSudarsana Reddy Kalluru ((edata->advertised & (ADVERTISED_1000baseT_Full | 1828c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) != 1829c3dc48f7SSudarsana Reddy Kalluru edata->advertised)) { 1830c3dc48f7SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1831c3dc48f7SSudarsana Reddy Kalluru "Invalid advertised capabilities %d\n", 1832c3dc48f7SSudarsana Reddy Kalluru edata->advertised); 1833c3dc48f7SSudarsana Reddy Kalluru return -EINVAL; 1834c3dc48f7SSudarsana Reddy Kalluru } 1835c3dc48f7SSudarsana Reddy Kalluru 1836c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_1000baseT_Full) 1837c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps = QED_EEE_1G_ADV; 1838c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_10000baseT_Full) 1839c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps |= QED_EEE_10G_ADV; 1840c3dc48f7SSudarsana Reddy Kalluru params.eee.enable = edata->eee_enabled; 1841c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_enable = edata->tx_lpi_enabled; 1842c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_timer = edata->tx_lpi_timer; 1843c3dc48f7SSudarsana Reddy Kalluru 1844c3dc48f7SSudarsana Reddy Kalluru params.link_up = true; 1845c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 1846c3dc48f7SSudarsana Reddy Kalluru 1847c3dc48f7SSudarsana Reddy Kalluru return 0; 1848c3dc48f7SSudarsana Reddy Kalluru } 1849c3dc48f7SSudarsana Reddy Kalluru 18509bdca14aSAlexander Lobakin static u32 qede_link_to_ethtool_fec(u32 link_fec) 18519bdca14aSAlexander Lobakin { 18529bdca14aSAlexander Lobakin u32 eth_fec = 0; 18539bdca14aSAlexander Lobakin 18549bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_NONE) 18559bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_OFF; 18569bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_FIRECODE) 18579bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_BASER; 18589bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_RS) 18599bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_RS; 18609bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_AUTO) 18619bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_AUTO; 18629bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_UNSUPPORTED) 18639bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_NONE; 18649bdca14aSAlexander Lobakin 18659bdca14aSAlexander Lobakin return eth_fec; 18669bdca14aSAlexander Lobakin } 18679bdca14aSAlexander Lobakin 18689bdca14aSAlexander Lobakin static u32 qede_ethtool_to_link_fec(u32 eth_fec) 18699bdca14aSAlexander Lobakin { 18709bdca14aSAlexander Lobakin u32 link_fec = 0; 18719bdca14aSAlexander Lobakin 18729bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_OFF) 18739bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_NONE; 18749bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_BASER) 18759bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_FIRECODE; 18769bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_RS) 18779bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_RS; 18789bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_AUTO) 18799bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_AUTO; 18809bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_NONE) 18819bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_UNSUPPORTED; 18829bdca14aSAlexander Lobakin 18839bdca14aSAlexander Lobakin return link_fec; 18849bdca14aSAlexander Lobakin } 18859bdca14aSAlexander Lobakin 18869bdca14aSAlexander Lobakin static int qede_get_fecparam(struct net_device *dev, 18879bdca14aSAlexander Lobakin struct ethtool_fecparam *fecparam) 18889bdca14aSAlexander Lobakin { 18899bdca14aSAlexander Lobakin struct qede_dev *edev = netdev_priv(dev); 18909bdca14aSAlexander Lobakin struct qed_link_output curr_link; 18919bdca14aSAlexander Lobakin 18929bdca14aSAlexander Lobakin memset(&curr_link, 0, sizeof(curr_link)); 18939bdca14aSAlexander Lobakin edev->ops->common->get_link(edev->cdev, &curr_link); 18949bdca14aSAlexander Lobakin 18959bdca14aSAlexander Lobakin fecparam->active_fec = qede_link_to_ethtool_fec(curr_link.active_fec); 18969bdca14aSAlexander Lobakin fecparam->fec = qede_link_to_ethtool_fec(curr_link.sup_fec); 18979bdca14aSAlexander Lobakin 18989bdca14aSAlexander Lobakin return 0; 18999bdca14aSAlexander Lobakin } 19009bdca14aSAlexander Lobakin 19019bdca14aSAlexander Lobakin static int qede_set_fecparam(struct net_device *dev, 19029bdca14aSAlexander Lobakin struct ethtool_fecparam *fecparam) 19039bdca14aSAlexander Lobakin { 19049bdca14aSAlexander Lobakin struct qede_dev *edev = netdev_priv(dev); 19059bdca14aSAlexander Lobakin struct qed_link_params params; 19069bdca14aSAlexander Lobakin 19079bdca14aSAlexander Lobakin if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 19089bdca14aSAlexander Lobakin DP_INFO(edev, "Link settings are not allowed to be changed\n"); 19099bdca14aSAlexander Lobakin return -EOPNOTSUPP; 19109bdca14aSAlexander Lobakin } 19119bdca14aSAlexander Lobakin 19129bdca14aSAlexander Lobakin memset(¶ms, 0, sizeof(params)); 19139bdca14aSAlexander Lobakin params.override_flags |= QED_LINK_OVERRIDE_FEC_CONFIG; 19149bdca14aSAlexander Lobakin params.fec = qede_ethtool_to_link_fec(fecparam->fec); 19159bdca14aSAlexander Lobakin params.link_up = true; 19169bdca14aSAlexander Lobakin 19179bdca14aSAlexander Lobakin edev->ops->common->set_link(edev->cdev, ¶ms); 19189bdca14aSAlexander Lobakin 19199bdca14aSAlexander Lobakin return 0; 19209bdca14aSAlexander Lobakin } 19219bdca14aSAlexander Lobakin 192297df0d65SSudarsana Reddy Kalluru static int qede_get_module_info(struct net_device *dev, 192397df0d65SSudarsana Reddy Kalluru struct ethtool_modinfo *modinfo) 192497df0d65SSudarsana Reddy Kalluru { 192597df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 192697df0d65SSudarsana Reddy Kalluru u8 buf[4]; 192797df0d65SSudarsana Reddy Kalluru int rc; 192897df0d65SSudarsana Reddy Kalluru 192997df0d65SSudarsana Reddy Kalluru /* Read first 4 bytes to find the sfp type */ 193097df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 193197df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 0, 4); 193297df0d65SSudarsana Reddy Kalluru if (rc) { 193397df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading EEPROM data %d\n", rc); 193497df0d65SSudarsana Reddy Kalluru return rc; 193597df0d65SSudarsana Reddy Kalluru } 193697df0d65SSudarsana Reddy Kalluru 193797df0d65SSudarsana Reddy Kalluru switch (buf[0]) { 193897df0d65SSudarsana Reddy Kalluru case 0x3: /* SFP, SFP+, SFP-28 */ 193997df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8472; 194097df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 194197df0d65SSudarsana Reddy Kalluru break; 194297df0d65SSudarsana Reddy Kalluru case 0xc: /* QSFP */ 194397df0d65SSudarsana Reddy Kalluru case 0xd: /* QSFP+ */ 194497df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8436; 194597df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; 194697df0d65SSudarsana Reddy Kalluru break; 194797df0d65SSudarsana Reddy Kalluru case 0x11: /* QSFP-28 */ 194897df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8636; 194997df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; 195097df0d65SSudarsana Reddy Kalluru break; 195197df0d65SSudarsana Reddy Kalluru default: 195297df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]); 195397df0d65SSudarsana Reddy Kalluru return -EINVAL; 195497df0d65SSudarsana Reddy Kalluru } 195597df0d65SSudarsana Reddy Kalluru 195697df0d65SSudarsana Reddy Kalluru return 0; 195797df0d65SSudarsana Reddy Kalluru } 195897df0d65SSudarsana Reddy Kalluru 195997df0d65SSudarsana Reddy Kalluru static int qede_get_module_eeprom(struct net_device *dev, 196097df0d65SSudarsana Reddy Kalluru struct ethtool_eeprom *ee, u8 *data) 196197df0d65SSudarsana Reddy Kalluru { 196297df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 196397df0d65SSudarsana Reddy Kalluru u32 start_addr = ee->offset, size = 0; 196497df0d65SSudarsana Reddy Kalluru u8 *buf = data; 196597df0d65SSudarsana Reddy Kalluru int rc = 0; 196697df0d65SSudarsana Reddy Kalluru 196797df0d65SSudarsana Reddy Kalluru /* Read A0 section */ 196897df0d65SSudarsana Reddy Kalluru if (ee->offset < ETH_MODULE_SFF_8079_LEN) { 196997df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A0 section boundary */ 197097df0d65SSudarsana Reddy Kalluru if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN) 197197df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8079_LEN - ee->offset; 197297df0d65SSudarsana Reddy Kalluru else 197397df0d65SSudarsana Reddy Kalluru size = ee->len; 197497df0d65SSudarsana Reddy Kalluru 197597df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 197697df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 197797df0d65SSudarsana Reddy Kalluru start_addr, size); 197897df0d65SSudarsana Reddy Kalluru if (rc) { 197997df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading A0 section %d\n", rc); 198097df0d65SSudarsana Reddy Kalluru return rc; 198197df0d65SSudarsana Reddy Kalluru } 198297df0d65SSudarsana Reddy Kalluru 198397df0d65SSudarsana Reddy Kalluru buf += size; 198497df0d65SSudarsana Reddy Kalluru start_addr += size; 198597df0d65SSudarsana Reddy Kalluru } 198697df0d65SSudarsana Reddy Kalluru 198797df0d65SSudarsana Reddy Kalluru /* Read A2 section */ 198897df0d65SSudarsana Reddy Kalluru if (start_addr >= ETH_MODULE_SFF_8079_LEN && 198997df0d65SSudarsana Reddy Kalluru start_addr < ETH_MODULE_SFF_8472_LEN) { 199097df0d65SSudarsana Reddy Kalluru size = ee->len - size; 199197df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A2 section boundary */ 199297df0d65SSudarsana Reddy Kalluru if (start_addr + size > ETH_MODULE_SFF_8472_LEN) 199397df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8472_LEN - start_addr; 199497df0d65SSudarsana Reddy Kalluru start_addr -= ETH_MODULE_SFF_8079_LEN; 199597df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 199697df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A2, 199797df0d65SSudarsana Reddy Kalluru start_addr, size); 199897df0d65SSudarsana Reddy Kalluru if (rc) { 199997df0d65SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 200097df0d65SSudarsana Reddy Kalluru "Failed reading A2 section %d\n", rc); 200197df0d65SSudarsana Reddy Kalluru return 0; 200297df0d65SSudarsana Reddy Kalluru } 200397df0d65SSudarsana Reddy Kalluru } 200497df0d65SSudarsana Reddy Kalluru 200597df0d65SSudarsana Reddy Kalluru return rc; 200697df0d65SSudarsana Reddy Kalluru } 200797df0d65SSudarsana Reddy Kalluru 2008d44a3cedSSudarsana Reddy Kalluru static int qede_set_dump(struct net_device *dev, struct ethtool_dump *val) 2009d44a3cedSSudarsana Reddy Kalluru { 2010d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 2011d44a3cedSSudarsana Reddy Kalluru int rc = 0; 2012d44a3cedSSudarsana Reddy Kalluru 2013d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.cmd == QEDE_DUMP_CMD_NONE) { 2014d44a3cedSSudarsana Reddy Kalluru if (val->flag > QEDE_DUMP_CMD_MAX) { 2015d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Invalid command %d\n", val->flag); 2016d44a3cedSSudarsana Reddy Kalluru return -EINVAL; 2017d44a3cedSSudarsana Reddy Kalluru } 2018d44a3cedSSudarsana Reddy Kalluru edev->dump_info.cmd = val->flag; 2019d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args = 0; 2020d44a3cedSSudarsana Reddy Kalluru return 0; 2021d44a3cedSSudarsana Reddy Kalluru } 2022d44a3cedSSudarsana Reddy Kalluru 2023d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.num_args == QEDE_DUMP_MAX_ARGS) { 2024d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Arg count = %d\n", edev->dump_info.num_args); 2025d44a3cedSSudarsana Reddy Kalluru return -EINVAL; 2026d44a3cedSSudarsana Reddy Kalluru } 2027d44a3cedSSudarsana Reddy Kalluru 2028d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) { 2029d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG: 2030d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[edev->dump_info.num_args] = val->flag; 2031d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args++; 2032d44a3cedSSudarsana Reddy Kalluru break; 2033849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP: 2034849dbf09SSudarsana Reddy Kalluru rc = edev->ops->common->set_grc_config(edev->cdev, 2035849dbf09SSudarsana Reddy Kalluru val->flag, 1); 2036849dbf09SSudarsana Reddy Kalluru break; 2037d44a3cedSSudarsana Reddy Kalluru default: 2038d44a3cedSSudarsana Reddy Kalluru break; 2039d44a3cedSSudarsana Reddy Kalluru } 2040d44a3cedSSudarsana Reddy Kalluru 2041d44a3cedSSudarsana Reddy Kalluru return rc; 2042d44a3cedSSudarsana Reddy Kalluru } 2043d44a3cedSSudarsana Reddy Kalluru 2044d44a3cedSSudarsana Reddy Kalluru static int qede_get_dump_flag(struct net_device *dev, 2045d44a3cedSSudarsana Reddy Kalluru struct ethtool_dump *dump) 2046d44a3cedSSudarsana Reddy Kalluru { 2047d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 2048d44a3cedSSudarsana Reddy Kalluru 2049849dbf09SSudarsana Reddy Kalluru if (!edev->ops || !edev->ops->common) { 2050849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Edev ops not populated\n"); 2051849dbf09SSudarsana Reddy Kalluru return -EINVAL; 2052849dbf09SSudarsana Reddy Kalluru } 2053849dbf09SSudarsana Reddy Kalluru 2054d44a3cedSSudarsana Reddy Kalluru dump->version = QEDE_DUMP_VERSION; 2055d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) { 2056d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG: 2057d44a3cedSSudarsana Reddy Kalluru dump->flag = QEDE_DUMP_CMD_NVM_CFG; 20589e54ba7cSSudarsana Reddy Kalluru dump->len = edev->ops->common->read_nvm_cfg_len(edev->cdev, 20599e54ba7cSSudarsana Reddy Kalluru edev->dump_info.args[0]); 2060d44a3cedSSudarsana Reddy Kalluru break; 2061849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP: 2062849dbf09SSudarsana Reddy Kalluru dump->flag = QEDE_DUMP_CMD_GRCDUMP; 2063849dbf09SSudarsana Reddy Kalluru dump->len = edev->ops->common->dbg_all_data_size(edev->cdev); 2064d44a3cedSSudarsana Reddy Kalluru break; 2065849dbf09SSudarsana Reddy Kalluru default: 2066849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd); 2067849dbf09SSudarsana Reddy Kalluru return -EINVAL; 2068d44a3cedSSudarsana Reddy Kalluru } 2069d44a3cedSSudarsana Reddy Kalluru 2070d44a3cedSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 2071d44a3cedSSudarsana Reddy Kalluru "dump->version = 0x%x dump->flag = %d dump->len = %d\n", 2072d44a3cedSSudarsana Reddy Kalluru dump->version, dump->flag, dump->len); 2073d44a3cedSSudarsana Reddy Kalluru return 0; 2074d44a3cedSSudarsana Reddy Kalluru } 2075d44a3cedSSudarsana Reddy Kalluru 2076d44a3cedSSudarsana Reddy Kalluru static int qede_get_dump_data(struct net_device *dev, 2077d44a3cedSSudarsana Reddy Kalluru struct ethtool_dump *dump, void *buf) 2078d44a3cedSSudarsana Reddy Kalluru { 2079d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 2080849dbf09SSudarsana Reddy Kalluru int rc = 0; 2081849dbf09SSudarsana Reddy Kalluru 2082849dbf09SSudarsana Reddy Kalluru if (!edev->ops || !edev->ops->common) { 2083849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Edev ops not populated\n"); 20849e54ba7cSSudarsana Reddy Kalluru rc = -EINVAL; 20859e54ba7cSSudarsana Reddy Kalluru goto err; 2086849dbf09SSudarsana Reddy Kalluru } 2087d44a3cedSSudarsana Reddy Kalluru 2088d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) { 2089d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG: 2090d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.num_args != QEDE_DUMP_NVM_ARG_COUNT) { 2091d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Arg count = %d required = %d\n", 2092d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args, 2093d44a3cedSSudarsana Reddy Kalluru QEDE_DUMP_NVM_ARG_COUNT); 20949e54ba7cSSudarsana Reddy Kalluru rc = -EINVAL; 20959e54ba7cSSudarsana Reddy Kalluru goto err; 2096d44a3cedSSudarsana Reddy Kalluru } 2097d44a3cedSSudarsana Reddy Kalluru rc = edev->ops->common->read_nvm_cfg(edev->cdev, (u8 **)&buf, 2098d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[0], 2099d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[1]); 2100d44a3cedSSudarsana Reddy Kalluru break; 2101849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP: 2102849dbf09SSudarsana Reddy Kalluru memset(buf, 0, dump->len); 2103849dbf09SSudarsana Reddy Kalluru rc = edev->ops->common->dbg_all_data(edev->cdev, buf); 2104849dbf09SSudarsana Reddy Kalluru break; 2105d44a3cedSSudarsana Reddy Kalluru default: 2106d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd); 2107d44a3cedSSudarsana Reddy Kalluru rc = -EINVAL; 2108d44a3cedSSudarsana Reddy Kalluru break; 2109d44a3cedSSudarsana Reddy Kalluru } 2110d44a3cedSSudarsana Reddy Kalluru 21119e54ba7cSSudarsana Reddy Kalluru err: 2112d44a3cedSSudarsana Reddy Kalluru edev->dump_info.cmd = QEDE_DUMP_CMD_NONE; 2113d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args = 0; 21149e54ba7cSSudarsana Reddy Kalluru memset(edev->dump_info.args, 0, sizeof(edev->dump_info.args)); 2115d44a3cedSSudarsana Reddy Kalluru 2116d44a3cedSSudarsana Reddy Kalluru return rc; 2117d44a3cedSSudarsana Reddy Kalluru } 2118d44a3cedSSudarsana Reddy Kalluru 2119b0ec5489SBhaskar Upadhaya int qede_set_per_coalesce(struct net_device *dev, u32 queue, 2120a0d2d97dSBhaskar Upadhaya struct ethtool_coalesce *coal) 2121a0d2d97dSBhaskar Upadhaya { 2122a0d2d97dSBhaskar Upadhaya struct qede_dev *edev = netdev_priv(dev); 2123a0d2d97dSBhaskar Upadhaya struct qede_fastpath *fp; 2124a0d2d97dSBhaskar Upadhaya u16 rxc, txc; 2125a0d2d97dSBhaskar Upadhaya int rc = 0; 2126a0d2d97dSBhaskar Upadhaya 2127a0d2d97dSBhaskar Upadhaya if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 2128a0d2d97dSBhaskar Upadhaya coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 2129a0d2d97dSBhaskar Upadhaya DP_INFO(edev, 2130a0d2d97dSBhaskar Upadhaya "Can't support requested %s coalesce value [max supported value %d]\n", 2131a0d2d97dSBhaskar Upadhaya coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" 2132a0d2d97dSBhaskar Upadhaya : "tx", 2133a0d2d97dSBhaskar Upadhaya QED_COALESCE_MAX); 2134a0d2d97dSBhaskar Upadhaya return -EINVAL; 2135a0d2d97dSBhaskar Upadhaya } 2136a0d2d97dSBhaskar Upadhaya 2137a0d2d97dSBhaskar Upadhaya rxc = (u16)coal->rx_coalesce_usecs; 2138a0d2d97dSBhaskar Upadhaya txc = (u16)coal->tx_coalesce_usecs; 2139a0d2d97dSBhaskar Upadhaya 2140a0d2d97dSBhaskar Upadhaya __qede_lock(edev); 2141a0d2d97dSBhaskar Upadhaya if (queue >= edev->num_queues) { 2142a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Invalid queue\n"); 2143a0d2d97dSBhaskar Upadhaya rc = -EINVAL; 2144a0d2d97dSBhaskar Upadhaya goto out; 2145a0d2d97dSBhaskar Upadhaya } 2146a0d2d97dSBhaskar Upadhaya 2147a0d2d97dSBhaskar Upadhaya if (edev->state != QEDE_STATE_OPEN) { 2148a0d2d97dSBhaskar Upadhaya rc = -EINVAL; 2149a0d2d97dSBhaskar Upadhaya goto out; 2150a0d2d97dSBhaskar Upadhaya } 2151a0d2d97dSBhaskar Upadhaya 2152a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue]; 2153a0d2d97dSBhaskar Upadhaya 2154a0d2d97dSBhaskar Upadhaya if (edev->fp_array[queue].type & QEDE_FASTPATH_RX) { 2155a0d2d97dSBhaskar Upadhaya rc = edev->ops->common->set_coalesce(edev->cdev, 2156a0d2d97dSBhaskar Upadhaya rxc, 0, 2157a0d2d97dSBhaskar Upadhaya fp->rxq->handle); 2158a0d2d97dSBhaskar Upadhaya if (rc) { 2159a0d2d97dSBhaskar Upadhaya DP_INFO(edev, 2160a0d2d97dSBhaskar Upadhaya "Set RX coalesce error, rc = %d\n", rc); 2161a0d2d97dSBhaskar Upadhaya goto out; 2162a0d2d97dSBhaskar Upadhaya } 2163b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].rxc = rxc; 2164b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].isvalid = true; 2165a0d2d97dSBhaskar Upadhaya } 2166a0d2d97dSBhaskar Upadhaya 2167a0d2d97dSBhaskar Upadhaya if (edev->fp_array[queue].type & QEDE_FASTPATH_TX) { 2168a0d2d97dSBhaskar Upadhaya rc = edev->ops->common->set_coalesce(edev->cdev, 2169a0d2d97dSBhaskar Upadhaya 0, txc, 2170a0d2d97dSBhaskar Upadhaya fp->txq->handle); 2171a0d2d97dSBhaskar Upadhaya if (rc) { 2172a0d2d97dSBhaskar Upadhaya DP_INFO(edev, 2173a0d2d97dSBhaskar Upadhaya "Set TX coalesce error, rc = %d\n", rc); 2174a0d2d97dSBhaskar Upadhaya goto out; 2175a0d2d97dSBhaskar Upadhaya } 2176b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].txc = txc; 2177b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].isvalid = true; 2178a0d2d97dSBhaskar Upadhaya } 2179a0d2d97dSBhaskar Upadhaya out: 2180a0d2d97dSBhaskar Upadhaya __qede_unlock(edev); 2181a0d2d97dSBhaskar Upadhaya 2182a0d2d97dSBhaskar Upadhaya return rc; 2183a0d2d97dSBhaskar Upadhaya } 2184a0d2d97dSBhaskar Upadhaya 2185a0d2d97dSBhaskar Upadhaya static int qede_get_per_coalesce(struct net_device *dev, 2186a0d2d97dSBhaskar Upadhaya u32 queue, 2187a0d2d97dSBhaskar Upadhaya struct ethtool_coalesce *coal) 2188a0d2d97dSBhaskar Upadhaya { 2189a0d2d97dSBhaskar Upadhaya void *rx_handle = NULL, *tx_handle = NULL; 2190a0d2d97dSBhaskar Upadhaya struct qede_dev *edev = netdev_priv(dev); 2191a0d2d97dSBhaskar Upadhaya struct qede_fastpath *fp; 2192a0d2d97dSBhaskar Upadhaya u16 rx_coal, tx_coal; 2193a0d2d97dSBhaskar Upadhaya int rc = 0; 2194a0d2d97dSBhaskar Upadhaya 2195a0d2d97dSBhaskar Upadhaya rx_coal = QED_DEFAULT_RX_USECS; 2196a0d2d97dSBhaskar Upadhaya tx_coal = QED_DEFAULT_TX_USECS; 2197a0d2d97dSBhaskar Upadhaya 2198a0d2d97dSBhaskar Upadhaya memset(coal, 0, sizeof(struct ethtool_coalesce)); 2199a0d2d97dSBhaskar Upadhaya 2200a0d2d97dSBhaskar Upadhaya __qede_lock(edev); 2201a0d2d97dSBhaskar Upadhaya if (queue >= edev->num_queues) { 2202a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Invalid queue\n"); 2203a0d2d97dSBhaskar Upadhaya rc = -EINVAL; 2204a0d2d97dSBhaskar Upadhaya goto out; 2205a0d2d97dSBhaskar Upadhaya } 2206a0d2d97dSBhaskar Upadhaya 2207a0d2d97dSBhaskar Upadhaya if (edev->state != QEDE_STATE_OPEN) { 2208a0d2d97dSBhaskar Upadhaya rc = -EINVAL; 2209a0d2d97dSBhaskar Upadhaya goto out; 2210a0d2d97dSBhaskar Upadhaya } 2211a0d2d97dSBhaskar Upadhaya 2212a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue]; 2213a0d2d97dSBhaskar Upadhaya 2214a0d2d97dSBhaskar Upadhaya if (fp->type & QEDE_FASTPATH_RX) 2215a0d2d97dSBhaskar Upadhaya rx_handle = fp->rxq->handle; 2216a0d2d97dSBhaskar Upadhaya 2217a0d2d97dSBhaskar Upadhaya rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, 2218a0d2d97dSBhaskar Upadhaya rx_handle); 2219a0d2d97dSBhaskar Upadhaya if (rc) { 2220a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Read Rx coalesce error\n"); 2221a0d2d97dSBhaskar Upadhaya goto out; 2222a0d2d97dSBhaskar Upadhaya } 2223a0d2d97dSBhaskar Upadhaya 2224a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue]; 2225a0d2d97dSBhaskar Upadhaya if (fp->type & QEDE_FASTPATH_TX) 2226a0d2d97dSBhaskar Upadhaya tx_handle = fp->txq->handle; 2227a0d2d97dSBhaskar Upadhaya 2228a0d2d97dSBhaskar Upadhaya rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, 2229a0d2d97dSBhaskar Upadhaya tx_handle); 2230a0d2d97dSBhaskar Upadhaya if (rc) 2231a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Read Tx coalesce error\n"); 2232a0d2d97dSBhaskar Upadhaya 2233a0d2d97dSBhaskar Upadhaya out: 2234a0d2d97dSBhaskar Upadhaya __qede_unlock(edev); 2235a0d2d97dSBhaskar Upadhaya 2236a0d2d97dSBhaskar Upadhaya coal->rx_coalesce_usecs = rx_coal; 2237a0d2d97dSBhaskar Upadhaya coal->tx_coalesce_usecs = tx_coal; 2238a0d2d97dSBhaskar Upadhaya 2239a0d2d97dSBhaskar Upadhaya return rc; 2240a0d2d97dSBhaskar Upadhaya } 2241a0d2d97dSBhaskar Upadhaya 2242133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 2243c9312022SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS, 2244054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 2245054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 2246133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 2247e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 2248e0971c83STomer Tayar .get_regs = qede_get_regs, 224914d39648SMintz, Yuval .get_wol = qede_get_wol, 225014d39648SMintz, Yuval .set_wol = qede_set_wol, 2251133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 2252133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 225332a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 2254133fac0eSSudarsana Kalluru .get_link = qede_get_link, 2255d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 2256d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 225701ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 225801ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 22590f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 22600f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 2261133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 22623d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 2263133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 2264f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 22657d9acd87SIgor Russkikh .set_priv_flags = qede_set_priv_flags, 2266133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 2267961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 2268961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 2269961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 2270961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 2271961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 2272961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 22734c55215cSSudarsana Reddy Kalluru .get_ts_info = qede_get_ts_info, 22748edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 22758edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 22763044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 227797df0d65SSudarsana Reddy Kalluru .get_module_info = qede_get_module_info, 227897df0d65SSudarsana Reddy Kalluru .get_module_eeprom = qede_get_module_eeprom, 2279c3dc48f7SSudarsana Reddy Kalluru .get_eee = qede_get_eee, 2280c3dc48f7SSudarsana Reddy Kalluru .set_eee = qede_set_eee, 22819bdca14aSAlexander Lobakin .get_fecparam = qede_get_fecparam, 22829bdca14aSAlexander Lobakin .set_fecparam = qede_set_fecparam, 22833d789994SManish Chopra .get_tunable = qede_get_tunable, 22843d789994SManish Chopra .set_tunable = qede_set_tunable, 2285a0d2d97dSBhaskar Upadhaya .get_per_queue_coalesce = qede_get_per_coalesce, 2286a0d2d97dSBhaskar Upadhaya .set_per_queue_coalesce = qede_set_per_coalesce, 2287ccfa110cSSudarsana Reddy Kalluru .flash_device = qede_flash_device, 2288d44a3cedSSudarsana Reddy Kalluru .get_dump_flag = qede_get_dump_flag, 2289d44a3cedSSudarsana Reddy Kalluru .get_dump_data = qede_get_dump_data, 2290d44a3cedSSudarsana Reddy Kalluru .set_dump = qede_set_dump, 2291133fac0eSSudarsana Kalluru }; 2292133fac0eSSudarsana Kalluru 2293fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 2294c9312022SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS, 2295054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 2296fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 2297fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 2298fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 2299fefb0202SYuval Mintz .get_link = qede_get_link, 2300477f2d14SRahul Verma .get_coalesce = qede_get_coalesce, 2301477f2d14SRahul Verma .set_coalesce = qede_set_coalesce, 2302fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 2303fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 2304fefb0202SYuval Mintz .get_strings = qede_get_strings, 2305fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 2306fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 2307fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 2308fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 2309fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 2310fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 2311fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 2312fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 2313fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 2314fefb0202SYuval Mintz .get_channels = qede_get_channels, 2315fefb0202SYuval Mintz .set_channels = qede_set_channels, 2316a0d2d97dSBhaskar Upadhaya .get_per_queue_coalesce = qede_get_per_coalesce, 2317a0d2d97dSBhaskar Upadhaya .set_per_queue_coalesce = qede_set_per_coalesce, 23183d789994SManish Chopra .get_tunable = qede_get_tunable, 23193d789994SManish Chopra .set_tunable = qede_set_tunable, 2320fefb0202SYuval Mintz }; 2321fefb0202SYuval Mintz 2322133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 2323133fac0eSSudarsana Kalluru { 2324fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 2325fefb0202SYuval Mintz 2326fefb0202SYuval Mintz if (IS_VF(edev)) 2327fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 2328fefb0202SYuval Mintz else 2329133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 2330133fac0eSSudarsana Kalluru } 2331