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/types.h>
8133fac0eSSudarsana Kalluru #include <linux/netdevice.h>
916f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h>
10133fac0eSSudarsana Kalluru #include <linux/ethtool.h>
11133fac0eSSudarsana Kalluru #include <linux/string.h>
12133fac0eSSudarsana Kalluru #include <linux/pci.h>
13133fac0eSSudarsana Kalluru #include <linux/capability.h>
14f29ffdb6SMintz, Yuval #include <linux/vmalloc.h>
15bdb5d8ecSAlexander Lobakin #include <linux/phylink.h>
16bdb5d8ecSAlexander Lobakin
17133fac0eSSudarsana Kalluru #include "qede.h"
184c55215cSSudarsana Reddy Kalluru #include "qede_ptp.h"
19133fac0eSSudarsana Kalluru
20133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \
21133fac0eSSudarsana Kalluru (offsetof(struct qede_rx_queue, stat_name))
22133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name)
23133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \
24133fac0eSSudarsana Kalluru {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)}
2516f46bf0SSudarsana Reddy Kalluru
2616f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100
27d44a3cedSSudarsana Reddy Kalluru #define QEDE_DUMP_VERSION 0x1
28d44a3cedSSudarsana Reddy Kalluru #define QEDE_DUMP_NVM_ARG_COUNT 2
2916f46bf0SSudarsana Reddy Kalluru
30133fac0eSSudarsana Kalluru static const struct {
31133fac0eSSudarsana Kalluru u64 offset;
32133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN];
33133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = {
3468db9ec2SSudarsana Reddy Kalluru QEDE_RQSTAT(rcv_pkts),
35133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_hw_errors),
36133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_alloc_errors),
37c72a6125SManish Chopra QEDE_RQSTAT(rx_ip_frags),
38496e0517SMintz, Yuval QEDE_RQSTAT(xdp_no_pass),
39133fac0eSSudarsana Kalluru };
40133fac0eSSudarsana Kalluru
41133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
4268db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \
4368db9ec2SSudarsana Reddy Kalluru (offsetof(struct qede_tx_queue, stat_name))
4468db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name)
4568db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \
4668db9ec2SSudarsana Reddy Kalluru {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)}
4768db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr)
4868db9ec2SSudarsana Reddy Kalluru static const struct {
4968db9ec2SSudarsana Reddy Kalluru u64 offset;
5068db9ec2SSudarsana Reddy Kalluru char string[ETH_GSTRING_LEN];
5168db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = {
5268db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(xmit_pkts),
5368db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(stopped_cnt),
54dcc6abaeSMichael Shteinbok QEDE_TQSTAT(tx_mem_alloc_err),
5568db9ec2SSudarsana Reddy Kalluru };
5668db9ec2SSudarsana Reddy Kalluru
579c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \
589c79ddaaSMintz, Yuval (offsetof(type, stat_name) + (base))
594dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name) (#stat_name)
609c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \
619c79ddaaSMintz, Yuval {QEDE_STAT_OFFSET(stat_name, type, base), \
629c79ddaaSMintz, Yuval QEDE_STAT_STRING(stat_name), \
639c79ddaaSMintz, Yuval attr}
649c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \
659c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0)
669c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \
679c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, \
689c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY))
699c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \
709c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_bb, \
719c79ddaaSMintz, Yuval offsetof(struct qede_stats, bb), \
729c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY))
739c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \
749c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_ah, \
759c79ddaaSMintz, Yuval offsetof(struct qede_stats, ah), \
769c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY))
77133fac0eSSudarsana Kalluru static const struct {
78133fac0eSSudarsana Kalluru u64 offset;
79133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN];
809c79ddaaSMintz, Yuval unsigned long attr;
819c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY 0
829c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY 1
839c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY 2
84133fac0eSSudarsana Kalluru } qede_stats_arr[] = {
85133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes),
86133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes),
87133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes),
88133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts),
89133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts),
90133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts),
91133fac0eSSudarsana Kalluru
92133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes),
93133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes),
94133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes),
95133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts),
96133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts),
97133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts),
98133fac0eSSudarsana Kalluru
99133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets),
100d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets),
101d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets),
102d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets),
103d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets),
104d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets),
1059c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets),
1069c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets),
1079c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets),
1089c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets),
1099c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets),
1109c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets),
111133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets),
112133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets),
113133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets),
114133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets),
115133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets),
116133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets),
1179c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets),
1189c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets),
1199c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets),
1209c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets),
1219c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets),
122133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames),
123133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames),
124133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames),
125133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames),
126133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames),
127133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames),
128133fac0eSSudarsana Kalluru
129133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors),
130133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors),
131133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors),
132133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets),
133133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers),
134133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets),
135133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments),
1369c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_lpi_entry_count),
1379c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_total_collisions),
138133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates),
139133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards),
140133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards),
141133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards),
142133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards),
143608e00d0SManish Chopra QEDE_PF_STAT(gft_filter_drop),
144133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts),
1451a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard),
1461a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard),
147133fac0eSSudarsana Kalluru
148133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts),
149133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events),
150133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num),
151133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts),
152133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes),
15332d26a68SSudarsana Reddy Kalluru
15432d26a68SSudarsana Reddy Kalluru QEDE_STAT(link_change_count),
1559adebac3SSudarsana Reddy Kalluru QEDE_STAT(ptp_skip_txts),
156133fac0eSSudarsana Kalluru };
157133fac0eSSudarsana Kalluru
158133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr)
1599c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \
1609c79ddaaSMintz, Yuval test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr)
1619c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \
1629c79ddaaSMintz, Yuval test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr)
1639c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \
1649c79ddaaSMintz, Yuval test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr)
165133fac0eSSudarsana Kalluru
166f3e72109SYuval Mintz enum {
167f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT,
168f15cff04SSudarsana Reddy Kalluru QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */
1697d9acd87SIgor Russkikh QEDE_PRI_FLAG_RECOVER_ON_ERROR,
170823163baSManish Chopra QEDE_PRI_FLAG_ESL_SUPPORT, /* MFW supports Enhanced System Lockdown */
171823163baSManish Chopra QEDE_PRI_FLAG_ESL_ACTIVE, /* Enhanced System Lockdown Active status */
172f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN,
173f3e72109SYuval Mintz };
174f3e72109SYuval Mintz
175f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
176f3e72109SYuval Mintz "Coupled-Function",
177f15cff04SSudarsana Reddy Kalluru "SmartAN capable",
1787d9acd87SIgor Russkikh "Recover on error",
179823163baSManish Chopra "ESL capable",
180823163baSManish Chopra "ESL active",
181f3e72109SYuval Mintz };
182f3e72109SYuval Mintz
1833044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests {
18416f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK,
1853044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST,
1863044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST,
1873044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST,
1883044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST,
1897a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST,
1903044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX
1913044a02eSSudarsana Reddy Kalluru };
1923044a02eSSudarsana Reddy Kalluru
1933044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
19416f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)",
1953044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t",
1963044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t",
1973044a02eSSudarsana Reddy Kalluru "Register (online)\t",
1983044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t",
1997a4b21b7SMintz, Yuval "Nvram (online)\t\t",
2003044a02eSSudarsana Reddy Kalluru };
2013044a02eSSudarsana Reddy Kalluru
2021d4e4eccSAlexander Lobakin /* Forced speed capabilities maps */
2031d4e4eccSAlexander Lobakin
2041d4e4eccSAlexander Lobakin struct qede_forced_speed_map {
2051d4e4eccSAlexander Lobakin u32 speed;
2061d4e4eccSAlexander Lobakin __ETHTOOL_DECLARE_LINK_MODE_MASK(caps);
2071d4e4eccSAlexander Lobakin
2081d4e4eccSAlexander Lobakin const u32 *cap_arr;
2091d4e4eccSAlexander Lobakin u32 arr_size;
2101d4e4eccSAlexander Lobakin };
2111d4e4eccSAlexander Lobakin
2121d4e4eccSAlexander Lobakin #define QEDE_FORCED_SPEED_MAP(value) \
2131d4e4eccSAlexander Lobakin { \
2141d4e4eccSAlexander Lobakin .speed = SPEED_##value, \
2151d4e4eccSAlexander Lobakin .cap_arr = qede_forced_speed_##value, \
2161d4e4eccSAlexander Lobakin .arr_size = ARRAY_SIZE(qede_forced_speed_##value), \
2171d4e4eccSAlexander Lobakin }
2181d4e4eccSAlexander Lobakin
2191d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_1000[] __initconst = {
2201d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
2211d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
2221d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
2231d4e4eccSAlexander Lobakin };
2241d4e4eccSAlexander Lobakin
2251d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_10000[] __initconst = {
2261d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
2271d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
2281d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
2291d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
2301d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
2311d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
2321d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
2331d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
2341d4e4eccSAlexander Lobakin };
2351d4e4eccSAlexander Lobakin
2361d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_20000[] __initconst = {
2371d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
2381d4e4eccSAlexander Lobakin };
2391d4e4eccSAlexander Lobakin
2401d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_25000[] __initconst = {
2411d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
2421d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
2431d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
2441d4e4eccSAlexander Lobakin };
2451d4e4eccSAlexander Lobakin
2461d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_40000[] __initconst = {
2471d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
2481d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
2491d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
2501d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
2511d4e4eccSAlexander Lobakin };
2521d4e4eccSAlexander Lobakin
2531d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_50000[] __initconst = {
2541d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
2551d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
2561d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
2571d4e4eccSAlexander Lobakin };
2581d4e4eccSAlexander Lobakin
2591d4e4eccSAlexander Lobakin static const u32 qede_forced_speed_100000[] __initconst = {
2601d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
2611d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
2621d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
2631d4e4eccSAlexander Lobakin ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
2641d4e4eccSAlexander Lobakin };
2651d4e4eccSAlexander Lobakin
2661d4e4eccSAlexander Lobakin static struct qede_forced_speed_map qede_forced_speed_maps[] __ro_after_init = {
2671d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(1000),
2681d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(10000),
2691d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(20000),
2701d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(25000),
2711d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(40000),
2721d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(50000),
2731d4e4eccSAlexander Lobakin QEDE_FORCED_SPEED_MAP(100000),
2741d4e4eccSAlexander Lobakin };
2751d4e4eccSAlexander Lobakin
qede_forced_speed_maps_init(void)2761d4e4eccSAlexander Lobakin void __init qede_forced_speed_maps_init(void)
2771d4e4eccSAlexander Lobakin {
2781d4e4eccSAlexander Lobakin struct qede_forced_speed_map *map;
2791d4e4eccSAlexander Lobakin u32 i;
2801d4e4eccSAlexander Lobakin
2811d4e4eccSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) {
2821d4e4eccSAlexander Lobakin map = qede_forced_speed_maps + i;
2831d4e4eccSAlexander Lobakin
2841d4e4eccSAlexander Lobakin linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps);
2851d4e4eccSAlexander Lobakin map->cap_arr = NULL;
2861d4e4eccSAlexander Lobakin map->arr_size = 0;
2871d4e4eccSAlexander Lobakin }
2881d4e4eccSAlexander Lobakin }
2891d4e4eccSAlexander Lobakin
2901d4e4eccSAlexander Lobakin /* Ethtool callbacks */
2911d4e4eccSAlexander Lobakin
qede_get_strings_stats_txq(struct qede_dev * edev,struct qede_tx_queue * txq,u8 ** buf)2924dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev,
2934dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf)
2944dbcd640SMintz, Yuval {
2954dbcd640SMintz, Yuval int i;
2964dbcd640SMintz, Yuval
2974dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
298cb6aeb07SMintz, Yuval if (txq->is_xdp)
299cb6aeb07SMintz, Yuval sprintf(*buf, "%d [XDP]: %s",
300cb6aeb07SMintz, Yuval QEDE_TXQ_XDP_TO_IDX(edev, txq),
301cb6aeb07SMintz, Yuval qede_tqstats_arr[i].string);
302cb6aeb07SMintz, Yuval else
3035e7baf0fSManish Chopra sprintf(*buf, "%d_%d: %s", txq->index, txq->cos,
3044dbcd640SMintz, Yuval qede_tqstats_arr[i].string);
3054dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN;
3064dbcd640SMintz, Yuval }
3074dbcd640SMintz, Yuval }
3084dbcd640SMintz, Yuval
qede_get_strings_stats_rxq(struct qede_dev * edev,struct qede_rx_queue * rxq,u8 ** buf)3094dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev,
3104dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf)
3114dbcd640SMintz, Yuval {
3124dbcd640SMintz, Yuval int i;
3134dbcd640SMintz, Yuval
3144dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
3154dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id,
3164dbcd640SMintz, Yuval qede_rqstats_arr[i].string);
3174dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN;
3184dbcd640SMintz, Yuval }
3194dbcd640SMintz, Yuval }
3204dbcd640SMintz, Yuval
qede_is_irrelevant_stat(struct qede_dev * edev,int stat_index)3219c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index)
3229c79ddaaSMintz, Yuval {
3239c79ddaaSMintz, Yuval return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) ||
3249c79ddaaSMintz, Yuval (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) ||
3259c79ddaaSMintz, Yuval (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index));
3269c79ddaaSMintz, Yuval }
3279c79ddaaSMintz, Yuval
qede_get_strings_stats(struct qede_dev * edev,u8 * buf)328133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
329133fac0eSSudarsana Kalluru {
3304dbcd640SMintz, Yuval struct qede_fastpath *fp;
3314dbcd640SMintz, Yuval int i;
332133fac0eSSudarsana Kalluru
3334dbcd640SMintz, Yuval /* Account for queue statistics */
3344dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
3354dbcd640SMintz, Yuval fp = &edev->fp_array[i];
33668db9ec2SSudarsana Reddy Kalluru
3374dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX)
3384dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf);
3394dbcd640SMintz, Yuval
340cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP)
341cb6aeb07SMintz, Yuval qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);
342cb6aeb07SMintz, Yuval
3435e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) {
3445e7baf0fSManish Chopra int cos;
3455e7baf0fSManish Chopra
3465e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos)
3475e7baf0fSManish Chopra qede_get_strings_stats_txq(edev,
3485e7baf0fSManish Chopra &fp->txq[cos], &buf);
3495e7baf0fSManish Chopra }
350cbbf049aSMintz, Yuval }
351cbbf049aSMintz, Yuval
3524dbcd640SMintz, Yuval /* Account for non-queue statistics */
3534dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) {
3549c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i))
355fefb0202SYuval Mintz continue;
3564dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string);
3574dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN;
358133fac0eSSudarsana Kalluru }
359133fac0eSSudarsana Kalluru }
360133fac0eSSudarsana Kalluru
qede_get_strings(struct net_device * dev,u32 stringset,u8 * buf)361133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
362133fac0eSSudarsana Kalluru {
363133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
364133fac0eSSudarsana Kalluru
365133fac0eSSudarsana Kalluru switch (stringset) {
366133fac0eSSudarsana Kalluru case ETH_SS_STATS:
367133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf);
368133fac0eSSudarsana Kalluru break;
369f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS:
370f3e72109SYuval Mintz memcpy(buf, qede_private_arr,
371f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN);
372f3e72109SYuval Mintz break;
3733044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST:
3743044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr,
3753044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX);
3763044a02eSSudarsana Reddy Kalluru break;
377133fac0eSSudarsana Kalluru default:
378133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
379133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset);
380133fac0eSSudarsana Kalluru }
381133fac0eSSudarsana Kalluru }
382133fac0eSSudarsana Kalluru
qede_get_ethtool_stats_txq(struct qede_tx_queue * txq,u64 ** buf)3834dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf)
3844dbcd640SMintz, Yuval {
3854dbcd640SMintz, Yuval int i;
3864dbcd640SMintz, Yuval
3874dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
3884dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset));
3894dbcd640SMintz, Yuval (*buf)++;
3904dbcd640SMintz, Yuval }
3914dbcd640SMintz, Yuval }
3924dbcd640SMintz, Yuval
qede_get_ethtool_stats_rxq(struct qede_rx_queue * rxq,u64 ** buf)3934dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf)
3944dbcd640SMintz, Yuval {
3954dbcd640SMintz, Yuval int i;
3964dbcd640SMintz, Yuval
3974dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
3984dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset));
3994dbcd640SMintz, Yuval (*buf)++;
4004dbcd640SMintz, Yuval }
4014dbcd640SMintz, Yuval }
4024dbcd640SMintz, Yuval
qede_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * buf)403133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev,
404133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf)
405133fac0eSSudarsana Kalluru {
406133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
4074dbcd640SMintz, Yuval struct qede_fastpath *fp;
4084dbcd640SMintz, Yuval int i;
409133fac0eSSudarsana Kalluru
410133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev);
411133fac0eSSudarsana Kalluru
412567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */
413567b3c12SMintz, Yuval __qede_lock(edev);
414567b3c12SMintz, Yuval
4154dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
4164dbcd640SMintz, Yuval fp = &edev->fp_array[i];
417133fac0eSSudarsana Kalluru
4184dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX)
4194dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf);
42068db9ec2SSudarsana Reddy Kalluru
421cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP)
422cb6aeb07SMintz, Yuval qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);
423cb6aeb07SMintz, Yuval
4245e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) {
4255e7baf0fSManish Chopra int cos;
4265e7baf0fSManish Chopra
4275e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos)
4285e7baf0fSManish Chopra qede_get_ethtool_stats_txq(&fp->txq[cos], &buf);
4295e7baf0fSManish Chopra }
43068db9ec2SSudarsana Reddy Kalluru }
43168db9ec2SSudarsana Reddy Kalluru
432*42510dffSManish Chopra spin_lock(&edev->stats_lock);
433*42510dffSManish Chopra
4344dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) {
4359c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i))
436fefb0202SYuval Mintz continue;
4374dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) +
4384dbcd640SMintz, Yuval qede_stats_arr[i].offset));
4394dbcd640SMintz, Yuval
4404dbcd640SMintz, Yuval buf++;
441fefb0202SYuval Mintz }
442133fac0eSSudarsana Kalluru
443*42510dffSManish Chopra spin_unlock(&edev->stats_lock);
444*42510dffSManish Chopra
445567b3c12SMintz, Yuval __qede_unlock(edev);
446133fac0eSSudarsana Kalluru }
447133fac0eSSudarsana Kalluru
qede_get_sset_count(struct net_device * dev,int stringset)448133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset)
449133fac0eSSudarsana Kalluru {
450133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
4519c79ddaaSMintz, Yuval int num_stats = QEDE_NUM_STATS, i;
452133fac0eSSudarsana Kalluru
453133fac0eSSudarsana Kalluru switch (stringset) {
454133fac0eSSudarsana Kalluru case ETH_SS_STATS:
455fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++)
4569c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i))
457fefb0202SYuval Mintz num_stats--;
4584dbcd640SMintz, Yuval
4594dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */
4605e7baf0fSManish Chopra num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS *
4615e7baf0fSManish Chopra edev->dev_info.num_tc;
4624dbcd640SMintz, Yuval
4634dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */
4644dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
4654dbcd640SMintz, Yuval
466cb6aeb07SMintz, Yuval /* Account for XDP statistics [if needed] */
467cb6aeb07SMintz, Yuval if (edev->xdp_prog)
468cb6aeb07SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS;
4694dbcd640SMintz, Yuval return num_stats;
4704dbcd640SMintz, Yuval
471f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS:
472f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN;
4733044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST:
4746ecb0a0cSYuval Mintz if (!IS_VF(edev))
4753044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX;
4766ecb0a0cSYuval Mintz else
4776ecb0a0cSYuval Mintz return 0;
478133fac0eSSudarsana Kalluru default:
479133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
480133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset);
481133fac0eSSudarsana Kalluru return -EINVAL;
482133fac0eSSudarsana Kalluru }
483133fac0eSSudarsana Kalluru }
484133fac0eSSudarsana Kalluru
qede_get_priv_flags(struct net_device * dev)485f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev)
486f3e72109SYuval Mintz {
487f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev);
488823163baSManish Chopra bool esl_active;
489f15cff04SSudarsana Reddy Kalluru u32 flags = 0;
490f3e72109SYuval Mintz
491f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1)
492f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_CMT);
493f15cff04SSudarsana Reddy Kalluru
494f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.smart_an)
495f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT);
496f15cff04SSudarsana Reddy Kalluru
4977d9acd87SIgor Russkikh if (edev->err_flags & BIT(QEDE_ERR_IS_RECOVERABLE))
4987d9acd87SIgor Russkikh flags |= BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR);
4997d9acd87SIgor Russkikh
500823163baSManish Chopra if (edev->dev_info.common.esl)
501823163baSManish Chopra flags |= BIT(QEDE_PRI_FLAG_ESL_SUPPORT);
502823163baSManish Chopra
503823163baSManish Chopra edev->ops->common->get_esl_status(edev->cdev, &esl_active);
504823163baSManish Chopra
505823163baSManish Chopra if (esl_active)
506823163baSManish Chopra flags |= BIT(QEDE_PRI_FLAG_ESL_ACTIVE);
507823163baSManish Chopra
508f15cff04SSudarsana Reddy Kalluru return flags;
509f3e72109SYuval Mintz }
510f3e72109SYuval Mintz
qede_set_priv_flags(struct net_device * dev,u32 flags)5117d9acd87SIgor Russkikh static int qede_set_priv_flags(struct net_device *dev, u32 flags)
5127d9acd87SIgor Russkikh {
5137d9acd87SIgor Russkikh struct qede_dev *edev = netdev_priv(dev);
5147d9acd87SIgor Russkikh u32 cflags = qede_get_priv_flags(dev);
5157d9acd87SIgor Russkikh u32 dflags = flags ^ cflags;
5167d9acd87SIgor Russkikh
5177d9acd87SIgor Russkikh /* can only change RECOVER_ON_ERROR flag */
5187d9acd87SIgor Russkikh if (dflags & ~BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR))
5197d9acd87SIgor Russkikh return -EINVAL;
5207d9acd87SIgor Russkikh
5217d9acd87SIgor Russkikh if (flags & BIT(QEDE_PRI_FLAG_RECOVER_ON_ERROR))
5227d9acd87SIgor Russkikh set_bit(QEDE_ERR_IS_RECOVERABLE, &edev->err_flags);
5237d9acd87SIgor Russkikh else
5247d9acd87SIgor Russkikh clear_bit(QEDE_ERR_IS_RECOVERABLE, &edev->err_flags);
5257d9acd87SIgor Russkikh
5267d9acd87SIgor Russkikh return 0;
5277d9acd87SIgor Russkikh }
5287d9acd87SIgor Russkikh
qede_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)529054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev,
530054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd)
531133fac0eSSudarsana Kalluru {
532bdb5d8ecSAlexander Lobakin typeof(cmd->link_modes) *link_modes = &cmd->link_modes;
533054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base;
534133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
535133fac0eSSudarsana Kalluru struct qed_link_output current_link;
536133fac0eSSudarsana Kalluru
537567b3c12SMintz, Yuval __qede_lock(edev);
538567b3c12SMintz, Yuval
539133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
540133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
541133fac0eSSudarsana Kalluru
542bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->supported, current_link.supported_caps);
543bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->advertising, current_link.advertised_caps);
544bdb5d8ecSAlexander Lobakin linkmode_copy(link_modes->lp_advertising, current_link.lp_caps);
545054c67d1SSudarsana Reddy Kalluru
546133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
547054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed;
548054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex;
549133fac0eSSudarsana Kalluru } else {
550054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN;
551054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN;
552133fac0eSSudarsana Kalluru }
553567b3c12SMintz, Yuval
554567b3c12SMintz, Yuval __qede_unlock(edev);
555567b3c12SMintz, Yuval
556054c67d1SSudarsana Reddy Kalluru base->port = current_link.port;
557054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
558133fac0eSSudarsana Kalluru AUTONEG_DISABLE;
559133fac0eSSudarsana Kalluru
560133fac0eSSudarsana Kalluru return 0;
561133fac0eSSudarsana Kalluru }
562133fac0eSSudarsana Kalluru
qede_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)563054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev,
564054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd)
565133fac0eSSudarsana Kalluru {
566054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base;
567133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
5681d4e4eccSAlexander Lobakin const struct qede_forced_speed_map *map;
569133fac0eSSudarsana Kalluru struct qed_link_output current_link;
570133fac0eSSudarsana Kalluru struct qed_link_params params;
5711d4e4eccSAlexander Lobakin u32 i;
572133fac0eSSudarsana Kalluru
573fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
574054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n");
575133fac0eSSudarsana Kalluru return -EOPNOTSUPP;
576133fac0eSSudarsana Kalluru }
577133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
578133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params));
579133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
580133fac0eSSudarsana Kalluru
581133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
582133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
583bdb5d8ecSAlexander Lobakin
584054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) {
585bdb5d8ecSAlexander Lobakin if (!phylink_test(current_link.supported_caps, Autoneg)) {
586161adb04Ssudarsana.kalluru@cavium.com DP_INFO(edev, "Auto negotiation is not supported\n");
587161adb04Ssudarsana.kalluru@cavium.com return -EOPNOTSUPP;
588161adb04Ssudarsana.kalluru@cavium.com }
589161adb04Ssudarsana.kalluru@cavium.com
590133fac0eSSudarsana Kalluru params.autoneg = true;
591133fac0eSSudarsana Kalluru params.forced_speed = 0;
592bdb5d8ecSAlexander Lobakin
593bdb5d8ecSAlexander Lobakin linkmode_copy(params.adv_speeds, cmd->link_modes.advertising);
594133fac0eSSudarsana Kalluru } else { /* forced speed */
595133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
596133fac0eSSudarsana Kalluru params.autoneg = false;
597054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed;
598bdb5d8ecSAlexander Lobakin
5991d4e4eccSAlexander Lobakin for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) {
6001d4e4eccSAlexander Lobakin map = qede_forced_speed_maps + i;
601bdb5d8ecSAlexander Lobakin
6021d4e4eccSAlexander Lobakin if (base->speed != map->speed ||
6031d4e4eccSAlexander Lobakin !linkmode_intersects(current_link.supported_caps,
6041d4e4eccSAlexander Lobakin map->caps))
6051d4e4eccSAlexander Lobakin continue;
6061d4e4eccSAlexander Lobakin
6071d4e4eccSAlexander Lobakin linkmode_and(params.adv_speeds,
6081d4e4eccSAlexander Lobakin current_link.supported_caps, map->caps);
6091d4e4eccSAlexander Lobakin goto set_link;
6101d4e4eccSAlexander Lobakin }
6111d4e4eccSAlexander Lobakin
612054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed);
613133fac0eSSudarsana Kalluru return -EINVAL;
614133fac0eSSudarsana Kalluru }
615bdb5d8ecSAlexander Lobakin
6161d4e4eccSAlexander Lobakin set_link:
617133fac0eSSudarsana Kalluru params.link_up = true;
618133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms);
619133fac0eSSudarsana Kalluru
620133fac0eSSudarsana Kalluru return 0;
621133fac0eSSudarsana Kalluru }
622133fac0eSSudarsana Kalluru
qede_get_drvinfo(struct net_device * ndev,struct ethtool_drvinfo * info)623133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev,
624133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info)
625133fac0eSSudarsana Kalluru {
626133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN];
627133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev);
628a88381deSSudarsana Reddy Kalluru char mbi[ETHTOOL_FWVERS_LEN];
629133fac0eSSudarsana Kalluru
630f029c781SWolfram Sang strscpy(info->driver, "qede", sizeof(info->driver));
631133fac0eSSudarsana Kalluru
632133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
633133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major,
634133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor,
635133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev,
636133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng);
637133fac0eSSudarsana Kalluru
638133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
639133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF,
640133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF,
641133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF,
642133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF);
643133fac0eSSudarsana Kalluru
64488ea96f8SShai Malin if ((strlen(storm) + strlen("[storm]")) <
645a88381deSSudarsana Reddy Kalluru sizeof(info->version))
646a88381deSSudarsana Reddy Kalluru snprintf(info->version, sizeof(info->version),
64788ea96f8SShai Malin "[storm %s]", storm);
648a88381deSSudarsana Reddy Kalluru else
649a88381deSSudarsana Reddy Kalluru snprintf(info->version, sizeof(info->version),
65088ea96f8SShai Malin "%s", storm);
651a88381deSSudarsana Reddy Kalluru
652a88381deSSudarsana Reddy Kalluru if (edev->dev_info.common.mbi_version) {
653a88381deSSudarsana Reddy Kalluru snprintf(mbi, ETHTOOL_FWVERS_LEN, "%d.%d.%d",
654a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version &
655a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_2_MASK) >> QED_MBI_VERSION_2_OFFSET,
656a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version &
657a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_1_MASK) >> QED_MBI_VERSION_1_OFFSET,
658a88381deSSudarsana Reddy Kalluru (edev->dev_info.common.mbi_version &
659a88381deSSudarsana Reddy Kalluru QED_MBI_VERSION_0_MASK) >> QED_MBI_VERSION_0_OFFSET);
660133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version),
661a88381deSSudarsana Reddy Kalluru "mbi %s [mfw %s]", mbi, mfw);
662133fac0eSSudarsana Kalluru } else {
663133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version),
664a88381deSSudarsana Reddy Kalluru "mfw %s", mfw);
665133fac0eSSudarsana Kalluru }
666133fac0eSSudarsana Kalluru
667f029c781SWolfram Sang strscpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
668133fac0eSSudarsana Kalluru }
669133fac0eSSudarsana Kalluru
qede_get_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)67014d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
67114d39648SMintz, Yuval {
67214d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev);
67314d39648SMintz, Yuval
67414d39648SMintz, Yuval if (edev->dev_info.common.wol_support) {
67514d39648SMintz, Yuval wol->supported = WAKE_MAGIC;
67614d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0;
67714d39648SMintz, Yuval }
67814d39648SMintz, Yuval }
67914d39648SMintz, Yuval
qede_set_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)68014d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
68114d39648SMintz, Yuval {
68214d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev);
68314d39648SMintz, Yuval bool wol_requested;
68414d39648SMintz, Yuval int rc;
68514d39648SMintz, Yuval
68614d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) {
68714d39648SMintz, Yuval DP_INFO(edev,
68814d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n");
68914d39648SMintz, Yuval return -EINVAL;
69014d39648SMintz, Yuval }
69114d39648SMintz, Yuval
69214d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC);
69314d39648SMintz, Yuval if (wol_requested == edev->wol_enabled)
69414d39648SMintz, Yuval return 0;
69514d39648SMintz, Yuval
69614d39648SMintz, Yuval /* Need to actually change configuration */
69714d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) {
69814d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n");
69914d39648SMintz, Yuval return -EINVAL;
70014d39648SMintz, Yuval }
70114d39648SMintz, Yuval
70214d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested);
70314d39648SMintz, Yuval if (!rc)
70414d39648SMintz, Yuval edev->wol_enabled = wol_requested;
70514d39648SMintz, Yuval
70614d39648SMintz, Yuval return rc;
70714d39648SMintz, Yuval }
70814d39648SMintz, Yuval
qede_get_msglevel(struct net_device * ndev)709133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev)
710133fac0eSSudarsana Kalluru {
711133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev);
712133fac0eSSudarsana Kalluru
7131a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module;
714133fac0eSSudarsana Kalluru }
715133fac0eSSudarsana Kalluru
qede_set_msglevel(struct net_device * ndev,u32 level)716133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level)
717133fac0eSSudarsana Kalluru {
718133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev);
719133fac0eSSudarsana Kalluru u32 dp_module = 0;
720133fac0eSSudarsana Kalluru u8 dp_level = 0;
721133fac0eSSudarsana Kalluru
722133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level);
723133fac0eSSudarsana Kalluru
724133fac0eSSudarsana Kalluru edev->dp_level = dp_level;
725133fac0eSSudarsana Kalluru edev->dp_module = dp_module;
726133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev,
727133fac0eSSudarsana Kalluru dp_module, dp_level);
728133fac0eSSudarsana Kalluru }
729133fac0eSSudarsana Kalluru
qede_nway_reset(struct net_device * dev)73032a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev)
73132a7a570SSudarsana Kalluru {
73232a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
73332a7a570SSudarsana Kalluru struct qed_link_output current_link;
73432a7a570SSudarsana Kalluru struct qed_link_params link_params;
73532a7a570SSudarsana Kalluru
736fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
7371a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n");
738fe7cd2bfSYuval Mintz return -EOPNOTSUPP;
739fe7cd2bfSYuval Mintz }
740fe7cd2bfSYuval Mintz
74132a7a570SSudarsana Kalluru if (!netif_running(dev))
74232a7a570SSudarsana Kalluru return 0;
74332a7a570SSudarsana Kalluru
74432a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
74532a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
74632a7a570SSudarsana Kalluru if (!current_link.link_up)
74732a7a570SSudarsana Kalluru return 0;
74832a7a570SSudarsana Kalluru
74932a7a570SSudarsana Kalluru /* Toggle the link */
75032a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params));
75132a7a570SSudarsana Kalluru link_params.link_up = false;
75232a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params);
75332a7a570SSudarsana Kalluru link_params.link_up = true;
75432a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params);
75532a7a570SSudarsana Kalluru
75632a7a570SSudarsana Kalluru return 0;
75732a7a570SSudarsana Kalluru }
75832a7a570SSudarsana Kalluru
qede_get_link(struct net_device * dev)759133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev)
760133fac0eSSudarsana Kalluru {
761133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
762133fac0eSSudarsana Kalluru struct qed_link_output current_link;
763133fac0eSSudarsana Kalluru
764133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
765133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
766133fac0eSSudarsana Kalluru
767133fac0eSSudarsana Kalluru return current_link.link_up;
768133fac0eSSudarsana Kalluru }
769133fac0eSSudarsana Kalluru
qede_flash_device(struct net_device * dev,struct ethtool_flash * flash)770ccfa110cSSudarsana Reddy Kalluru static int qede_flash_device(struct net_device *dev,
771ccfa110cSSudarsana Reddy Kalluru struct ethtool_flash *flash)
772ccfa110cSSudarsana Reddy Kalluru {
773ccfa110cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
774ccfa110cSSudarsana Reddy Kalluru
775ccfa110cSSudarsana Reddy Kalluru return edev->ops->common->nvm_flash(edev->cdev, flash->data);
776ccfa110cSSudarsana Reddy Kalluru }
777ccfa110cSSudarsana Reddy Kalluru
qede_get_coalesce(struct net_device * dev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)778d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev,
779f3ccfda1SYufeng Mo struct ethtool_coalesce *coal,
780f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
781f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
782d552fa84SSudarsana Reddy Kalluru {
783bf5a94bfSRahul Verma void *rx_handle = NULL, *tx_handle = NULL;
784d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
785bf5a94bfSRahul Verma u16 rx_coal, tx_coal, i, rc = 0;
786bf5a94bfSRahul Verma struct qede_fastpath *fp;
787bf5a94bfSRahul Verma
788bf5a94bfSRahul Verma rx_coal = QED_DEFAULT_RX_USECS;
789bf5a94bfSRahul Verma tx_coal = QED_DEFAULT_TX_USECS;
790d552fa84SSudarsana Reddy Kalluru
791d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce));
792d2890deaSSudarsana Reddy Kalluru
793bf5a94bfSRahul Verma __qede_lock(edev);
794bf5a94bfSRahul Verma if (edev->state == QEDE_STATE_OPEN) {
795bf5a94bfSRahul Verma for_each_queue(i) {
796bf5a94bfSRahul Verma fp = &edev->fp_array[i];
797d552fa84SSudarsana Reddy Kalluru
798bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_RX) {
799bf5a94bfSRahul Verma rx_handle = fp->rxq->handle;
800bf5a94bfSRahul Verma break;
801bf5a94bfSRahul Verma }
802bf5a94bfSRahul Verma }
803bf5a94bfSRahul Verma
804bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle);
805bf5a94bfSRahul Verma if (rc) {
806bf5a94bfSRahul Verma DP_INFO(edev, "Read Rx coalesce error\n");
807bf5a94bfSRahul Verma goto out;
808bf5a94bfSRahul Verma }
809bf5a94bfSRahul Verma
810bf5a94bfSRahul Verma for_each_queue(i) {
8115e7baf0fSManish Chopra struct qede_tx_queue *txq;
8125e7baf0fSManish Chopra
813bf5a94bfSRahul Verma fp = &edev->fp_array[i];
8145e7baf0fSManish Chopra
8155e7baf0fSManish Chopra /* All TX queues of given fastpath uses same
8165e7baf0fSManish Chopra * coalescing value, so no need to iterate over
8175e7baf0fSManish Chopra * all TCs, TC0 txq should suffice.
8185e7baf0fSManish Chopra */
819bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_TX) {
8205e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp);
8215e7baf0fSManish Chopra tx_handle = txq->handle;
822bf5a94bfSRahul Verma break;
823bf5a94bfSRahul Verma }
824bf5a94bfSRahul Verma }
825bf5a94bfSRahul Verma
826bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle);
827bf5a94bfSRahul Verma if (rc)
828bf5a94bfSRahul Verma DP_INFO(edev, "Read Tx coalesce error\n");
829bf5a94bfSRahul Verma }
830bf5a94bfSRahul Verma
831bf5a94bfSRahul Verma out:
832bf5a94bfSRahul Verma __qede_unlock(edev);
833bf5a94bfSRahul Verma
834bf5a94bfSRahul Verma coal->rx_coalesce_usecs = rx_coal;
835bf5a94bfSRahul Verma coal->tx_coalesce_usecs = tx_coal;
836*42510dffSManish Chopra coal->stats_block_coalesce_usecs = edev->stats_coal_usecs;
837bf5a94bfSRahul Verma
838bf5a94bfSRahul Verma return rc;
839d552fa84SSudarsana Reddy Kalluru }
840d552fa84SSudarsana Reddy Kalluru
qede_set_coalesce(struct net_device * dev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)841f3ccfda1SYufeng Mo int qede_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal,
842f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
843f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
844d552fa84SSudarsana Reddy Kalluru {
845d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
846477f2d14SRahul Verma struct qede_fastpath *fp;
847d552fa84SSudarsana Reddy Kalluru int i, rc = 0;
848477f2d14SRahul Verma u16 rxc, txc;
849d552fa84SSudarsana Reddy Kalluru
850*42510dffSManish Chopra if (edev->stats_coal_usecs != coal->stats_block_coalesce_usecs) {
851*42510dffSManish Chopra edev->stats_coal_usecs = coal->stats_block_coalesce_usecs;
852*42510dffSManish Chopra if (edev->stats_coal_usecs) {
853*42510dffSManish Chopra edev->stats_coal_ticks = usecs_to_jiffies(edev->stats_coal_usecs);
854*42510dffSManish Chopra schedule_delayed_work(&edev->periodic_task, 0);
855*42510dffSManish Chopra
856*42510dffSManish Chopra DP_INFO(edev, "Configured stats coal ticks=%lu jiffies\n",
857*42510dffSManish Chopra edev->stats_coal_ticks);
858*42510dffSManish Chopra } else {
859*42510dffSManish Chopra cancel_delayed_work_sync(&edev->periodic_task);
860*42510dffSManish Chopra }
861*42510dffSManish Chopra }
862*42510dffSManish Chopra
863d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) {
864d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n");
865d552fa84SSudarsana Reddy Kalluru return -EINVAL;
866d552fa84SSudarsana Reddy Kalluru }
867d552fa84SSudarsana Reddy Kalluru
868d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
869d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
870d552fa84SSudarsana Reddy Kalluru DP_INFO(edev,
871d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n",
872477f2d14SRahul Verma coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" :
873477f2d14SRahul Verma "tx", QED_COALESCE_MAX);
874d552fa84SSudarsana Reddy Kalluru return -EINVAL;
875d552fa84SSudarsana Reddy Kalluru }
876d552fa84SSudarsana Reddy Kalluru
877d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs;
878d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs;
8799a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) {
880477f2d14SRahul Verma fp = &edev->fp_array[i];
881477f2d14SRahul Verma
882477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
883477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev,
884477f2d14SRahul Verma rxc, 0,
885477f2d14SRahul Verma fp->rxq->handle);
886d552fa84SSudarsana Reddy Kalluru if (rc) {
887477f2d14SRahul Verma DP_INFO(edev,
888477f2d14SRahul Verma "Set RX coalesce error, rc = %d\n", rc);
889d552fa84SSudarsana Reddy Kalluru return rc;
890d552fa84SSudarsana Reddy Kalluru }
891b0ec5489SBhaskar Upadhaya edev->coal_entry[i].rxc = rxc;
892b0ec5489SBhaskar Upadhaya edev->coal_entry[i].isvalid = true;
893d552fa84SSudarsana Reddy Kalluru }
894d552fa84SSudarsana Reddy Kalluru
895477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
8965e7baf0fSManish Chopra struct qede_tx_queue *txq;
8975e7baf0fSManish Chopra
8985e7baf0fSManish Chopra /* All TX queues of given fastpath uses same
8995e7baf0fSManish Chopra * coalescing value, so no need to iterate over
9005e7baf0fSManish Chopra * all TCs, TC0 txq should suffice.
9015e7baf0fSManish Chopra */
9025e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp);
9035e7baf0fSManish Chopra
904477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev,
905477f2d14SRahul Verma 0, txc,
9065e7baf0fSManish Chopra txq->handle);
907477f2d14SRahul Verma if (rc) {
908477f2d14SRahul Verma DP_INFO(edev,
909477f2d14SRahul Verma "Set TX coalesce error, rc = %d\n", rc);
910477f2d14SRahul Verma return rc;
911477f2d14SRahul Verma }
912b0ec5489SBhaskar Upadhaya edev->coal_entry[i].txc = txc;
913b0ec5489SBhaskar Upadhaya edev->coal_entry[i].isvalid = true;
914477f2d14SRahul Verma }
915477f2d14SRahul Verma }
916477f2d14SRahul Verma
917d552fa84SSudarsana Reddy Kalluru return rc;
918d552fa84SSudarsana Reddy Kalluru }
919d552fa84SSudarsana Reddy Kalluru
qede_get_ringparam(struct net_device * dev,struct ethtool_ringparam * ering,struct kernel_ethtool_ringparam * kernel_ering,struct netlink_ext_ack * extack)92001ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev,
92174624944SHao Chen struct ethtool_ringparam *ering,
92274624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering,
92374624944SHao Chen struct netlink_ext_ack *extack)
92401ef7e05SSudarsana Kalluru {
92501ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
92601ef7e05SSudarsana Kalluru
92701ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX;
92801ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers;
92901ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX;
93001ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers;
93101ef7e05SSudarsana Kalluru }
93201ef7e05SSudarsana Kalluru
qede_set_ringparam(struct net_device * dev,struct ethtool_ringparam * ering,struct kernel_ethtool_ringparam * kernel_ering,struct netlink_ext_ack * extack)93301ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev,
93474624944SHao Chen struct ethtool_ringparam *ering,
93574624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering,
93674624944SHao Chen struct netlink_ext_ack *extack)
93701ef7e05SSudarsana Kalluru {
93801ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
93901ef7e05SSudarsana Kalluru
94001ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
94101ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
94201ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending);
94301ef7e05SSudarsana Kalluru
94401ef7e05SSudarsana Kalluru /* Validate legality of configuration */
94501ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX ||
94601ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN ||
94701ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX ||
94801ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) {
94901ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
95001ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n",
95101ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX,
95201ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX);
95301ef7e05SSudarsana Kalluru return -EINVAL;
95401ef7e05SSudarsana Kalluru }
95501ef7e05SSudarsana Kalluru
95601ef7e05SSudarsana Kalluru /* Change ring size and re-load */
95701ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending;
95801ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending;
95901ef7e05SSudarsana Kalluru
960567b3c12SMintz, Yuval qede_reload(edev, NULL, false);
96101ef7e05SSudarsana Kalluru
96201ef7e05SSudarsana Kalluru return 0;
96301ef7e05SSudarsana Kalluru }
96401ef7e05SSudarsana Kalluru
qede_get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)9650f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev,
9660f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause)
9670f7db144SSudarsana Kalluru {
9680f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
9690f7db144SSudarsana Kalluru struct qed_link_output current_link;
9700f7db144SSudarsana Kalluru
9710f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
9720f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
9730f7db144SSudarsana Kalluru
9740f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
9750f7db144SSudarsana Kalluru epause->autoneg = true;
9760f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE)
9770f7db144SSudarsana Kalluru epause->rx_pause = true;
9780f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE)
9790f7db144SSudarsana Kalluru epause->tx_pause = true;
9800f7db144SSudarsana Kalluru
9810f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
9820f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n",
9830f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause,
9840f7db144SSudarsana Kalluru epause->tx_pause);
9850f7db144SSudarsana Kalluru }
9860f7db144SSudarsana Kalluru
qede_set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)9870f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev,
9880f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause)
9890f7db144SSudarsana Kalluru {
9900f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
9910f7db144SSudarsana Kalluru struct qed_link_params params;
9920f7db144SSudarsana Kalluru struct qed_link_output current_link;
9930f7db144SSudarsana Kalluru
994fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
9950f7db144SSudarsana Kalluru DP_INFO(edev,
996fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n");
9970f7db144SSudarsana Kalluru return -EOPNOTSUPP;
9980f7db144SSudarsana Kalluru }
9990f7db144SSudarsana Kalluru
10000f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link));
10010f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
10020f7db144SSudarsana Kalluru
10030f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params));
10040f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
1005bdb5d8ecSAlexander Lobakin
10060f7db144SSudarsana Kalluru if (epause->autoneg) {
1007bdb5d8ecSAlexander Lobakin if (!phylink_test(current_link.supported_caps, Autoneg)) {
10080f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n");
10090f7db144SSudarsana Kalluru return -EINVAL;
10100f7db144SSudarsana Kalluru }
1011bdb5d8ecSAlexander Lobakin
10120f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
10130f7db144SSudarsana Kalluru }
1014bdb5d8ecSAlexander Lobakin
10150f7db144SSudarsana Kalluru if (epause->rx_pause)
10160f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
10170f7db144SSudarsana Kalluru if (epause->tx_pause)
10180f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE;
10190f7db144SSudarsana Kalluru
10200f7db144SSudarsana Kalluru params.link_up = true;
10210f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms);
10220f7db144SSudarsana Kalluru
10230f7db144SSudarsana Kalluru return 0;
10240f7db144SSudarsana Kalluru }
10250f7db144SSudarsana Kalluru
qede_get_regs(struct net_device * ndev,struct ethtool_regs * regs,void * buffer)1026e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev,
1027e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer)
1028e0971c83STomer Tayar {
1029e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev);
1030e0971c83STomer Tayar
1031e0971c83STomer Tayar regs->version = 0;
1032e0971c83STomer Tayar memset(buffer, 0, regs->len);
1033e0971c83STomer Tayar
1034e0971c83STomer Tayar if (edev->ops && edev->ops->common)
1035e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer);
1036e0971c83STomer Tayar }
1037e0971c83STomer Tayar
qede_get_regs_len(struct net_device * ndev)1038e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev)
1039e0971c83STomer Tayar {
1040e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev);
1041e0971c83STomer Tayar
1042e0971c83STomer Tayar if (edev->ops && edev->ops->common)
1043e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev);
1044e0971c83STomer Tayar else
1045e0971c83STomer Tayar return -EINVAL;
1046e0971c83STomer Tayar }
1047e0971c83STomer Tayar
qede_update_mtu(struct qede_dev * edev,struct qede_reload_args * args)1048567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev,
1049567b3c12SMintz, Yuval struct qede_reload_args *args)
1050133fac0eSSudarsana Kalluru {
1051567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu;
1052133fac0eSSudarsana Kalluru }
1053133fac0eSSudarsana Kalluru
1054133fac0eSSudarsana Kalluru /* Netdevice NDOs */
qede_change_mtu(struct net_device * ndev,int new_mtu)1055133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu)
1056133fac0eSSudarsana Kalluru {
1057133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev);
1058567b3c12SMintz, Yuval struct qede_reload_args args;
1059133fac0eSSudarsana Kalluru
1060133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
1061133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu);
1062133fac0eSSudarsana Kalluru
106318c602deSMichael Chan if (new_mtu > PAGE_SIZE)
106418c602deSMichael Chan ndev->features &= ~NETIF_F_GRO_HW;
106518c602deSMichael Chan
1066133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */
1067567b3c12SMintz, Yuval args.u.mtu = new_mtu;
1068567b3c12SMintz, Yuval args.func = &qede_update_mtu;
1069567b3c12SMintz, Yuval qede_reload(edev, &args, false);
107097fb3e33SMichal Kalderon #if IS_ENABLED(CONFIG_QED_RDMA)
107197fb3e33SMichal Kalderon qede_rdma_event_change_mtu(edev);
107297fb3e33SMichal Kalderon #endif
1073567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu);
10740fefbfbaSSudarsana Kalluru
1075133fac0eSSudarsana Kalluru return 0;
1076133fac0eSSudarsana Kalluru }
1077133fac0eSSudarsana Kalluru
qede_get_channels(struct net_device * dev,struct ethtool_channels * channels)10788edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev,
10798edf049dSSudarsana Kalluru struct ethtool_channels *channels)
10808edf049dSSudarsana Kalluru {
10818edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
10828edf049dSSudarsana Kalluru
10838edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev);
1084bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev);
1085bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev);
10869a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx -
10879a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx;
10889a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx;
10899a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx;
10908edf049dSSudarsana Kalluru }
10918edf049dSSudarsana Kalluru
qede_set_channels(struct net_device * dev,struct ethtool_channels * channels)10928edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev,
10938edf049dSSudarsana Kalluru struct ethtool_channels *channels)
10948edf049dSSudarsana Kalluru {
10958edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
10969a4d7e86SSudarsana Reddy Kalluru u32 count;
10978edf049dSSudarsana Kalluru
10988edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
10998edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
11008edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count,
11018edf049dSSudarsana Kalluru channels->other_count, channels->combined_count);
11028edf049dSSudarsana Kalluru
11039a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count +
11049a4d7e86SSudarsana Reddy Kalluru channels->combined_count;
11059a4d7e86SSudarsana Reddy Kalluru
11069a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */
11079a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) {
11088edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11098edf049dSSudarsana Kalluru "command parameters not supported\n");
11108edf049dSSudarsana Kalluru return -EINVAL;
11118edf049dSSudarsana Kalluru }
11128edf049dSSudarsana Kalluru
11139a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count &&
11149a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) {
11159a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11169a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n");
11179a4d7e86SSudarsana Reddy Kalluru return -EINVAL;
11189a4d7e86SSudarsana Reddy Kalluru }
11199a4d7e86SSudarsana Reddy Kalluru
11209a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) {
11219a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11229a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n",
11239a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev));
11249a4d7e86SSudarsana Reddy Kalluru return -EINVAL;
11259a4d7e86SSudarsana Reddy Kalluru }
11269a4d7e86SSudarsana Reddy Kalluru
11278edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */
11289a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) &&
11299a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) &&
11309a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) {
11318edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11328edf049dSSudarsana Kalluru "No change in active parameters\n");
11338edf049dSSudarsana Kalluru return 0;
11348edf049dSSudarsana Kalluru }
11358edf049dSSudarsana Kalluru
11368edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */
11379a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) ||
11389a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) ||
11399a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) {
11408edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11419a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n",
11428edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns);
11438edf049dSSudarsana Kalluru return -EINVAL;
11448edf049dSSudarsana Kalluru }
11458edf049dSSudarsana Kalluru
11468edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */
11479a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count;
11489a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count;
11499a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count;
1150ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */
1151ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) {
1152ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED;
1153f29ffdb6SMintz, Yuval memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table));
1154ed0dd915SSudarsana Reddy Kalluru }
1155ed0dd915SSudarsana Reddy Kalluru
1156567b3c12SMintz, Yuval qede_reload(edev, NULL, false);
11578edf049dSSudarsana Kalluru
11588edf049dSSudarsana Kalluru return 0;
11598edf049dSSudarsana Kalluru }
11608edf049dSSudarsana Kalluru
qede_get_ts_info(struct net_device * dev,struct ethtool_ts_info * info)11614c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev,
11624c55215cSSudarsana Reddy Kalluru struct ethtool_ts_info *info)
11634c55215cSSudarsana Reddy Kalluru {
11644c55215cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
11654c55215cSSudarsana Reddy Kalluru
11664c55215cSSudarsana Reddy Kalluru return qede_ptp_get_ts_info(edev, info);
11674c55215cSSudarsana Reddy Kalluru }
11684c55215cSSudarsana Reddy Kalluru
qede_set_phys_id(struct net_device * dev,enum ethtool_phys_id_state state)11693d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev,
11703d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state)
11713d971cbdSSudarsana Kalluru {
11723d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev);
11733d971cbdSSudarsana Kalluru u8 led_state = 0;
11743d971cbdSSudarsana Kalluru
11753d971cbdSSudarsana Kalluru switch (state) {
11763d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE:
11773d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */
11783d971cbdSSudarsana Kalluru
11793d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON:
11803d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON;
11813d971cbdSSudarsana Kalluru break;
11823d971cbdSSudarsana Kalluru
11833d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF:
11843d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF;
11853d971cbdSSudarsana Kalluru break;
11863d971cbdSSudarsana Kalluru
11873d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE:
11883d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE;
11893d971cbdSSudarsana Kalluru break;
11903d971cbdSSudarsana Kalluru }
11913d971cbdSSudarsana Kalluru
11923d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state);
11933d971cbdSSudarsana Kalluru
11943d971cbdSSudarsana Kalluru return 0;
11953d971cbdSSudarsana Kalluru }
11963d971cbdSSudarsana Kalluru
qede_get_rss_flags(struct qede_dev * edev,struct ethtool_rxnfc * info)1197961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1198961acdeaSSudarsana Reddy Kalluru {
1199961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST;
1200961acdeaSSudarsana Reddy Kalluru
1201961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) {
1202961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW:
1203961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW:
1204961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1205961acdeaSSudarsana Reddy Kalluru break;
1206961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW:
1207f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV4_UDP)
1208961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1209961acdeaSSudarsana Reddy Kalluru break;
1210961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW:
1211f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV6_UDP)
1212961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1213961acdeaSSudarsana Reddy Kalluru break;
1214961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW:
1215961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW:
1216961acdeaSSudarsana Reddy Kalluru break;
1217961acdeaSSudarsana Reddy Kalluru default:
1218961acdeaSSudarsana Reddy Kalluru info->data = 0;
1219961acdeaSSudarsana Reddy Kalluru break;
1220961acdeaSSudarsana Reddy Kalluru }
1221961acdeaSSudarsana Reddy Kalluru
1222961acdeaSSudarsana Reddy Kalluru return 0;
1223961acdeaSSudarsana Reddy Kalluru }
1224961acdeaSSudarsana Reddy Kalluru
qede_get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info,u32 * rule_locs)1225961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1226ec9b8dbdSChopra, Manish u32 *rule_locs)
1227961acdeaSSudarsana Reddy Kalluru {
1228961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1229ec9b8dbdSChopra, Manish int rc = 0;
1230961acdeaSSudarsana Reddy Kalluru
1231961acdeaSSudarsana Reddy Kalluru switch (info->cmd) {
1232961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS:
12339a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev);
1234ec9b8dbdSChopra, Manish break;
1235961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH:
1236ec9b8dbdSChopra, Manish rc = qede_get_rss_flags(edev, info);
1237ec9b8dbdSChopra, Manish break;
1238ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLCNT:
1239ec9b8dbdSChopra, Manish info->rule_cnt = qede_get_arfs_filter_count(edev);
1240ec9b8dbdSChopra, Manish info->data = QEDE_RFS_MAX_FLTR;
1241ec9b8dbdSChopra, Manish break;
1242ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRULE:
1243ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_entry(edev, info);
1244ec9b8dbdSChopra, Manish break;
1245ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLALL:
1246ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_all(edev, info, rule_locs);
1247ec9b8dbdSChopra, Manish break;
1248961acdeaSSudarsana Reddy Kalluru default:
1249961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n");
1250ec9b8dbdSChopra, Manish rc = -EOPNOTSUPP;
1251961acdeaSSudarsana Reddy Kalluru }
1252ec9b8dbdSChopra, Manish
1253ec9b8dbdSChopra, Manish return rc;
1254961acdeaSSudarsana Reddy Kalluru }
1255961acdeaSSudarsana Reddy Kalluru
qede_set_rss_flags(struct qede_dev * edev,struct ethtool_rxnfc * info)1256961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1257961acdeaSSudarsana Reddy Kalluru {
1258f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params;
1259961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0;
1260f29ffdb6SMintz, Yuval int rc = 0;
1261961acdeaSSudarsana Reddy Kalluru
1262961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1263961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n",
1264961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data);
1265961acdeaSSudarsana Reddy Kalluru
1266961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) {
1267961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW:
1268961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW:
1269961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */
1270961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
1271961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1272961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n");
1273961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1274961acdeaSSudarsana Reddy Kalluru }
1275961acdeaSSudarsana Reddy Kalluru return 0;
1276961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW:
1277961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */
1278961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1279961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1280961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP;
1281961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1282961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n");
1283961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1284961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP;
1285961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1286961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n");
1287961acdeaSSudarsana Reddy Kalluru } else {
1288961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1289961acdeaSSudarsana Reddy Kalluru }
1290961acdeaSSudarsana Reddy Kalluru break;
1291961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW:
1292961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */
1293961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1294961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1295961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP;
1296961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1297961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n");
1298961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1299961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP;
1300961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1301961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n");
1302961acdeaSSudarsana Reddy Kalluru } else {
1303961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1304961acdeaSSudarsana Reddy Kalluru }
1305961acdeaSSudarsana Reddy Kalluru break;
1306961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW:
1307961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW:
1308961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */
1309961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
1310961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n");
1311961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1312961acdeaSSudarsana Reddy Kalluru }
1313961acdeaSSudarsana Reddy Kalluru return 0;
1314961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW:
1315961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW:
1316961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW:
1317961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW:
1318961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW:
1319961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW:
1320961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW:
1321961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW:
1322961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW:
1323961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW:
1324961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */
1325961acdeaSSudarsana Reddy Kalluru if (info->data) {
1326961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n");
1327961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1328961acdeaSSudarsana Reddy Kalluru }
1329961acdeaSSudarsana Reddy Kalluru return 0;
1330961acdeaSSudarsana Reddy Kalluru default:
1331961acdeaSSudarsana Reddy Kalluru return -EINVAL;
1332961acdeaSSudarsana Reddy Kalluru }
1333961acdeaSSudarsana Reddy Kalluru
1334961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */
1335f29ffdb6SMintz, Yuval if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps))
1336961acdeaSSudarsana Reddy Kalluru return 0;
1337961acdeaSSudarsana Reddy Kalluru
1338961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */
1339f29ffdb6SMintz, Yuval edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps);
1340961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED;
1341961acdeaSSudarsana Reddy Kalluru
1342961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */
1343f29ffdb6SMintz, Yuval __qede_lock(edev);
1344f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) {
1345f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params));
1346f29ffdb6SMintz, Yuval if (!vport_update_params) {
1347f29ffdb6SMintz, Yuval __qede_unlock(edev);
1348f29ffdb6SMintz, Yuval return -ENOMEM;
1349961acdeaSSudarsana Reddy Kalluru }
1350f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params,
1351f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg);
1352f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1353f29ffdb6SMintz, Yuval vfree(vport_update_params);
1354f29ffdb6SMintz, Yuval }
1355f29ffdb6SMintz, Yuval __qede_unlock(edev);
1356961acdeaSSudarsana Reddy Kalluru
1357f29ffdb6SMintz, Yuval return rc;
1358961acdeaSSudarsana Reddy Kalluru }
1359961acdeaSSudarsana Reddy Kalluru
qede_set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info)1360961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
1361961acdeaSSudarsana Reddy Kalluru {
1362961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
13633f2a2b8bSChopra, Manish int rc;
1364961acdeaSSudarsana Reddy Kalluru
1365961acdeaSSudarsana Reddy Kalluru switch (info->cmd) {
1366961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH:
13673f2a2b8bSChopra, Manish rc = qede_set_rss_flags(edev, info);
13683f2a2b8bSChopra, Manish break;
13693f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLINS:
13703f2a2b8bSChopra, Manish rc = qede_add_cls_rule(edev, info);
13713f2a2b8bSChopra, Manish break;
13723f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLDEL:
13732ce9c93eSManish Chopra rc = qede_delete_flow_filter(edev, info->fs.location);
13743f2a2b8bSChopra, Manish break;
1375961acdeaSSudarsana Reddy Kalluru default:
1376961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n");
13773f2a2b8bSChopra, Manish rc = -EOPNOTSUPP;
1378961acdeaSSudarsana Reddy Kalluru }
13793f2a2b8bSChopra, Manish
13803f2a2b8bSChopra, Manish return rc;
1381961acdeaSSudarsana Reddy Kalluru }
1382961acdeaSSudarsana Reddy Kalluru
qede_get_rxfh_indir_size(struct net_device * dev)1383961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev)
1384961acdeaSSudarsana Reddy Kalluru {
1385961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE;
1386961acdeaSSudarsana Reddy Kalluru }
1387961acdeaSSudarsana Reddy Kalluru
qede_get_rxfh_key_size(struct net_device * dev)1388961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev)
1389961acdeaSSudarsana Reddy Kalluru {
1390961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1391961acdeaSSudarsana Reddy Kalluru
1392f29ffdb6SMintz, Yuval return sizeof(edev->rss_key);
1393961acdeaSSudarsana Reddy Kalluru }
1394961acdeaSSudarsana Reddy Kalluru
qede_get_rxfh(struct net_device * dev,u32 * indir,u8 * key,u8 * hfunc)1395961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
1396961acdeaSSudarsana Reddy Kalluru {
1397961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1398961acdeaSSudarsana Reddy Kalluru int i;
1399961acdeaSSudarsana Reddy Kalluru
1400961acdeaSSudarsana Reddy Kalluru if (hfunc)
1401961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP;
1402961acdeaSSudarsana Reddy Kalluru
1403961acdeaSSudarsana Reddy Kalluru if (!indir)
1404961acdeaSSudarsana Reddy Kalluru return 0;
1405961acdeaSSudarsana Reddy Kalluru
1406961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1407f29ffdb6SMintz, Yuval indir[i] = edev->rss_ind_table[i];
1408961acdeaSSudarsana Reddy Kalluru
1409961acdeaSSudarsana Reddy Kalluru if (key)
1410f29ffdb6SMintz, Yuval memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev));
1411961acdeaSSudarsana Reddy Kalluru
1412961acdeaSSudarsana Reddy Kalluru return 0;
1413961acdeaSSudarsana Reddy Kalluru }
1414961acdeaSSudarsana Reddy Kalluru
qede_set_rxfh(struct net_device * dev,const u32 * indir,const u8 * key,const u8 hfunc)1415961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
1416961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc)
1417961acdeaSSudarsana Reddy Kalluru {
1418f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params;
1419961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1420f29ffdb6SMintz, Yuval int i, rc = 0;
1421961acdeaSSudarsana Reddy Kalluru
1422ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) {
1423ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev,
1424ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n");
1425ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP;
1426ba300ce3SSudarsana Reddy Kalluru }
1427ba300ce3SSudarsana Reddy Kalluru
1428961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1429961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP;
1430961acdeaSSudarsana Reddy Kalluru
1431961acdeaSSudarsana Reddy Kalluru if (!indir && !key)
1432961acdeaSSudarsana Reddy Kalluru return 0;
1433961acdeaSSudarsana Reddy Kalluru
1434961acdeaSSudarsana Reddy Kalluru if (indir) {
1435961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1436f29ffdb6SMintz, Yuval edev->rss_ind_table[i] = indir[i];
1437961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED;
1438961acdeaSSudarsana Reddy Kalluru }
1439961acdeaSSudarsana Reddy Kalluru
1440961acdeaSSudarsana Reddy Kalluru if (key) {
1441f29ffdb6SMintz, Yuval memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev));
1442961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED;
1443961acdeaSSudarsana Reddy Kalluru }
1444961acdeaSSudarsana Reddy Kalluru
1445f29ffdb6SMintz, Yuval __qede_lock(edev);
1446f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) {
1447f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params));
1448f29ffdb6SMintz, Yuval if (!vport_update_params) {
1449f29ffdb6SMintz, Yuval __qede_unlock(edev);
1450f29ffdb6SMintz, Yuval return -ENOMEM;
1451961acdeaSSudarsana Reddy Kalluru }
1452f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params,
1453f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg);
1454f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1455f29ffdb6SMintz, Yuval vfree(vport_update_params);
1456f29ffdb6SMintz, Yuval }
1457f29ffdb6SMintz, Yuval __qede_unlock(edev);
1458961acdeaSSudarsana Reddy Kalluru
1459f29ffdb6SMintz, Yuval return rc;
1460961acdeaSSudarsana Reddy Kalluru }
1461961acdeaSSudarsana Reddy Kalluru
146216f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */
qede_netif_start(struct qede_dev * edev)146316f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev)
146416f46bf0SSudarsana Reddy Kalluru {
146516f46bf0SSudarsana Reddy Kalluru int i;
146616f46bf0SSudarsana Reddy Kalluru
146716f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev))
146816f46bf0SSudarsana Reddy Kalluru return;
146916f46bf0SSudarsana Reddy Kalluru
14709a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) {
147116f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */
147216f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1);
147316f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi);
147416f46bf0SSudarsana Reddy Kalluru }
147516f46bf0SSudarsana Reddy Kalluru }
147616f46bf0SSudarsana Reddy Kalluru
147716f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */
qede_netif_stop(struct qede_dev * edev)147816f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev)
147916f46bf0SSudarsana Reddy Kalluru {
148016f46bf0SSudarsana Reddy Kalluru int i;
148116f46bf0SSudarsana Reddy Kalluru
14829a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) {
148316f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi);
148416f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */
148516f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0);
148616f46bf0SSudarsana Reddy Kalluru }
148716f46bf0SSudarsana Reddy Kalluru }
148816f46bf0SSudarsana Reddy Kalluru
qede_selftest_transmit_traffic(struct qede_dev * edev,struct sk_buff * skb)148916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev,
149016f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb)
149116f46bf0SSudarsana Reddy Kalluru {
14929a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL;
149316f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd;
149416f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping;
149548848a06SManish Chopra int i, idx;
149648848a06SManish Chopra u16 val;
149716f46bf0SSudarsana Reddy Kalluru
14989a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) {
14995e7baf0fSManish Chopra struct qede_fastpath *fp = &edev->fp_array[i];
15005e7baf0fSManish Chopra
15015e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) {
15025e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp);
15039a4d7e86SSudarsana Reddy Kalluru break;
15049a4d7e86SSudarsana Reddy Kalluru }
15059a4d7e86SSudarsana Reddy Kalluru }
15069a4d7e86SSudarsana Reddy Kalluru
15079a4d7e86SSudarsana Reddy Kalluru if (!txq) {
15089a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n");
15099a4d7e86SSudarsana Reddy Kalluru return -1;
15109a4d7e86SSudarsana Reddy Kalluru }
15119a4d7e86SSudarsana Reddy Kalluru
151216f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */
15135a052d62SSudarsana Reddy Kalluru idx = txq->sw_tx_prod;
1514cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = skb;
151516f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl);
151616f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd));
151716f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
151816f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val;
1519351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK;
152048848a06SManish Chopra val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT;
152148848a06SManish Chopra first_bd->data.bitfields |= cpu_to_le16(val);
152216f46bf0SSudarsana Reddy Kalluru
152316f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */
152416f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data,
152516f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE);
152616f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
152716f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n");
152816f46bf0SSudarsana Reddy Kalluru return -ENOMEM;
152916f46bf0SSudarsana Reddy Kalluru }
153016f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
153116f46bf0SSudarsana Reddy Kalluru
153216f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */
153316f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1;
15345a052d62SSudarsana Reddy Kalluru txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers;
153516f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */
153648848a06SManish Chopra val = qed_chain_get_prod_idx(&txq->tx_pbl);
153748848a06SManish Chopra txq->tx_db.data.bd_prod = cpu_to_le16(val);
153816f46bf0SSudarsana Reddy Kalluru
153916f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the
154016f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs.
154116f46bf0SSudarsana Reddy Kalluru */
154216f46bf0SSudarsana Reddy Kalluru wmb();
154316f46bf0SSudarsana Reddy Kalluru barrier();
154416f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr);
154516f46bf0SSudarsana Reddy Kalluru
154616f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
154716f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq))
154816f46bf0SSudarsana Reddy Kalluru break;
154916f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200);
155016f46bf0SSudarsana Reddy Kalluru }
155116f46bf0SSudarsana Reddy Kalluru
155216f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) {
155316f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n");
155416f46bf0SSudarsana Reddy Kalluru return -1;
155516f46bf0SSudarsana Reddy Kalluru }
155616f46bf0SSudarsana Reddy Kalluru
155716f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
1558fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
155916f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
15605a052d62SSudarsana Reddy Kalluru txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers;
1561cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = NULL;
156216f46bf0SSudarsana Reddy Kalluru
156316f46bf0SSudarsana Reddy Kalluru return 0;
156416f46bf0SSudarsana Reddy Kalluru }
156516f46bf0SSudarsana Reddy Kalluru
qede_selftest_receive_traffic(struct qede_dev * edev)156616f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev)
156716f46bf0SSudarsana Reddy Kalluru {
156810ee4b87SZheng Zengkai u16 sw_rx_index, len;
156916f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe;
15709a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL;
157116f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data;
157216f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe;
1573afe981d6SSudarsana Reddy Kalluru int i, iter, rc = 0;
157416f46bf0SSudarsana Reddy Kalluru u8 *data_ptr;
157516f46bf0SSudarsana Reddy Kalluru
15769a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) {
15779a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
15789a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq;
15799a4d7e86SSudarsana Reddy Kalluru break;
15809a4d7e86SSudarsana Reddy Kalluru }
15819a4d7e86SSudarsana Reddy Kalluru }
15829a4d7e86SSudarsana Reddy Kalluru
15839a4d7e86SSudarsana Reddy Kalluru if (!rxq) {
15849a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n");
15859a4d7e86SSudarsana Reddy Kalluru return -1;
15869a4d7e86SSudarsana Reddy Kalluru }
15879a4d7e86SSudarsana Reddy Kalluru
158816f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is
158916f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default
159016f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP.
159116f46bf0SSudarsana Reddy Kalluru */
1592afe981d6SSudarsana Reddy Kalluru for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) {
159316f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) {
1594837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200);
1595837d4eb6SSudarsana Reddy Kalluru continue;
159616f46bf0SSudarsana Reddy Kalluru }
159716f46bf0SSudarsana Reddy Kalluru
159816f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */
159916f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
160016f46bf0SSudarsana Reddy Kalluru
160116f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */
160216f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
160316f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
160416f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular;
160516f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd);
160616f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) +
1607837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset +
16088a863397SManish Chopra sw_rx_data->page_offset +
16098a863397SManish Chopra rxq->rx_headroom);
1610837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) &&
1611837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN,
1612837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) {
161316f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++)
161416f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) {
1615837d4eb6SSudarsana Reddy Kalluru rc = -1;
1616837d4eb6SSudarsana Reddy Kalluru break;
161716f46bf0SSudarsana Reddy Kalluru }
161816f46bf0SSudarsana Reddy Kalluru
16199eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1);
1620837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1621837d4eb6SSudarsana Reddy Kalluru break;
1622837d4eb6SSudarsana Reddy Kalluru }
162316f46bf0SSudarsana Reddy Kalluru
1624837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n");
16259eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1);
1626837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1627837d4eb6SSudarsana Reddy Kalluru }
1628837d4eb6SSudarsana Reddy Kalluru
1629afe981d6SSudarsana Reddy Kalluru if (iter == QEDE_SELFTEST_POLL_COUNT) {
1630837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n");
1631837d4eb6SSudarsana Reddy Kalluru return -1;
1632837d4eb6SSudarsana Reddy Kalluru }
1633837d4eb6SSudarsana Reddy Kalluru
1634837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq);
1635837d4eb6SSudarsana Reddy Kalluru
1636837d4eb6SSudarsana Reddy Kalluru return rc;
163716f46bf0SSudarsana Reddy Kalluru }
163816f46bf0SSudarsana Reddy Kalluru
qede_selftest_run_loopback(struct qede_dev * edev,u32 loopback_mode)163916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
164016f46bf0SSudarsana Reddy Kalluru {
164116f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params;
164216f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL;
164316f46bf0SSudarsana Reddy Kalluru int rc = 0, i;
164416f46bf0SSudarsana Reddy Kalluru u32 pkt_size;
164516f46bf0SSudarsana Reddy Kalluru u8 *packet;
164616f46bf0SSudarsana Reddy Kalluru
164716f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) {
164816f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n");
164916f46bf0SSudarsana Reddy Kalluru return -EINVAL;
165016f46bf0SSudarsana Reddy Kalluru }
165116f46bf0SSudarsana Reddy Kalluru
165216f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev);
165316f46bf0SSudarsana Reddy Kalluru
165416f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */
165516f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params));
165616f46bf0SSudarsana Reddy Kalluru link_params.link_up = true;
165716f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
165816f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode;
165916f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params);
166016f46bf0SSudarsana Reddy Kalluru
166116f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */
166216f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500);
166316f46bf0SSudarsana Reddy Kalluru
1664b89869daSSudarsana Reddy Kalluru /* Setting max packet size to 1.5K to avoid data being split over
1665b89869daSSudarsana Reddy Kalluru * multiple BDs in cases where MTU > PAGE_SIZE.
1666b89869daSSudarsana Reddy Kalluru */
1667b89869daSSudarsana Reddy Kalluru pkt_size = (((edev->ndev->mtu < ETH_DATA_LEN) ?
1668b89869daSSudarsana Reddy Kalluru edev->ndev->mtu : ETH_DATA_LEN) + ETH_HLEN);
166916f46bf0SSudarsana Reddy Kalluru
167016f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size);
167116f46bf0SSudarsana Reddy Kalluru if (!skb) {
167216f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n");
167316f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM;
167416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit;
167516f46bf0SSudarsana Reddy Kalluru }
167616f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size);
167716f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr);
167816f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr);
167916f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN)));
168016f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++)
168116f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff);
168216f46bf0SSudarsana Reddy Kalluru
168316f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb);
168416f46bf0SSudarsana Reddy Kalluru if (rc)
168516f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit;
168616f46bf0SSudarsana Reddy Kalluru
168716f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev);
168816f46bf0SSudarsana Reddy Kalluru if (rc)
168916f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit;
169016f46bf0SSudarsana Reddy Kalluru
169116f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n");
169216f46bf0SSudarsana Reddy Kalluru
169316f46bf0SSudarsana Reddy Kalluru test_loopback_exit:
169416f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb);
169516f46bf0SSudarsana Reddy Kalluru
169616f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */
169716f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params));
169816f46bf0SSudarsana Reddy Kalluru link_params.link_up = true;
169916f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
170016f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE;
170116f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params);
170216f46bf0SSudarsana Reddy Kalluru
170316f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */
170416f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500);
170516f46bf0SSudarsana Reddy Kalluru
170616f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev);
170716f46bf0SSudarsana Reddy Kalluru
170816f46bf0SSudarsana Reddy Kalluru return rc;
170916f46bf0SSudarsana Reddy Kalluru }
171016f46bf0SSudarsana Reddy Kalluru
qede_self_test(struct net_device * dev,struct ethtool_test * etest,u64 * buf)17113044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev,
17123044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf)
17133044a02eSSudarsana Reddy Kalluru {
17143044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
17153044a02eSSudarsana Reddy Kalluru
17163044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
17173044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n",
17183044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE),
17193044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2);
17203044a02eSSudarsana Reddy Kalluru
17213044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX);
17223044a02eSSudarsana Reddy Kalluru
172316f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) {
172416f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev,
172516f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) {
172616f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1;
172716f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED;
172816f46bf0SSudarsana Reddy Kalluru }
172916f46bf0SSudarsana Reddy Kalluru }
173016f46bf0SSudarsana Reddy Kalluru
17313044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) {
17323044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1;
17333044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED;
17343044a02eSSudarsana Reddy Kalluru }
17353044a02eSSudarsana Reddy Kalluru
17363044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) {
17373044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1;
17383044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED;
17393044a02eSSudarsana Reddy Kalluru }
17403044a02eSSudarsana Reddy Kalluru
17413044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) {
17423044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1;
17433044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED;
17443044a02eSSudarsana Reddy Kalluru }
17453044a02eSSudarsana Reddy Kalluru
17463044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) {
17473044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
17483044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED;
17493044a02eSSudarsana Reddy Kalluru }
17507a4b21b7SMintz, Yuval
17517a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) {
17527a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1;
17537a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED;
17547a4b21b7SMintz, Yuval }
17553044a02eSSudarsana Reddy Kalluru }
17563044a02eSSudarsana Reddy Kalluru
qede_set_tunable(struct net_device * dev,const struct ethtool_tunable * tuna,const void * data)17573d789994SManish Chopra static int qede_set_tunable(struct net_device *dev,
17583d789994SManish Chopra const struct ethtool_tunable *tuna,
17593d789994SManish Chopra const void *data)
17603d789994SManish Chopra {
17613d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev);
17623d789994SManish Chopra u32 val;
17633d789994SManish Chopra
17643d789994SManish Chopra switch (tuna->id) {
17653d789994SManish Chopra case ETHTOOL_RX_COPYBREAK:
17663d789994SManish Chopra val = *(u32 *)data;
17673d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) {
17683d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG,
17693d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]",
17703d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE);
17713d789994SManish Chopra return -EINVAL;
17723d789994SManish Chopra }
17733d789994SManish Chopra
17743d789994SManish Chopra edev->rx_copybreak = *(u32 *)data;
17753d789994SManish Chopra break;
17763d789994SManish Chopra default:
17773d789994SManish Chopra return -EOPNOTSUPP;
17783d789994SManish Chopra }
17793d789994SManish Chopra
17803d789994SManish Chopra return 0;
17813d789994SManish Chopra }
17823d789994SManish Chopra
qede_get_tunable(struct net_device * dev,const struct ethtool_tunable * tuna,void * data)17833d789994SManish Chopra static int qede_get_tunable(struct net_device *dev,
17843d789994SManish Chopra const struct ethtool_tunable *tuna, void *data)
17853d789994SManish Chopra {
17863d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev);
17873d789994SManish Chopra
17883d789994SManish Chopra switch (tuna->id) {
17893d789994SManish Chopra case ETHTOOL_RX_COPYBREAK:
17903d789994SManish Chopra *(u32 *)data = edev->rx_copybreak;
17913d789994SManish Chopra break;
17923d789994SManish Chopra default:
17933d789994SManish Chopra return -EOPNOTSUPP;
17943d789994SManish Chopra }
17953d789994SManish Chopra
17963d789994SManish Chopra return 0;
17973d789994SManish Chopra }
17983d789994SManish Chopra
qede_get_eee(struct net_device * dev,struct ethtool_eee * edata)1799c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata)
1800c3dc48f7SSudarsana Reddy Kalluru {
1801c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1802c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link;
1803c3dc48f7SSudarsana Reddy Kalluru
1804c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link));
1805c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
1806c3dc48f7SSudarsana Reddy Kalluru
1807c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) {
1808c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n");
1809c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP;
1810c3dc48f7SSudarsana Reddy Kalluru }
1811c3dc48f7SSudarsana Reddy Kalluru
1812c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_1G_ADV)
1813c3dc48f7SSudarsana Reddy Kalluru edata->advertised = ADVERTISED_1000baseT_Full;
1814c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_10G_ADV)
1815c3dc48f7SSudarsana Reddy Kalluru edata->advertised |= ADVERTISED_10000baseT_Full;
1816c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_1G_ADV)
1817c3dc48f7SSudarsana Reddy Kalluru edata->supported = ADVERTISED_1000baseT_Full;
1818c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_10G_ADV)
1819c3dc48f7SSudarsana Reddy Kalluru edata->supported |= ADVERTISED_10000baseT_Full;
1820c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV)
1821c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised = ADVERTISED_1000baseT_Full;
1822c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV)
1823c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised |= ADVERTISED_10000baseT_Full;
1824c3dc48f7SSudarsana Reddy Kalluru
1825c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_timer = current_link.eee.tx_lpi_timer;
1826c3dc48f7SSudarsana Reddy Kalluru edata->eee_enabled = current_link.eee.enable;
1827c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable;
1828c3dc48f7SSudarsana Reddy Kalluru edata->eee_active = current_link.eee_active;
1829c3dc48f7SSudarsana Reddy Kalluru
1830c3dc48f7SSudarsana Reddy Kalluru return 0;
1831c3dc48f7SSudarsana Reddy Kalluru }
1832c3dc48f7SSudarsana Reddy Kalluru
qede_set_eee(struct net_device * dev,struct ethtool_eee * edata)1833c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
1834c3dc48f7SSudarsana Reddy Kalluru {
1835c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
1836c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link;
1837c3dc48f7SSudarsana Reddy Kalluru struct qed_link_params params;
1838c3dc48f7SSudarsana Reddy Kalluru
1839c3dc48f7SSudarsana Reddy Kalluru if (!edev->ops->common->can_link_change(edev->cdev)) {
1840c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n");
1841c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP;
1842c3dc48f7SSudarsana Reddy Kalluru }
1843c3dc48f7SSudarsana Reddy Kalluru
1844c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link));
1845c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link);
1846c3dc48f7SSudarsana Reddy Kalluru
1847c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) {
1848c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n");
1849c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP;
1850c3dc48f7SSudarsana Reddy Kalluru }
1851c3dc48f7SSudarsana Reddy Kalluru
1852c3dc48f7SSudarsana Reddy Kalluru memset(¶ms, 0, sizeof(params));
1853c3dc48f7SSudarsana Reddy Kalluru params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG;
1854c3dc48f7SSudarsana Reddy Kalluru
1855c3dc48f7SSudarsana Reddy Kalluru if (!(edata->advertised & (ADVERTISED_1000baseT_Full |
1856c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) ||
1857c3dc48f7SSudarsana Reddy Kalluru ((edata->advertised & (ADVERTISED_1000baseT_Full |
1858c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) !=
1859c3dc48f7SSudarsana Reddy Kalluru edata->advertised)) {
1860c3dc48f7SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
1861c3dc48f7SSudarsana Reddy Kalluru "Invalid advertised capabilities %d\n",
1862c3dc48f7SSudarsana Reddy Kalluru edata->advertised);
1863c3dc48f7SSudarsana Reddy Kalluru return -EINVAL;
1864c3dc48f7SSudarsana Reddy Kalluru }
1865c3dc48f7SSudarsana Reddy Kalluru
1866c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_1000baseT_Full)
1867c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps = QED_EEE_1G_ADV;
1868c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_10000baseT_Full)
1869c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps |= QED_EEE_10G_ADV;
1870c3dc48f7SSudarsana Reddy Kalluru params.eee.enable = edata->eee_enabled;
1871c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_enable = edata->tx_lpi_enabled;
1872c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_timer = edata->tx_lpi_timer;
1873c3dc48f7SSudarsana Reddy Kalluru
1874c3dc48f7SSudarsana Reddy Kalluru params.link_up = true;
1875c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, ¶ms);
1876c3dc48f7SSudarsana Reddy Kalluru
1877c3dc48f7SSudarsana Reddy Kalluru return 0;
1878c3dc48f7SSudarsana Reddy Kalluru }
1879c3dc48f7SSudarsana Reddy Kalluru
qede_link_to_ethtool_fec(u32 link_fec)18809bdca14aSAlexander Lobakin static u32 qede_link_to_ethtool_fec(u32 link_fec)
18819bdca14aSAlexander Lobakin {
18829bdca14aSAlexander Lobakin u32 eth_fec = 0;
18839bdca14aSAlexander Lobakin
18849bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_NONE)
18859bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_OFF;
18869bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_FIRECODE)
18879bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_BASER;
18889bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_RS)
18899bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_RS;
18909bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_AUTO)
18919bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_AUTO;
18929bdca14aSAlexander Lobakin if (link_fec & QED_FEC_MODE_UNSUPPORTED)
18939bdca14aSAlexander Lobakin eth_fec |= ETHTOOL_FEC_NONE;
18949bdca14aSAlexander Lobakin
18959bdca14aSAlexander Lobakin return eth_fec;
18969bdca14aSAlexander Lobakin }
18979bdca14aSAlexander Lobakin
qede_ethtool_to_link_fec(u32 eth_fec)18989bdca14aSAlexander Lobakin static u32 qede_ethtool_to_link_fec(u32 eth_fec)
18999bdca14aSAlexander Lobakin {
19009bdca14aSAlexander Lobakin u32 link_fec = 0;
19019bdca14aSAlexander Lobakin
19029bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_OFF)
19039bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_NONE;
19049bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_BASER)
19059bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_FIRECODE;
19069bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_RS)
19079bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_RS;
19089bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_AUTO)
19099bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_AUTO;
19109bdca14aSAlexander Lobakin if (eth_fec & ETHTOOL_FEC_NONE)
19119bdca14aSAlexander Lobakin link_fec |= QED_FEC_MODE_UNSUPPORTED;
19129bdca14aSAlexander Lobakin
19139bdca14aSAlexander Lobakin return link_fec;
19149bdca14aSAlexander Lobakin }
19159bdca14aSAlexander Lobakin
qede_get_fecparam(struct net_device * dev,struct ethtool_fecparam * fecparam)19169bdca14aSAlexander Lobakin static int qede_get_fecparam(struct net_device *dev,
19179bdca14aSAlexander Lobakin struct ethtool_fecparam *fecparam)
19189bdca14aSAlexander Lobakin {
19199bdca14aSAlexander Lobakin struct qede_dev *edev = netdev_priv(dev);
19209bdca14aSAlexander Lobakin struct qed_link_output curr_link;
19219bdca14aSAlexander Lobakin
19229bdca14aSAlexander Lobakin memset(&curr_link, 0, sizeof(curr_link));
19239bdca14aSAlexander Lobakin edev->ops->common->get_link(edev->cdev, &curr_link);
19249bdca14aSAlexander Lobakin
19259bdca14aSAlexander Lobakin fecparam->active_fec = qede_link_to_ethtool_fec(curr_link.active_fec);
19269bdca14aSAlexander Lobakin fecparam->fec = qede_link_to_ethtool_fec(curr_link.sup_fec);
19279bdca14aSAlexander Lobakin
19289bdca14aSAlexander Lobakin return 0;
19299bdca14aSAlexander Lobakin }
19309bdca14aSAlexander Lobakin
qede_set_fecparam(struct net_device * dev,struct ethtool_fecparam * fecparam)19319bdca14aSAlexander Lobakin static int qede_set_fecparam(struct net_device *dev,
19329bdca14aSAlexander Lobakin struct ethtool_fecparam *fecparam)
19339bdca14aSAlexander Lobakin {
19349bdca14aSAlexander Lobakin struct qede_dev *edev = netdev_priv(dev);
19359bdca14aSAlexander Lobakin struct qed_link_params params;
19369bdca14aSAlexander Lobakin
19379bdca14aSAlexander Lobakin if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
19389bdca14aSAlexander Lobakin DP_INFO(edev, "Link settings are not allowed to be changed\n");
19399bdca14aSAlexander Lobakin return -EOPNOTSUPP;
19409bdca14aSAlexander Lobakin }
19419bdca14aSAlexander Lobakin
19429bdca14aSAlexander Lobakin memset(¶ms, 0, sizeof(params));
19439bdca14aSAlexander Lobakin params.override_flags |= QED_LINK_OVERRIDE_FEC_CONFIG;
19449bdca14aSAlexander Lobakin params.fec = qede_ethtool_to_link_fec(fecparam->fec);
19459bdca14aSAlexander Lobakin params.link_up = true;
19469bdca14aSAlexander Lobakin
19479bdca14aSAlexander Lobakin edev->ops->common->set_link(edev->cdev, ¶ms);
19489bdca14aSAlexander Lobakin
19499bdca14aSAlexander Lobakin return 0;
19509bdca14aSAlexander Lobakin }
19519bdca14aSAlexander Lobakin
qede_get_module_info(struct net_device * dev,struct ethtool_modinfo * modinfo)195297df0d65SSudarsana Reddy Kalluru static int qede_get_module_info(struct net_device *dev,
195397df0d65SSudarsana Reddy Kalluru struct ethtool_modinfo *modinfo)
195497df0d65SSudarsana Reddy Kalluru {
195597df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
195697df0d65SSudarsana Reddy Kalluru u8 buf[4];
195797df0d65SSudarsana Reddy Kalluru int rc;
195897df0d65SSudarsana Reddy Kalluru
195997df0d65SSudarsana Reddy Kalluru /* Read first 4 bytes to find the sfp type */
196097df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
196197df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 0, 4);
196297df0d65SSudarsana Reddy Kalluru if (rc) {
196397df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading EEPROM data %d\n", rc);
196497df0d65SSudarsana Reddy Kalluru return rc;
196597df0d65SSudarsana Reddy Kalluru }
196697df0d65SSudarsana Reddy Kalluru
196797df0d65SSudarsana Reddy Kalluru switch (buf[0]) {
196897df0d65SSudarsana Reddy Kalluru case 0x3: /* SFP, SFP+, SFP-28 */
196997df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8472;
197097df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
197197df0d65SSudarsana Reddy Kalluru break;
197297df0d65SSudarsana Reddy Kalluru case 0xc: /* QSFP */
197397df0d65SSudarsana Reddy Kalluru case 0xd: /* QSFP+ */
197497df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8436;
197597df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
197697df0d65SSudarsana Reddy Kalluru break;
197797df0d65SSudarsana Reddy Kalluru case 0x11: /* QSFP-28 */
197897df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8636;
197997df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
198097df0d65SSudarsana Reddy Kalluru break;
198197df0d65SSudarsana Reddy Kalluru default:
198297df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]);
198397df0d65SSudarsana Reddy Kalluru return -EINVAL;
198497df0d65SSudarsana Reddy Kalluru }
198597df0d65SSudarsana Reddy Kalluru
198697df0d65SSudarsana Reddy Kalluru return 0;
198797df0d65SSudarsana Reddy Kalluru }
198897df0d65SSudarsana Reddy Kalluru
qede_get_module_eeprom(struct net_device * dev,struct ethtool_eeprom * ee,u8 * data)198997df0d65SSudarsana Reddy Kalluru static int qede_get_module_eeprom(struct net_device *dev,
199097df0d65SSudarsana Reddy Kalluru struct ethtool_eeprom *ee, u8 *data)
199197df0d65SSudarsana Reddy Kalluru {
199297df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
199397df0d65SSudarsana Reddy Kalluru u32 start_addr = ee->offset, size = 0;
199497df0d65SSudarsana Reddy Kalluru u8 *buf = data;
199597df0d65SSudarsana Reddy Kalluru int rc = 0;
199697df0d65SSudarsana Reddy Kalluru
199797df0d65SSudarsana Reddy Kalluru /* Read A0 section */
199897df0d65SSudarsana Reddy Kalluru if (ee->offset < ETH_MODULE_SFF_8079_LEN) {
199997df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A0 section boundary */
200097df0d65SSudarsana Reddy Kalluru if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN)
200197df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8079_LEN - ee->offset;
200297df0d65SSudarsana Reddy Kalluru else
200397df0d65SSudarsana Reddy Kalluru size = ee->len;
200497df0d65SSudarsana Reddy Kalluru
200597df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
200697df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0,
200797df0d65SSudarsana Reddy Kalluru start_addr, size);
200897df0d65SSudarsana Reddy Kalluru if (rc) {
200997df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading A0 section %d\n", rc);
201097df0d65SSudarsana Reddy Kalluru return rc;
201197df0d65SSudarsana Reddy Kalluru }
201297df0d65SSudarsana Reddy Kalluru
201397df0d65SSudarsana Reddy Kalluru buf += size;
201497df0d65SSudarsana Reddy Kalluru start_addr += size;
201597df0d65SSudarsana Reddy Kalluru }
201697df0d65SSudarsana Reddy Kalluru
201797df0d65SSudarsana Reddy Kalluru /* Read A2 section */
201897df0d65SSudarsana Reddy Kalluru if (start_addr >= ETH_MODULE_SFF_8079_LEN &&
201997df0d65SSudarsana Reddy Kalluru start_addr < ETH_MODULE_SFF_8472_LEN) {
202097df0d65SSudarsana Reddy Kalluru size = ee->len - size;
202197df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A2 section boundary */
202297df0d65SSudarsana Reddy Kalluru if (start_addr + size > ETH_MODULE_SFF_8472_LEN)
202397df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8472_LEN - start_addr;
202497df0d65SSudarsana Reddy Kalluru start_addr -= ETH_MODULE_SFF_8079_LEN;
202597df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
202697df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A2,
202797df0d65SSudarsana Reddy Kalluru start_addr, size);
202897df0d65SSudarsana Reddy Kalluru if (rc) {
202997df0d65SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
203097df0d65SSudarsana Reddy Kalluru "Failed reading A2 section %d\n", rc);
203197df0d65SSudarsana Reddy Kalluru return 0;
203297df0d65SSudarsana Reddy Kalluru }
203397df0d65SSudarsana Reddy Kalluru }
203497df0d65SSudarsana Reddy Kalluru
203597df0d65SSudarsana Reddy Kalluru return rc;
203697df0d65SSudarsana Reddy Kalluru }
203797df0d65SSudarsana Reddy Kalluru
qede_set_dump(struct net_device * dev,struct ethtool_dump * val)2038d44a3cedSSudarsana Reddy Kalluru static int qede_set_dump(struct net_device *dev, struct ethtool_dump *val)
2039d44a3cedSSudarsana Reddy Kalluru {
2040d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
2041d44a3cedSSudarsana Reddy Kalluru int rc = 0;
2042d44a3cedSSudarsana Reddy Kalluru
2043d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.cmd == QEDE_DUMP_CMD_NONE) {
2044d44a3cedSSudarsana Reddy Kalluru if (val->flag > QEDE_DUMP_CMD_MAX) {
2045d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Invalid command %d\n", val->flag);
2046d44a3cedSSudarsana Reddy Kalluru return -EINVAL;
2047d44a3cedSSudarsana Reddy Kalluru }
2048d44a3cedSSudarsana Reddy Kalluru edev->dump_info.cmd = val->flag;
2049d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args = 0;
2050d44a3cedSSudarsana Reddy Kalluru return 0;
2051d44a3cedSSudarsana Reddy Kalluru }
2052d44a3cedSSudarsana Reddy Kalluru
2053d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.num_args == QEDE_DUMP_MAX_ARGS) {
2054d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Arg count = %d\n", edev->dump_info.num_args);
2055d44a3cedSSudarsana Reddy Kalluru return -EINVAL;
2056d44a3cedSSudarsana Reddy Kalluru }
2057d44a3cedSSudarsana Reddy Kalluru
2058d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) {
2059d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG:
2060d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[edev->dump_info.num_args] = val->flag;
2061d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args++;
2062d44a3cedSSudarsana Reddy Kalluru break;
2063849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP:
2064849dbf09SSudarsana Reddy Kalluru rc = edev->ops->common->set_grc_config(edev->cdev,
2065849dbf09SSudarsana Reddy Kalluru val->flag, 1);
2066849dbf09SSudarsana Reddy Kalluru break;
2067d44a3cedSSudarsana Reddy Kalluru default:
2068d44a3cedSSudarsana Reddy Kalluru break;
2069d44a3cedSSudarsana Reddy Kalluru }
2070d44a3cedSSudarsana Reddy Kalluru
2071d44a3cedSSudarsana Reddy Kalluru return rc;
2072d44a3cedSSudarsana Reddy Kalluru }
2073d44a3cedSSudarsana Reddy Kalluru
qede_get_dump_flag(struct net_device * dev,struct ethtool_dump * dump)2074d44a3cedSSudarsana Reddy Kalluru static int qede_get_dump_flag(struct net_device *dev,
2075d44a3cedSSudarsana Reddy Kalluru struct ethtool_dump *dump)
2076d44a3cedSSudarsana Reddy Kalluru {
2077d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
2078d44a3cedSSudarsana Reddy Kalluru
2079849dbf09SSudarsana Reddy Kalluru if (!edev->ops || !edev->ops->common) {
2080849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Edev ops not populated\n");
2081849dbf09SSudarsana Reddy Kalluru return -EINVAL;
2082849dbf09SSudarsana Reddy Kalluru }
2083849dbf09SSudarsana Reddy Kalluru
2084d44a3cedSSudarsana Reddy Kalluru dump->version = QEDE_DUMP_VERSION;
2085d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) {
2086d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG:
2087d44a3cedSSudarsana Reddy Kalluru dump->flag = QEDE_DUMP_CMD_NVM_CFG;
20889e54ba7cSSudarsana Reddy Kalluru dump->len = edev->ops->common->read_nvm_cfg_len(edev->cdev,
20899e54ba7cSSudarsana Reddy Kalluru edev->dump_info.args[0]);
2090d44a3cedSSudarsana Reddy Kalluru break;
2091849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP:
2092849dbf09SSudarsana Reddy Kalluru dump->flag = QEDE_DUMP_CMD_GRCDUMP;
2093849dbf09SSudarsana Reddy Kalluru dump->len = edev->ops->common->dbg_all_data_size(edev->cdev);
2094d44a3cedSSudarsana Reddy Kalluru break;
2095849dbf09SSudarsana Reddy Kalluru default:
2096849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd);
2097849dbf09SSudarsana Reddy Kalluru return -EINVAL;
2098d44a3cedSSudarsana Reddy Kalluru }
2099d44a3cedSSudarsana Reddy Kalluru
2100d44a3cedSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG,
2101d44a3cedSSudarsana Reddy Kalluru "dump->version = 0x%x dump->flag = %d dump->len = %d\n",
2102d44a3cedSSudarsana Reddy Kalluru dump->version, dump->flag, dump->len);
2103d44a3cedSSudarsana Reddy Kalluru return 0;
2104d44a3cedSSudarsana Reddy Kalluru }
2105d44a3cedSSudarsana Reddy Kalluru
qede_get_dump_data(struct net_device * dev,struct ethtool_dump * dump,void * buf)2106d44a3cedSSudarsana Reddy Kalluru static int qede_get_dump_data(struct net_device *dev,
2107d44a3cedSSudarsana Reddy Kalluru struct ethtool_dump *dump, void *buf)
2108d44a3cedSSudarsana Reddy Kalluru {
2109d44a3cedSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev);
2110849dbf09SSudarsana Reddy Kalluru int rc = 0;
2111849dbf09SSudarsana Reddy Kalluru
2112849dbf09SSudarsana Reddy Kalluru if (!edev->ops || !edev->ops->common) {
2113849dbf09SSudarsana Reddy Kalluru DP_ERR(edev, "Edev ops not populated\n");
21149e54ba7cSSudarsana Reddy Kalluru rc = -EINVAL;
21159e54ba7cSSudarsana Reddy Kalluru goto err;
2116849dbf09SSudarsana Reddy Kalluru }
2117d44a3cedSSudarsana Reddy Kalluru
2118d44a3cedSSudarsana Reddy Kalluru switch (edev->dump_info.cmd) {
2119d44a3cedSSudarsana Reddy Kalluru case QEDE_DUMP_CMD_NVM_CFG:
2120d44a3cedSSudarsana Reddy Kalluru if (edev->dump_info.num_args != QEDE_DUMP_NVM_ARG_COUNT) {
2121d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Arg count = %d required = %d\n",
2122d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args,
2123d44a3cedSSudarsana Reddy Kalluru QEDE_DUMP_NVM_ARG_COUNT);
21249e54ba7cSSudarsana Reddy Kalluru rc = -EINVAL;
21259e54ba7cSSudarsana Reddy Kalluru goto err;
2126d44a3cedSSudarsana Reddy Kalluru }
2127d44a3cedSSudarsana Reddy Kalluru rc = edev->ops->common->read_nvm_cfg(edev->cdev, (u8 **)&buf,
2128d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[0],
2129d44a3cedSSudarsana Reddy Kalluru edev->dump_info.args[1]);
2130d44a3cedSSudarsana Reddy Kalluru break;
2131849dbf09SSudarsana Reddy Kalluru case QEDE_DUMP_CMD_GRCDUMP:
2132849dbf09SSudarsana Reddy Kalluru memset(buf, 0, dump->len);
2133849dbf09SSudarsana Reddy Kalluru rc = edev->ops->common->dbg_all_data(edev->cdev, buf);
2134849dbf09SSudarsana Reddy Kalluru break;
2135d44a3cedSSudarsana Reddy Kalluru default:
2136d44a3cedSSudarsana Reddy Kalluru DP_ERR(edev, "Invalid cmd = %d\n", edev->dump_info.cmd);
2137d44a3cedSSudarsana Reddy Kalluru rc = -EINVAL;
2138d44a3cedSSudarsana Reddy Kalluru break;
2139d44a3cedSSudarsana Reddy Kalluru }
2140d44a3cedSSudarsana Reddy Kalluru
21419e54ba7cSSudarsana Reddy Kalluru err:
2142d44a3cedSSudarsana Reddy Kalluru edev->dump_info.cmd = QEDE_DUMP_CMD_NONE;
2143d44a3cedSSudarsana Reddy Kalluru edev->dump_info.num_args = 0;
21449e54ba7cSSudarsana Reddy Kalluru memset(edev->dump_info.args, 0, sizeof(edev->dump_info.args));
2145d44a3cedSSudarsana Reddy Kalluru
2146d44a3cedSSudarsana Reddy Kalluru return rc;
2147d44a3cedSSudarsana Reddy Kalluru }
2148d44a3cedSSudarsana Reddy Kalluru
qede_set_per_coalesce(struct net_device * dev,u32 queue,struct ethtool_coalesce * coal)2149b0ec5489SBhaskar Upadhaya int qede_set_per_coalesce(struct net_device *dev, u32 queue,
2150a0d2d97dSBhaskar Upadhaya struct ethtool_coalesce *coal)
2151a0d2d97dSBhaskar Upadhaya {
2152a0d2d97dSBhaskar Upadhaya struct qede_dev *edev = netdev_priv(dev);
2153a0d2d97dSBhaskar Upadhaya struct qede_fastpath *fp;
2154a0d2d97dSBhaskar Upadhaya u16 rxc, txc;
2155a0d2d97dSBhaskar Upadhaya int rc = 0;
2156a0d2d97dSBhaskar Upadhaya
2157a0d2d97dSBhaskar Upadhaya if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
2158a0d2d97dSBhaskar Upadhaya coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
2159a0d2d97dSBhaskar Upadhaya DP_INFO(edev,
2160a0d2d97dSBhaskar Upadhaya "Can't support requested %s coalesce value [max supported value %d]\n",
2161a0d2d97dSBhaskar Upadhaya coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx"
2162a0d2d97dSBhaskar Upadhaya : "tx",
2163a0d2d97dSBhaskar Upadhaya QED_COALESCE_MAX);
2164a0d2d97dSBhaskar Upadhaya return -EINVAL;
2165a0d2d97dSBhaskar Upadhaya }
2166a0d2d97dSBhaskar Upadhaya
2167a0d2d97dSBhaskar Upadhaya rxc = (u16)coal->rx_coalesce_usecs;
2168a0d2d97dSBhaskar Upadhaya txc = (u16)coal->tx_coalesce_usecs;
2169a0d2d97dSBhaskar Upadhaya
2170a0d2d97dSBhaskar Upadhaya __qede_lock(edev);
2171a0d2d97dSBhaskar Upadhaya if (queue >= edev->num_queues) {
2172a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Invalid queue\n");
2173a0d2d97dSBhaskar Upadhaya rc = -EINVAL;
2174a0d2d97dSBhaskar Upadhaya goto out;
2175a0d2d97dSBhaskar Upadhaya }
2176a0d2d97dSBhaskar Upadhaya
2177a0d2d97dSBhaskar Upadhaya if (edev->state != QEDE_STATE_OPEN) {
2178a0d2d97dSBhaskar Upadhaya rc = -EINVAL;
2179a0d2d97dSBhaskar Upadhaya goto out;
2180a0d2d97dSBhaskar Upadhaya }
2181a0d2d97dSBhaskar Upadhaya
2182a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue];
2183a0d2d97dSBhaskar Upadhaya
2184a0d2d97dSBhaskar Upadhaya if (edev->fp_array[queue].type & QEDE_FASTPATH_RX) {
2185a0d2d97dSBhaskar Upadhaya rc = edev->ops->common->set_coalesce(edev->cdev,
2186a0d2d97dSBhaskar Upadhaya rxc, 0,
2187a0d2d97dSBhaskar Upadhaya fp->rxq->handle);
2188a0d2d97dSBhaskar Upadhaya if (rc) {
2189a0d2d97dSBhaskar Upadhaya DP_INFO(edev,
2190a0d2d97dSBhaskar Upadhaya "Set RX coalesce error, rc = %d\n", rc);
2191a0d2d97dSBhaskar Upadhaya goto out;
2192a0d2d97dSBhaskar Upadhaya }
2193b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].rxc = rxc;
2194b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].isvalid = true;
2195a0d2d97dSBhaskar Upadhaya }
2196a0d2d97dSBhaskar Upadhaya
2197a0d2d97dSBhaskar Upadhaya if (edev->fp_array[queue].type & QEDE_FASTPATH_TX) {
2198a0d2d97dSBhaskar Upadhaya rc = edev->ops->common->set_coalesce(edev->cdev,
2199a0d2d97dSBhaskar Upadhaya 0, txc,
2200a0d2d97dSBhaskar Upadhaya fp->txq->handle);
2201a0d2d97dSBhaskar Upadhaya if (rc) {
2202a0d2d97dSBhaskar Upadhaya DP_INFO(edev,
2203a0d2d97dSBhaskar Upadhaya "Set TX coalesce error, rc = %d\n", rc);
2204a0d2d97dSBhaskar Upadhaya goto out;
2205a0d2d97dSBhaskar Upadhaya }
2206b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].txc = txc;
2207b0ec5489SBhaskar Upadhaya edev->coal_entry[queue].isvalid = true;
2208a0d2d97dSBhaskar Upadhaya }
2209a0d2d97dSBhaskar Upadhaya out:
2210a0d2d97dSBhaskar Upadhaya __qede_unlock(edev);
2211a0d2d97dSBhaskar Upadhaya
2212a0d2d97dSBhaskar Upadhaya return rc;
2213a0d2d97dSBhaskar Upadhaya }
2214a0d2d97dSBhaskar Upadhaya
qede_get_per_coalesce(struct net_device * dev,u32 queue,struct ethtool_coalesce * coal)2215a0d2d97dSBhaskar Upadhaya static int qede_get_per_coalesce(struct net_device *dev,
2216a0d2d97dSBhaskar Upadhaya u32 queue,
2217a0d2d97dSBhaskar Upadhaya struct ethtool_coalesce *coal)
2218a0d2d97dSBhaskar Upadhaya {
2219a0d2d97dSBhaskar Upadhaya void *rx_handle = NULL, *tx_handle = NULL;
2220a0d2d97dSBhaskar Upadhaya struct qede_dev *edev = netdev_priv(dev);
2221a0d2d97dSBhaskar Upadhaya struct qede_fastpath *fp;
2222a0d2d97dSBhaskar Upadhaya u16 rx_coal, tx_coal;
2223a0d2d97dSBhaskar Upadhaya int rc = 0;
2224a0d2d97dSBhaskar Upadhaya
2225a0d2d97dSBhaskar Upadhaya rx_coal = QED_DEFAULT_RX_USECS;
2226a0d2d97dSBhaskar Upadhaya tx_coal = QED_DEFAULT_TX_USECS;
2227a0d2d97dSBhaskar Upadhaya
2228a0d2d97dSBhaskar Upadhaya memset(coal, 0, sizeof(struct ethtool_coalesce));
2229a0d2d97dSBhaskar Upadhaya
2230a0d2d97dSBhaskar Upadhaya __qede_lock(edev);
2231a0d2d97dSBhaskar Upadhaya if (queue >= edev->num_queues) {
2232a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Invalid queue\n");
2233a0d2d97dSBhaskar Upadhaya rc = -EINVAL;
2234a0d2d97dSBhaskar Upadhaya goto out;
2235a0d2d97dSBhaskar Upadhaya }
2236a0d2d97dSBhaskar Upadhaya
2237a0d2d97dSBhaskar Upadhaya if (edev->state != QEDE_STATE_OPEN) {
2238a0d2d97dSBhaskar Upadhaya rc = -EINVAL;
2239a0d2d97dSBhaskar Upadhaya goto out;
2240a0d2d97dSBhaskar Upadhaya }
2241a0d2d97dSBhaskar Upadhaya
2242a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue];
2243a0d2d97dSBhaskar Upadhaya
2244a0d2d97dSBhaskar Upadhaya if (fp->type & QEDE_FASTPATH_RX)
2245a0d2d97dSBhaskar Upadhaya rx_handle = fp->rxq->handle;
2246a0d2d97dSBhaskar Upadhaya
2247a0d2d97dSBhaskar Upadhaya rc = edev->ops->get_coalesce(edev->cdev, &rx_coal,
2248a0d2d97dSBhaskar Upadhaya rx_handle);
2249a0d2d97dSBhaskar Upadhaya if (rc) {
2250a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Read Rx coalesce error\n");
2251a0d2d97dSBhaskar Upadhaya goto out;
2252a0d2d97dSBhaskar Upadhaya }
2253a0d2d97dSBhaskar Upadhaya
2254a0d2d97dSBhaskar Upadhaya fp = &edev->fp_array[queue];
2255a0d2d97dSBhaskar Upadhaya if (fp->type & QEDE_FASTPATH_TX)
2256a0d2d97dSBhaskar Upadhaya tx_handle = fp->txq->handle;
2257a0d2d97dSBhaskar Upadhaya
2258a0d2d97dSBhaskar Upadhaya rc = edev->ops->get_coalesce(edev->cdev, &tx_coal,
2259a0d2d97dSBhaskar Upadhaya tx_handle);
2260a0d2d97dSBhaskar Upadhaya if (rc)
2261a0d2d97dSBhaskar Upadhaya DP_INFO(edev, "Read Tx coalesce error\n");
2262a0d2d97dSBhaskar Upadhaya
2263a0d2d97dSBhaskar Upadhaya out:
2264a0d2d97dSBhaskar Upadhaya __qede_unlock(edev);
2265a0d2d97dSBhaskar Upadhaya
2266a0d2d97dSBhaskar Upadhaya coal->rx_coalesce_usecs = rx_coal;
2267a0d2d97dSBhaskar Upadhaya coal->tx_coalesce_usecs = tx_coal;
2268a0d2d97dSBhaskar Upadhaya
2269a0d2d97dSBhaskar Upadhaya return rc;
2270a0d2d97dSBhaskar Upadhaya }
2271a0d2d97dSBhaskar Upadhaya
2272133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = {
2273*42510dffSManish Chopra .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2274*42510dffSManish Chopra ETHTOOL_COALESCE_STATS_BLOCK_USECS,
2275054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings,
2276054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings,
2277133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo,
2278e0971c83STomer Tayar .get_regs_len = qede_get_regs_len,
2279e0971c83STomer Tayar .get_regs = qede_get_regs,
228014d39648SMintz, Yuval .get_wol = qede_get_wol,
228114d39648SMintz, Yuval .set_wol = qede_set_wol,
2282133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel,
2283133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel,
228432a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset,
2285133fac0eSSudarsana Kalluru .get_link = qede_get_link,
2286d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce,
2287d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce,
228801ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam,
228901ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam,
22900f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam,
22910f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam,
2292133fac0eSSudarsana Kalluru .get_strings = qede_get_strings,
22933d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id,
2294133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats,
2295f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags,
22967d9acd87SIgor Russkikh .set_priv_flags = qede_set_priv_flags,
2297133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count,
2298961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc,
2299961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc,
2300961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size,
2301961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size,
2302961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh,
2303961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh,
23044c55215cSSudarsana Reddy Kalluru .get_ts_info = qede_get_ts_info,
23058edf049dSSudarsana Kalluru .get_channels = qede_get_channels,
23068edf049dSSudarsana Kalluru .set_channels = qede_set_channels,
23073044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test,
230897df0d65SSudarsana Reddy Kalluru .get_module_info = qede_get_module_info,
230997df0d65SSudarsana Reddy Kalluru .get_module_eeprom = qede_get_module_eeprom,
2310c3dc48f7SSudarsana Reddy Kalluru .get_eee = qede_get_eee,
2311c3dc48f7SSudarsana Reddy Kalluru .set_eee = qede_set_eee,
23129bdca14aSAlexander Lobakin .get_fecparam = qede_get_fecparam,
23139bdca14aSAlexander Lobakin .set_fecparam = qede_set_fecparam,
23143d789994SManish Chopra .get_tunable = qede_get_tunable,
23153d789994SManish Chopra .set_tunable = qede_set_tunable,
2316a0d2d97dSBhaskar Upadhaya .get_per_queue_coalesce = qede_get_per_coalesce,
2317a0d2d97dSBhaskar Upadhaya .set_per_queue_coalesce = qede_set_per_coalesce,
2318ccfa110cSSudarsana Reddy Kalluru .flash_device = qede_flash_device,
2319d44a3cedSSudarsana Reddy Kalluru .get_dump_flag = qede_get_dump_flag,
2320d44a3cedSSudarsana Reddy Kalluru .get_dump_data = qede_get_dump_data,
2321d44a3cedSSudarsana Reddy Kalluru .set_dump = qede_set_dump,
2322133fac0eSSudarsana Kalluru };
2323133fac0eSSudarsana Kalluru
2324fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = {
2325*42510dffSManish Chopra .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2326*42510dffSManish Chopra ETHTOOL_COALESCE_STATS_BLOCK_USECS,
2327054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings,
2328fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo,
2329fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel,
2330fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel,
2331fefb0202SYuval Mintz .get_link = qede_get_link,
2332477f2d14SRahul Verma .get_coalesce = qede_get_coalesce,
2333477f2d14SRahul Verma .set_coalesce = qede_set_coalesce,
2334fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam,
2335fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam,
2336fefb0202SYuval Mintz .get_strings = qede_get_strings,
2337fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats,
2338fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags,
2339fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count,
2340fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc,
2341fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc,
2342fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size,
2343fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size,
2344fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh,
2345fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh,
2346fefb0202SYuval Mintz .get_channels = qede_get_channels,
2347fefb0202SYuval Mintz .set_channels = qede_set_channels,
2348a0d2d97dSBhaskar Upadhaya .get_per_queue_coalesce = qede_get_per_coalesce,
2349a0d2d97dSBhaskar Upadhaya .set_per_queue_coalesce = qede_set_per_coalesce,
23503d789994SManish Chopra .get_tunable = qede_get_tunable,
23513d789994SManish Chopra .set_tunable = qede_set_tunable,
2352fefb0202SYuval Mintz };
2353fefb0202SYuval Mintz
qede_set_ethtool_ops(struct net_device * dev)2354133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev)
2355133fac0eSSudarsana Kalluru {
2356fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev);
2357fefb0202SYuval Mintz
2358fefb0202SYuval Mintz if (IS_VF(edev))
2359fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops;
2360fefb0202SYuval Mintz else
2361133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops;
2362133fac0eSSudarsana Kalluru }
2363