1133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver 2e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation 3133fac0eSSudarsana Kalluru * 4e8f1cb50SMintz, Yuval * This software is available to you under a choice of one of two 5e8f1cb50SMintz, Yuval * licenses. You may choose to be licensed under the terms of the GNU 6e8f1cb50SMintz, Yuval * General Public License (GPL) Version 2, available from the file 7e8f1cb50SMintz, Yuval * COPYING in the main directory of this source tree, or the 8e8f1cb50SMintz, Yuval * OpenIB.org BSD license below: 9e8f1cb50SMintz, Yuval * 10e8f1cb50SMintz, Yuval * Redistribution and use in source and binary forms, with or 11e8f1cb50SMintz, Yuval * without modification, are permitted provided that the following 12e8f1cb50SMintz, Yuval * conditions are met: 13e8f1cb50SMintz, Yuval * 14e8f1cb50SMintz, Yuval * - Redistributions of source code must retain the above 15e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 16e8f1cb50SMintz, Yuval * disclaimer. 17e8f1cb50SMintz, Yuval * 18e8f1cb50SMintz, Yuval * - Redistributions in binary form must reproduce the above 19e8f1cb50SMintz, Yuval * copyright notice, this list of conditions and the following 20e8f1cb50SMintz, Yuval * disclaimer in the documentation and /or other materials 21e8f1cb50SMintz, Yuval * provided with the distribution. 22e8f1cb50SMintz, Yuval * 23e8f1cb50SMintz, Yuval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e8f1cb50SMintz, Yuval * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e8f1cb50SMintz, Yuval * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e8f1cb50SMintz, Yuval * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e8f1cb50SMintz, Yuval * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e8f1cb50SMintz, Yuval * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e8f1cb50SMintz, Yuval * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e8f1cb50SMintz, Yuval * SOFTWARE. 31133fac0eSSudarsana Kalluru */ 32133fac0eSSudarsana Kalluru #include <linux/version.h> 33133fac0eSSudarsana Kalluru #include <linux/types.h> 34133fac0eSSudarsana Kalluru #include <linux/netdevice.h> 3516f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h> 36133fac0eSSudarsana Kalluru #include <linux/ethtool.h> 37133fac0eSSudarsana Kalluru #include <linux/string.h> 38133fac0eSSudarsana Kalluru #include <linux/pci.h> 39133fac0eSSudarsana Kalluru #include <linux/capability.h> 40f29ffdb6SMintz, Yuval #include <linux/vmalloc.h> 41133fac0eSSudarsana Kalluru #include "qede.h" 424c55215cSSudarsana Reddy Kalluru #include "qede_ptp.h" 43133fac0eSSudarsana Kalluru 44133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \ 45133fac0eSSudarsana Kalluru (offsetof(struct qede_rx_queue, stat_name)) 46133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name) 47133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \ 48133fac0eSSudarsana Kalluru {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} 4916f46bf0SSudarsana Reddy Kalluru 5016f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100 5116f46bf0SSudarsana Reddy Kalluru 52133fac0eSSudarsana Kalluru static const struct { 53133fac0eSSudarsana Kalluru u64 offset; 54133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 55133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = { 5668db9ec2SSudarsana Reddy Kalluru QEDE_RQSTAT(rcv_pkts), 57133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_hw_errors), 58133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_alloc_errors), 59c72a6125SManish Chopra QEDE_RQSTAT(rx_ip_frags), 60496e0517SMintz, Yuval QEDE_RQSTAT(xdp_no_pass), 61133fac0eSSudarsana Kalluru }; 62133fac0eSSudarsana Kalluru 63133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) 6468db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \ 6568db9ec2SSudarsana Reddy Kalluru (offsetof(struct qede_tx_queue, stat_name)) 6668db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name) 6768db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \ 6868db9ec2SSudarsana Reddy Kalluru {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)} 6968db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr) 7068db9ec2SSudarsana Reddy Kalluru static const struct { 7168db9ec2SSudarsana Reddy Kalluru u64 offset; 7268db9ec2SSudarsana Reddy Kalluru char string[ETH_GSTRING_LEN]; 7368db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = { 7468db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(xmit_pkts), 7568db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(stopped_cnt), 7668db9ec2SSudarsana Reddy Kalluru }; 7768db9ec2SSudarsana Reddy Kalluru 789c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \ 799c79ddaaSMintz, Yuval (offsetof(type, stat_name) + (base)) 804dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name) (#stat_name) 819c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \ 829c79ddaaSMintz, Yuval {QEDE_STAT_OFFSET(stat_name, type, base), \ 839c79ddaaSMintz, Yuval QEDE_STAT_STRING(stat_name), \ 849c79ddaaSMintz, Yuval attr} 859c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \ 869c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0) 879c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \ 889c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, \ 899c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY)) 909c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \ 919c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_bb, \ 929c79ddaaSMintz, Yuval offsetof(struct qede_stats, bb), \ 939c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY)) 949c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \ 959c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_ah, \ 969c79ddaaSMintz, Yuval offsetof(struct qede_stats, ah), \ 979c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY)) 98133fac0eSSudarsana Kalluru static const struct { 99133fac0eSSudarsana Kalluru u64 offset; 100133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 1019c79ddaaSMintz, Yuval unsigned long attr; 1029c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY 0 1039c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY 1 1049c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY 2 105133fac0eSSudarsana Kalluru } qede_stats_arr[] = { 106133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes), 107133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes), 108133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes), 109133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts), 110133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts), 111133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts), 112133fac0eSSudarsana Kalluru 113133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes), 114133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes), 115133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes), 116133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts), 117133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts), 118133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts), 119133fac0eSSudarsana Kalluru 120133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets), 121d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets), 122d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets), 123d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets), 124d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets), 125d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets), 1269c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets), 1279c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets), 1289c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets), 1299c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets), 1309c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets), 1319c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets), 132133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets), 133133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets), 134133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets), 135133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets), 136133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets), 137133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets), 1389c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets), 1399c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets), 1409c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets), 1419c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets), 1429c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets), 143133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames), 144133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames), 145133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames), 146133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames), 147133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames), 148133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames), 149133fac0eSSudarsana Kalluru 150133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors), 151133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors), 152133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors), 153133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets), 154133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers), 155133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets), 156133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments), 1579c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_lpi_entry_count), 1589c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_total_collisions), 159133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates), 160133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards), 161133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards), 162133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards), 163133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards), 164608e00d0SManish Chopra QEDE_PF_STAT(gft_filter_drop), 165133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1661a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1671a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 168133fac0eSSudarsana Kalluru 169133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 170133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 171133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 172133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 173133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 17432d26a68SSudarsana Reddy Kalluru 17532d26a68SSudarsana Reddy Kalluru QEDE_STAT(link_change_count), 176133fac0eSSudarsana Kalluru }; 177133fac0eSSudarsana Kalluru 178133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 1799c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \ 1809c79ddaaSMintz, Yuval test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr) 1819c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \ 1829c79ddaaSMintz, Yuval test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr) 1839c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \ 1849c79ddaaSMintz, Yuval test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr) 185133fac0eSSudarsana Kalluru 186f3e72109SYuval Mintz enum { 187f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 188f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 189f3e72109SYuval Mintz }; 190f3e72109SYuval Mintz 191f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 192f3e72109SYuval Mintz "Coupled-Function", 193f3e72109SYuval Mintz }; 194f3e72109SYuval Mintz 1953044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 19616f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 1973044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 1983044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 1993044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 2003044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 2017a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 2023044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 2033044a02eSSudarsana Reddy Kalluru }; 2043044a02eSSudarsana Reddy Kalluru 2053044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 20616f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 2073044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 2083044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 2093044a02eSSudarsana Reddy Kalluru "Register (online)\t", 2103044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 2117a4b21b7SMintz, Yuval "Nvram (online)\t\t", 2123044a02eSSudarsana Reddy Kalluru }; 2133044a02eSSudarsana Reddy Kalluru 2144dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev, 2154dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf) 2164dbcd640SMintz, Yuval { 2174dbcd640SMintz, Yuval int i; 2184dbcd640SMintz, Yuval 2194dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 220cb6aeb07SMintz, Yuval if (txq->is_xdp) 221cb6aeb07SMintz, Yuval sprintf(*buf, "%d [XDP]: %s", 222cb6aeb07SMintz, Yuval QEDE_TXQ_XDP_TO_IDX(edev, txq), 223cb6aeb07SMintz, Yuval qede_tqstats_arr[i].string); 224cb6aeb07SMintz, Yuval else 2255e7baf0fSManish Chopra sprintf(*buf, "%d_%d: %s", txq->index, txq->cos, 2264dbcd640SMintz, Yuval qede_tqstats_arr[i].string); 2274dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2284dbcd640SMintz, Yuval } 2294dbcd640SMintz, Yuval } 2304dbcd640SMintz, Yuval 2314dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev, 2324dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf) 2334dbcd640SMintz, Yuval { 2344dbcd640SMintz, Yuval int i; 2354dbcd640SMintz, Yuval 2364dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 2374dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id, 2384dbcd640SMintz, Yuval qede_rqstats_arr[i].string); 2394dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2404dbcd640SMintz, Yuval } 2414dbcd640SMintz, Yuval } 2424dbcd640SMintz, Yuval 2439c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index) 2449c79ddaaSMintz, Yuval { 2459c79ddaaSMintz, Yuval return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) || 2469c79ddaaSMintz, Yuval (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) || 2479c79ddaaSMintz, Yuval (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index)); 2489c79ddaaSMintz, Yuval } 2499c79ddaaSMintz, Yuval 250133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 251133fac0eSSudarsana Kalluru { 2524dbcd640SMintz, Yuval struct qede_fastpath *fp; 2534dbcd640SMintz, Yuval int i; 254133fac0eSSudarsana Kalluru 2554dbcd640SMintz, Yuval /* Account for queue statistics */ 2564dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 2574dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 25868db9ec2SSudarsana Reddy Kalluru 2594dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 2604dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf); 2614dbcd640SMintz, Yuval 262cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 263cb6aeb07SMintz, Yuval qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf); 264cb6aeb07SMintz, Yuval 2655e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 2665e7baf0fSManish Chopra int cos; 2675e7baf0fSManish Chopra 2685e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 2695e7baf0fSManish Chopra qede_get_strings_stats_txq(edev, 2705e7baf0fSManish Chopra &fp->txq[cos], &buf); 2715e7baf0fSManish Chopra } 272cbbf049aSMintz, Yuval } 273cbbf049aSMintz, Yuval 2744dbcd640SMintz, Yuval /* Account for non-queue statistics */ 2754dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 2769c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 277fefb0202SYuval Mintz continue; 2784dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string); 2794dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN; 280133fac0eSSudarsana Kalluru } 281133fac0eSSudarsana Kalluru } 282133fac0eSSudarsana Kalluru 283133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 284133fac0eSSudarsana Kalluru { 285133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 286133fac0eSSudarsana Kalluru 287133fac0eSSudarsana Kalluru switch (stringset) { 288133fac0eSSudarsana Kalluru case ETH_SS_STATS: 289133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 290133fac0eSSudarsana Kalluru break; 291f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 292f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 293f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 294f3e72109SYuval Mintz break; 2953044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2963044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 2973044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 2983044a02eSSudarsana Reddy Kalluru break; 299133fac0eSSudarsana Kalluru default: 300133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 301133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 302133fac0eSSudarsana Kalluru } 303133fac0eSSudarsana Kalluru } 304133fac0eSSudarsana Kalluru 3054dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) 3064dbcd640SMintz, Yuval { 3074dbcd640SMintz, Yuval int i; 3084dbcd640SMintz, Yuval 3094dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 3104dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); 3114dbcd640SMintz, Yuval (*buf)++; 3124dbcd640SMintz, Yuval } 3134dbcd640SMintz, Yuval } 3144dbcd640SMintz, Yuval 3154dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) 3164dbcd640SMintz, Yuval { 3174dbcd640SMintz, Yuval int i; 3184dbcd640SMintz, Yuval 3194dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 3204dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); 3214dbcd640SMintz, Yuval (*buf)++; 3224dbcd640SMintz, Yuval } 3234dbcd640SMintz, Yuval } 3244dbcd640SMintz, Yuval 325133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 326133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 327133fac0eSSudarsana Kalluru { 328133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3294dbcd640SMintz, Yuval struct qede_fastpath *fp; 3304dbcd640SMintz, Yuval int i; 331133fac0eSSudarsana Kalluru 332133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 333133fac0eSSudarsana Kalluru 334567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */ 335567b3c12SMintz, Yuval __qede_lock(edev); 336567b3c12SMintz, Yuval 3374dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 3384dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 339133fac0eSSudarsana Kalluru 3404dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 3414dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf); 34268db9ec2SSudarsana Reddy Kalluru 343cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 344cb6aeb07SMintz, Yuval qede_get_ethtool_stats_txq(fp->xdp_tx, &buf); 345cb6aeb07SMintz, Yuval 3465e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 3475e7baf0fSManish Chopra int cos; 3485e7baf0fSManish Chopra 3495e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 3505e7baf0fSManish Chopra qede_get_ethtool_stats_txq(&fp->txq[cos], &buf); 3515e7baf0fSManish Chopra } 35268db9ec2SSudarsana Reddy Kalluru } 35368db9ec2SSudarsana Reddy Kalluru 3544dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 3559c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 356fefb0202SYuval Mintz continue; 3574dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) + 3584dbcd640SMintz, Yuval qede_stats_arr[i].offset)); 3594dbcd640SMintz, Yuval 3604dbcd640SMintz, Yuval buf++; 361fefb0202SYuval Mintz } 362133fac0eSSudarsana Kalluru 363567b3c12SMintz, Yuval __qede_unlock(edev); 364133fac0eSSudarsana Kalluru } 365133fac0eSSudarsana Kalluru 366133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 367133fac0eSSudarsana Kalluru { 368133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3699c79ddaaSMintz, Yuval int num_stats = QEDE_NUM_STATS, i; 370133fac0eSSudarsana Kalluru 371133fac0eSSudarsana Kalluru switch (stringset) { 372133fac0eSSudarsana Kalluru case ETH_SS_STATS: 373fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 3749c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 375fefb0202SYuval Mintz num_stats--; 3764dbcd640SMintz, Yuval 3774dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */ 3785e7baf0fSManish Chopra num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * 3795e7baf0fSManish Chopra edev->dev_info.num_tc; 3804dbcd640SMintz, Yuval 3814dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */ 3824dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; 3834dbcd640SMintz, Yuval 384cb6aeb07SMintz, Yuval /* Account for XDP statistics [if needed] */ 385cb6aeb07SMintz, Yuval if (edev->xdp_prog) 386cb6aeb07SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; 3874dbcd640SMintz, Yuval return num_stats; 3884dbcd640SMintz, Yuval 389f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 390f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 3913044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 3926ecb0a0cSYuval Mintz if (!IS_VF(edev)) 3933044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 3946ecb0a0cSYuval Mintz else 3956ecb0a0cSYuval Mintz return 0; 396133fac0eSSudarsana Kalluru default: 397133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 398133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 399133fac0eSSudarsana Kalluru return -EINVAL; 400133fac0eSSudarsana Kalluru } 401133fac0eSSudarsana Kalluru } 402133fac0eSSudarsana Kalluru 403f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 404f3e72109SYuval Mintz { 405f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 406f3e72109SYuval Mintz 407f3e72109SYuval Mintz return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; 408f3e72109SYuval Mintz } 409f3e72109SYuval Mintz 410054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 411054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 412054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 413054c67d1SSudarsana Reddy Kalluru }; 414054c67d1SSudarsana Reddy Kalluru 415054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 416054c67d1SSudarsana Reddy Kalluru {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, 417054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 418054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 419054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 420054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT}, 421054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 422054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 423054c67d1SSudarsana Reddy Kalluru {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 424054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 425054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 426054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 427054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 428054c67d1SSudarsana Reddy Kalluru }; 429054c67d1SSudarsana Reddy Kalluru 430054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 431054c67d1SSudarsana Reddy Kalluru { \ 432054c67d1SSudarsana Reddy Kalluru int i; \ 433054c67d1SSudarsana Reddy Kalluru \ 434d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 435054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 436054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 437054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 438054c67d1SSudarsana Reddy Kalluru } \ 439054c67d1SSudarsana Reddy Kalluru } 440054c67d1SSudarsana Reddy Kalluru 441054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 442054c67d1SSudarsana Reddy Kalluru { \ 443054c67d1SSudarsana Reddy Kalluru int i; \ 444054c67d1SSudarsana Reddy Kalluru \ 445d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 446054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 447054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 448054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 449054c67d1SSudarsana Reddy Kalluru } \ 450054c67d1SSudarsana Reddy Kalluru } 451054c67d1SSudarsana Reddy Kalluru 452054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 453054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 454133fac0eSSudarsana Kalluru { 455054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 456133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 457133fac0eSSudarsana Kalluru struct qed_link_output current_link; 458133fac0eSSudarsana Kalluru 459567b3c12SMintz, Yuval __qede_lock(edev); 460567b3c12SMintz, Yuval 461133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 462133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 463133fac0eSSudarsana Kalluru 464054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 465054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 466054c67d1SSudarsana Reddy Kalluru 467054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 468054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 469054c67d1SSudarsana Reddy Kalluru 470054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 471054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 472054c67d1SSudarsana Reddy Kalluru 473133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 474054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 475054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 476133fac0eSSudarsana Kalluru } else { 477054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 478054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 479133fac0eSSudarsana Kalluru } 480567b3c12SMintz, Yuval 481567b3c12SMintz, Yuval __qede_unlock(edev); 482567b3c12SMintz, Yuval 483054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 484054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 485133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 486133fac0eSSudarsana Kalluru 487133fac0eSSudarsana Kalluru return 0; 488133fac0eSSudarsana Kalluru } 489133fac0eSSudarsana Kalluru 490054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 491054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 492133fac0eSSudarsana Kalluru { 493054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 494133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 495133fac0eSSudarsana Kalluru struct qed_link_output current_link; 496133fac0eSSudarsana Kalluru struct qed_link_params params; 497133fac0eSSudarsana Kalluru 498fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 499054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 500133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 501133fac0eSSudarsana Kalluru } 502133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 503133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 504133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 505133fac0eSSudarsana Kalluru 506133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 507133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 508054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 509161adb04Ssudarsana.kalluru@cavium.com if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 510161adb04Ssudarsana.kalluru@cavium.com DP_INFO(edev, "Auto negotiation is not supported\n"); 511161adb04Ssudarsana.kalluru@cavium.com return -EOPNOTSUPP; 512161adb04Ssudarsana.kalluru@cavium.com } 513161adb04Ssudarsana.kalluru@cavium.com 514133fac0eSSudarsana Kalluru params.autoneg = true; 515133fac0eSSudarsana Kalluru params.forced_speed = 0; 516054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 517133fac0eSSudarsana Kalluru } else { /* forced speed */ 518133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 519133fac0eSSudarsana Kalluru params.autoneg = false; 520054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 521054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 5229ac4c546SSudarsana Reddy Kalluru case SPEED_1000: 5239ac4c546SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 5249ac4c546SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT)) { 5259ac4c546SSudarsana Reddy Kalluru DP_INFO(edev, "1G speed not supported\n"); 5269ac4c546SSudarsana Reddy Kalluru return -EINVAL; 5279ac4c546SSudarsana Reddy Kalluru } 5289ac4c546SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_1000baseT_Full_BIT; 5299ac4c546SSudarsana Reddy Kalluru break; 530133fac0eSSudarsana Kalluru case SPEED_10000: 531133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 532054c67d1SSudarsana Reddy Kalluru QED_LM_10000baseKR_Full_BIT)) { 533133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 534133fac0eSSudarsana Kalluru return -EINVAL; 535133fac0eSSudarsana Kalluru } 536054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_10000baseKR_Full_BIT; 537054c67d1SSudarsana Reddy Kalluru break; 538054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 539054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 540054c67d1SSudarsana Reddy Kalluru QED_LM_25000baseKR_Full_BIT)) { 541054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 542054c67d1SSudarsana Reddy Kalluru return -EINVAL; 543054c67d1SSudarsana Reddy Kalluru } 544054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_25000baseKR_Full_BIT; 545133fac0eSSudarsana Kalluru break; 546133fac0eSSudarsana Kalluru case SPEED_40000: 547133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 548054c67d1SSudarsana Reddy Kalluru QED_LM_40000baseLR4_Full_BIT)) { 549133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 550133fac0eSSudarsana Kalluru return -EINVAL; 551133fac0eSSudarsana Kalluru } 552054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_40000baseLR4_Full_BIT; 553054c67d1SSudarsana Reddy Kalluru break; 55416d5946aSYuval Mintz case SPEED_50000: 555054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 556054c67d1SSudarsana Reddy Kalluru QED_LM_50000baseKR2_Full_BIT)) { 557054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 558054c67d1SSudarsana Reddy Kalluru return -EINVAL; 559054c67d1SSudarsana Reddy Kalluru } 560054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_50000baseKR2_Full_BIT; 561054c67d1SSudarsana Reddy Kalluru break; 56216d5946aSYuval Mintz case SPEED_100000: 563054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 564054c67d1SSudarsana Reddy Kalluru QED_LM_100000baseKR4_Full_BIT)) { 565054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 566054c67d1SSudarsana Reddy Kalluru return -EINVAL; 567054c67d1SSudarsana Reddy Kalluru } 568054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_100000baseKR4_Full_BIT; 569133fac0eSSudarsana Kalluru break; 570133fac0eSSudarsana Kalluru default: 571054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 572133fac0eSSudarsana Kalluru return -EINVAL; 573133fac0eSSudarsana Kalluru } 574133fac0eSSudarsana Kalluru } 575133fac0eSSudarsana Kalluru 576133fac0eSSudarsana Kalluru params.link_up = true; 577133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 578133fac0eSSudarsana Kalluru 579133fac0eSSudarsana Kalluru return 0; 580133fac0eSSudarsana Kalluru } 581133fac0eSSudarsana Kalluru 582133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 583133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 584133fac0eSSudarsana Kalluru { 585133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 586133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 587133fac0eSSudarsana Kalluru 588133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 589133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 590133fac0eSSudarsana Kalluru 591133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 592133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 593133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 594133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 595133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 596133fac0eSSudarsana Kalluru 597133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 598133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 599133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 600133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 601133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 602133fac0eSSudarsana Kalluru 603133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 604133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 605133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 606133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 607133fac0eSSudarsana Kalluru } else { 608133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 609133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 610133fac0eSSudarsana Kalluru } 611133fac0eSSudarsana Kalluru 612133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 613133fac0eSSudarsana Kalluru } 614133fac0eSSudarsana Kalluru 61514d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 61614d39648SMintz, Yuval { 61714d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 61814d39648SMintz, Yuval 61914d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 62014d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 62114d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 62214d39648SMintz, Yuval } 62314d39648SMintz, Yuval } 62414d39648SMintz, Yuval 62514d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 62614d39648SMintz, Yuval { 62714d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 62814d39648SMintz, Yuval bool wol_requested; 62914d39648SMintz, Yuval int rc; 63014d39648SMintz, Yuval 63114d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 63214d39648SMintz, Yuval DP_INFO(edev, 63314d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 63414d39648SMintz, Yuval return -EINVAL; 63514d39648SMintz, Yuval } 63614d39648SMintz, Yuval 63714d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 63814d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 63914d39648SMintz, Yuval return 0; 64014d39648SMintz, Yuval 64114d39648SMintz, Yuval /* Need to actually change configuration */ 64214d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 64314d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 64414d39648SMintz, Yuval return -EINVAL; 64514d39648SMintz, Yuval } 64614d39648SMintz, Yuval 64714d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 64814d39648SMintz, Yuval if (!rc) 64914d39648SMintz, Yuval edev->wol_enabled = wol_requested; 65014d39648SMintz, Yuval 65114d39648SMintz, Yuval return rc; 65214d39648SMintz, Yuval } 65314d39648SMintz, Yuval 654133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 655133fac0eSSudarsana Kalluru { 656133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 657133fac0eSSudarsana Kalluru 6581a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 659133fac0eSSudarsana Kalluru } 660133fac0eSSudarsana Kalluru 661133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 662133fac0eSSudarsana Kalluru { 663133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 664133fac0eSSudarsana Kalluru u32 dp_module = 0; 665133fac0eSSudarsana Kalluru u8 dp_level = 0; 666133fac0eSSudarsana Kalluru 667133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 668133fac0eSSudarsana Kalluru 669133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 670133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 671133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 672133fac0eSSudarsana Kalluru dp_module, dp_level); 673133fac0eSSudarsana Kalluru } 674133fac0eSSudarsana Kalluru 67532a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 67632a7a570SSudarsana Kalluru { 67732a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 67832a7a570SSudarsana Kalluru struct qed_link_output current_link; 67932a7a570SSudarsana Kalluru struct qed_link_params link_params; 68032a7a570SSudarsana Kalluru 681fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 6821a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 683fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 684fe7cd2bfSYuval Mintz } 685fe7cd2bfSYuval Mintz 68632a7a570SSudarsana Kalluru if (!netif_running(dev)) 68732a7a570SSudarsana Kalluru return 0; 68832a7a570SSudarsana Kalluru 68932a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 69032a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 69132a7a570SSudarsana Kalluru if (!current_link.link_up) 69232a7a570SSudarsana Kalluru return 0; 69332a7a570SSudarsana Kalluru 69432a7a570SSudarsana Kalluru /* Toggle the link */ 69532a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 69632a7a570SSudarsana Kalluru link_params.link_up = false; 69732a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 69832a7a570SSudarsana Kalluru link_params.link_up = true; 69932a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 70032a7a570SSudarsana Kalluru 70132a7a570SSudarsana Kalluru return 0; 70232a7a570SSudarsana Kalluru } 70332a7a570SSudarsana Kalluru 704133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 705133fac0eSSudarsana Kalluru { 706133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 707133fac0eSSudarsana Kalluru struct qed_link_output current_link; 708133fac0eSSudarsana Kalluru 709133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 710133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 711133fac0eSSudarsana Kalluru 712133fac0eSSudarsana Kalluru return current_link.link_up; 713133fac0eSSudarsana Kalluru } 714133fac0eSSudarsana Kalluru 715ccfa110cSSudarsana Reddy Kalluru static int qede_flash_device(struct net_device *dev, 716ccfa110cSSudarsana Reddy Kalluru struct ethtool_flash *flash) 717ccfa110cSSudarsana Reddy Kalluru { 718ccfa110cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 719ccfa110cSSudarsana Reddy Kalluru 720ccfa110cSSudarsana Reddy Kalluru return edev->ops->common->nvm_flash(edev->cdev, flash->data); 721ccfa110cSSudarsana Reddy Kalluru } 722ccfa110cSSudarsana Reddy Kalluru 723d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 724d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 725d552fa84SSudarsana Reddy Kalluru { 726bf5a94bfSRahul Verma void *rx_handle = NULL, *tx_handle = NULL; 727d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 728bf5a94bfSRahul Verma u16 rx_coal, tx_coal, i, rc = 0; 729bf5a94bfSRahul Verma struct qede_fastpath *fp; 730bf5a94bfSRahul Verma 731bf5a94bfSRahul Verma rx_coal = QED_DEFAULT_RX_USECS; 732bf5a94bfSRahul Verma tx_coal = QED_DEFAULT_TX_USECS; 733d552fa84SSudarsana Reddy Kalluru 734d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 735d2890deaSSudarsana Reddy Kalluru 736bf5a94bfSRahul Verma __qede_lock(edev); 737bf5a94bfSRahul Verma if (edev->state == QEDE_STATE_OPEN) { 738bf5a94bfSRahul Verma for_each_queue(i) { 739bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 740d552fa84SSudarsana Reddy Kalluru 741bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_RX) { 742bf5a94bfSRahul Verma rx_handle = fp->rxq->handle; 743bf5a94bfSRahul Verma break; 744bf5a94bfSRahul Verma } 745bf5a94bfSRahul Verma } 746bf5a94bfSRahul Verma 747bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle); 748bf5a94bfSRahul Verma if (rc) { 749bf5a94bfSRahul Verma DP_INFO(edev, "Read Rx coalesce error\n"); 750bf5a94bfSRahul Verma goto out; 751bf5a94bfSRahul Verma } 752bf5a94bfSRahul Verma 753bf5a94bfSRahul Verma for_each_queue(i) { 7545e7baf0fSManish Chopra struct qede_tx_queue *txq; 7555e7baf0fSManish Chopra 756bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 7575e7baf0fSManish Chopra 7585e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 7595e7baf0fSManish Chopra * coalescing value, so no need to iterate over 7605e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 7615e7baf0fSManish Chopra */ 762bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_TX) { 7635e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 7645e7baf0fSManish Chopra tx_handle = txq->handle; 765bf5a94bfSRahul Verma break; 766bf5a94bfSRahul Verma } 767bf5a94bfSRahul Verma } 768bf5a94bfSRahul Verma 769bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle); 770bf5a94bfSRahul Verma if (rc) 771bf5a94bfSRahul Verma DP_INFO(edev, "Read Tx coalesce error\n"); 772bf5a94bfSRahul Verma } 773bf5a94bfSRahul Verma 774bf5a94bfSRahul Verma out: 775bf5a94bfSRahul Verma __qede_unlock(edev); 776bf5a94bfSRahul Verma 777bf5a94bfSRahul Verma coal->rx_coalesce_usecs = rx_coal; 778bf5a94bfSRahul Verma coal->tx_coalesce_usecs = tx_coal; 779bf5a94bfSRahul Verma 780bf5a94bfSRahul Verma return rc; 781d552fa84SSudarsana Reddy Kalluru } 782d552fa84SSudarsana Reddy Kalluru 783d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 784d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 785d552fa84SSudarsana Reddy Kalluru { 786d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 787477f2d14SRahul Verma struct qede_fastpath *fp; 788d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 789477f2d14SRahul Verma u16 rxc, txc; 790d552fa84SSudarsana Reddy Kalluru 791d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 792d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 793d552fa84SSudarsana Reddy Kalluru return -EINVAL; 794d552fa84SSudarsana Reddy Kalluru } 795d552fa84SSudarsana Reddy Kalluru 796d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 797d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 798d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 799d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 800477f2d14SRahul Verma coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" : 801477f2d14SRahul Verma "tx", QED_COALESCE_MAX); 802d552fa84SSudarsana Reddy Kalluru return -EINVAL; 803d552fa84SSudarsana Reddy Kalluru } 804d552fa84SSudarsana Reddy Kalluru 805d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 806d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 8079a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 808477f2d14SRahul Verma fp = &edev->fp_array[i]; 809477f2d14SRahul Verma 810477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 811477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 812477f2d14SRahul Verma rxc, 0, 813477f2d14SRahul Verma fp->rxq->handle); 814d552fa84SSudarsana Reddy Kalluru if (rc) { 815477f2d14SRahul Verma DP_INFO(edev, 816477f2d14SRahul Verma "Set RX coalesce error, rc = %d\n", rc); 817d552fa84SSudarsana Reddy Kalluru return rc; 818d552fa84SSudarsana Reddy Kalluru } 819d552fa84SSudarsana Reddy Kalluru } 820d552fa84SSudarsana Reddy Kalluru 821477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 8225e7baf0fSManish Chopra struct qede_tx_queue *txq; 8235e7baf0fSManish Chopra 8245e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 8255e7baf0fSManish Chopra * coalescing value, so no need to iterate over 8265e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 8275e7baf0fSManish Chopra */ 8285e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 8295e7baf0fSManish Chopra 830477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 831477f2d14SRahul Verma 0, txc, 8325e7baf0fSManish Chopra txq->handle); 833477f2d14SRahul Verma if (rc) { 834477f2d14SRahul Verma DP_INFO(edev, 835477f2d14SRahul Verma "Set TX coalesce error, rc = %d\n", rc); 836477f2d14SRahul Verma return rc; 837477f2d14SRahul Verma } 838477f2d14SRahul Verma } 839477f2d14SRahul Verma } 840477f2d14SRahul Verma 841d552fa84SSudarsana Reddy Kalluru return rc; 842d552fa84SSudarsana Reddy Kalluru } 843d552fa84SSudarsana Reddy Kalluru 84401ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 84501ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 84601ef7e05SSudarsana Kalluru { 84701ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 84801ef7e05SSudarsana Kalluru 84901ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 85001ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 85101ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 85201ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 85301ef7e05SSudarsana Kalluru } 85401ef7e05SSudarsana Kalluru 85501ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 85601ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 85701ef7e05SSudarsana Kalluru { 85801ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 85901ef7e05SSudarsana Kalluru 86001ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 86101ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 86201ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 86301ef7e05SSudarsana Kalluru 86401ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 86501ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 86601ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 86701ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 86801ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 86901ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 87001ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 87101ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 87201ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 87301ef7e05SSudarsana Kalluru return -EINVAL; 87401ef7e05SSudarsana Kalluru } 87501ef7e05SSudarsana Kalluru 87601ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 87701ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 87801ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 87901ef7e05SSudarsana Kalluru 880567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 88101ef7e05SSudarsana Kalluru 88201ef7e05SSudarsana Kalluru return 0; 88301ef7e05SSudarsana Kalluru } 88401ef7e05SSudarsana Kalluru 8850f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 8860f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 8870f7db144SSudarsana Kalluru { 8880f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8890f7db144SSudarsana Kalluru struct qed_link_output current_link; 8900f7db144SSudarsana Kalluru 8910f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 8920f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 8930f7db144SSudarsana Kalluru 8940f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 8950f7db144SSudarsana Kalluru epause->autoneg = true; 8960f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 8970f7db144SSudarsana Kalluru epause->rx_pause = true; 8980f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 8990f7db144SSudarsana Kalluru epause->tx_pause = true; 9000f7db144SSudarsana Kalluru 9010f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 9020f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 9030f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 9040f7db144SSudarsana Kalluru epause->tx_pause); 9050f7db144SSudarsana Kalluru } 9060f7db144SSudarsana Kalluru 9070f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 9080f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 9090f7db144SSudarsana Kalluru { 9100f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9110f7db144SSudarsana Kalluru struct qed_link_params params; 9120f7db144SSudarsana Kalluru struct qed_link_output current_link; 9130f7db144SSudarsana Kalluru 914fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 9150f7db144SSudarsana Kalluru DP_INFO(edev, 916fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 9170f7db144SSudarsana Kalluru return -EOPNOTSUPP; 9180f7db144SSudarsana Kalluru } 9190f7db144SSudarsana Kalluru 9200f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 9210f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 9220f7db144SSudarsana Kalluru 9230f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 9240f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 9250f7db144SSudarsana Kalluru if (epause->autoneg) { 926d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 9270f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 9280f7db144SSudarsana Kalluru return -EINVAL; 9290f7db144SSudarsana Kalluru } 9300f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 9310f7db144SSudarsana Kalluru } 9320f7db144SSudarsana Kalluru if (epause->rx_pause) 9330f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 9340f7db144SSudarsana Kalluru if (epause->tx_pause) 9350f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 9360f7db144SSudarsana Kalluru 9370f7db144SSudarsana Kalluru params.link_up = true; 9380f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 9390f7db144SSudarsana Kalluru 9400f7db144SSudarsana Kalluru return 0; 9410f7db144SSudarsana Kalluru } 9420f7db144SSudarsana Kalluru 943e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 944e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 945e0971c83STomer Tayar { 946e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 947e0971c83STomer Tayar 948e0971c83STomer Tayar regs->version = 0; 949e0971c83STomer Tayar memset(buffer, 0, regs->len); 950e0971c83STomer Tayar 951e0971c83STomer Tayar if (edev->ops && edev->ops->common) 952e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 953e0971c83STomer Tayar } 954e0971c83STomer Tayar 955e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 956e0971c83STomer Tayar { 957e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 958e0971c83STomer Tayar 959e0971c83STomer Tayar if (edev->ops && edev->ops->common) 960e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 961e0971c83STomer Tayar else 962e0971c83STomer Tayar return -EINVAL; 963e0971c83STomer Tayar } 964e0971c83STomer Tayar 965567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev, 966567b3c12SMintz, Yuval struct qede_reload_args *args) 967133fac0eSSudarsana Kalluru { 968567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu; 969133fac0eSSudarsana Kalluru } 970133fac0eSSudarsana Kalluru 971133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 972133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 973133fac0eSSudarsana Kalluru { 974133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 975567b3c12SMintz, Yuval struct qede_reload_args args; 976133fac0eSSudarsana Kalluru 977133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 978133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 979133fac0eSSudarsana Kalluru 98018c602deSMichael Chan if (new_mtu > PAGE_SIZE) 98118c602deSMichael Chan ndev->features &= ~NETIF_F_GRO_HW; 98218c602deSMichael Chan 983133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */ 984567b3c12SMintz, Yuval args.u.mtu = new_mtu; 985567b3c12SMintz, Yuval args.func = &qede_update_mtu; 986567b3c12SMintz, Yuval qede_reload(edev, &args, false); 987133fac0eSSudarsana Kalluru 988567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu); 9890fefbfbaSSudarsana Kalluru 990133fac0eSSudarsana Kalluru return 0; 991133fac0eSSudarsana Kalluru } 992133fac0eSSudarsana Kalluru 9938edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 9948edf049dSSudarsana Kalluru struct ethtool_channels *channels) 9958edf049dSSudarsana Kalluru { 9968edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9978edf049dSSudarsana Kalluru 9988edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 999bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 1000bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 10019a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 10029a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 10039a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 10049a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 10058edf049dSSudarsana Kalluru } 10068edf049dSSudarsana Kalluru 10078edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 10088edf049dSSudarsana Kalluru struct ethtool_channels *channels) 10098edf049dSSudarsana Kalluru { 10108edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10119a4d7e86SSudarsana Reddy Kalluru u32 count; 10128edf049dSSudarsana Kalluru 10138edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10148edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 10158edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 10168edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 10178edf049dSSudarsana Kalluru 10189a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 10199a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 10209a4d7e86SSudarsana Reddy Kalluru 10219a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 10229a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 10238edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10248edf049dSSudarsana Kalluru "command parameters not supported\n"); 10258edf049dSSudarsana Kalluru return -EINVAL; 10268edf049dSSudarsana Kalluru } 10278edf049dSSudarsana Kalluru 10289a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 10299a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 10309a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10319a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 10329a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 10339a4d7e86SSudarsana Reddy Kalluru } 10349a4d7e86SSudarsana Reddy Kalluru 10359a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 10369a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10379a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 10389a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 10399a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 10409a4d7e86SSudarsana Reddy Kalluru } 10419a4d7e86SSudarsana Reddy Kalluru 10428edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 10439a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 10449a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 10459a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 10468edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10478edf049dSSudarsana Kalluru "No change in active parameters\n"); 10488edf049dSSudarsana Kalluru return 0; 10498edf049dSSudarsana Kalluru } 10508edf049dSSudarsana Kalluru 10518edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 10529a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 10539a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 10549a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 10558edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10569a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 10578edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 10588edf049dSSudarsana Kalluru return -EINVAL; 10598edf049dSSudarsana Kalluru } 10608edf049dSSudarsana Kalluru 10618edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 10629a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 10639a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 10649a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 1065ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 1066ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 1067ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 1068f29ffdb6SMintz, Yuval memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); 1069ed0dd915SSudarsana Reddy Kalluru } 1070ed0dd915SSudarsana Reddy Kalluru 1071567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 10728edf049dSSudarsana Kalluru 10738edf049dSSudarsana Kalluru return 0; 10748edf049dSSudarsana Kalluru } 10758edf049dSSudarsana Kalluru 10764c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev, 10774c55215cSSudarsana Reddy Kalluru struct ethtool_ts_info *info) 10784c55215cSSudarsana Reddy Kalluru { 10794c55215cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 10804c55215cSSudarsana Reddy Kalluru 10814c55215cSSudarsana Reddy Kalluru return qede_ptp_get_ts_info(edev, info); 10824c55215cSSudarsana Reddy Kalluru } 10834c55215cSSudarsana Reddy Kalluru 10843d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 10853d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 10863d971cbdSSudarsana Kalluru { 10873d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10883d971cbdSSudarsana Kalluru u8 led_state = 0; 10893d971cbdSSudarsana Kalluru 10903d971cbdSSudarsana Kalluru switch (state) { 10913d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 10923d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 10933d971cbdSSudarsana Kalluru 10943d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 10953d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 10963d971cbdSSudarsana Kalluru break; 10973d971cbdSSudarsana Kalluru 10983d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 10993d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 11003d971cbdSSudarsana Kalluru break; 11013d971cbdSSudarsana Kalluru 11023d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 11033d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 11043d971cbdSSudarsana Kalluru break; 11053d971cbdSSudarsana Kalluru } 11063d971cbdSSudarsana Kalluru 11073d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 11083d971cbdSSudarsana Kalluru 11093d971cbdSSudarsana Kalluru return 0; 11103d971cbdSSudarsana Kalluru } 11113d971cbdSSudarsana Kalluru 1112961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1113961acdeaSSudarsana Reddy Kalluru { 1114961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 1115961acdeaSSudarsana Reddy Kalluru 1116961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1117961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1118961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1119961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1120961acdeaSSudarsana Reddy Kalluru break; 1121961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1122f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV4_UDP) 1123961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1124961acdeaSSudarsana Reddy Kalluru break; 1125961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1126f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV6_UDP) 1127961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1128961acdeaSSudarsana Reddy Kalluru break; 1129961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1130961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1131961acdeaSSudarsana Reddy Kalluru break; 1132961acdeaSSudarsana Reddy Kalluru default: 1133961acdeaSSudarsana Reddy Kalluru info->data = 0; 1134961acdeaSSudarsana Reddy Kalluru break; 1135961acdeaSSudarsana Reddy Kalluru } 1136961acdeaSSudarsana Reddy Kalluru 1137961acdeaSSudarsana Reddy Kalluru return 0; 1138961acdeaSSudarsana Reddy Kalluru } 1139961acdeaSSudarsana Reddy Kalluru 1140961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 1141ec9b8dbdSChopra, Manish u32 *rule_locs) 1142961acdeaSSudarsana Reddy Kalluru { 1143961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1144ec9b8dbdSChopra, Manish int rc = 0; 1145961acdeaSSudarsana Reddy Kalluru 1146961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1147961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 11489a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 1149ec9b8dbdSChopra, Manish break; 1150961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 1151ec9b8dbdSChopra, Manish rc = qede_get_rss_flags(edev, info); 1152ec9b8dbdSChopra, Manish break; 1153ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLCNT: 1154ec9b8dbdSChopra, Manish info->rule_cnt = qede_get_arfs_filter_count(edev); 1155ec9b8dbdSChopra, Manish info->data = QEDE_RFS_MAX_FLTR; 1156ec9b8dbdSChopra, Manish break; 1157ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRULE: 1158ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_entry(edev, info); 1159ec9b8dbdSChopra, Manish break; 1160ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLALL: 1161ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_all(edev, info, rule_locs); 1162ec9b8dbdSChopra, Manish break; 1163961acdeaSSudarsana Reddy Kalluru default: 1164961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 1165ec9b8dbdSChopra, Manish rc = -EOPNOTSUPP; 1166961acdeaSSudarsana Reddy Kalluru } 1167ec9b8dbdSChopra, Manish 1168ec9b8dbdSChopra, Manish return rc; 1169961acdeaSSudarsana Reddy Kalluru } 1170961acdeaSSudarsana Reddy Kalluru 1171961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1172961acdeaSSudarsana Reddy Kalluru { 1173f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1174961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 1175f29ffdb6SMintz, Yuval int rc = 0; 1176961acdeaSSudarsana Reddy Kalluru 1177961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1178961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 1179961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 1180961acdeaSSudarsana Reddy Kalluru 1181961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1182961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1183961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1184961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 1185961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 1186961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1187961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1188961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1189961acdeaSSudarsana Reddy Kalluru } 1190961acdeaSSudarsana Reddy Kalluru return 0; 1191961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1192961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1193961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1194961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1195961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 1196961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1197961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1198961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1199961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 1200961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1201961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1202961acdeaSSudarsana Reddy Kalluru } else { 1203961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1204961acdeaSSudarsana Reddy Kalluru } 1205961acdeaSSudarsana Reddy Kalluru break; 1206961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1207961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1208961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1209961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1210961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 1211961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1212961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1213961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1214961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 1215961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1216961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1217961acdeaSSudarsana Reddy Kalluru } else { 1218961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1219961acdeaSSudarsana Reddy Kalluru } 1220961acdeaSSudarsana Reddy Kalluru break; 1221961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1222961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1223961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 1224961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 1225961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1226961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1227961acdeaSSudarsana Reddy Kalluru } 1228961acdeaSSudarsana Reddy Kalluru return 0; 1229961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1230961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1231961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1232961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1233961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1234961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1235961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1236961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1237961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1238961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1239961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1240961acdeaSSudarsana Reddy Kalluru if (info->data) { 1241961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1242961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1243961acdeaSSudarsana Reddy Kalluru } 1244961acdeaSSudarsana Reddy Kalluru return 0; 1245961acdeaSSudarsana Reddy Kalluru default: 1246961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1247961acdeaSSudarsana Reddy Kalluru } 1248961acdeaSSudarsana Reddy Kalluru 1249961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1250f29ffdb6SMintz, Yuval if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) 1251961acdeaSSudarsana Reddy Kalluru return 0; 1252961acdeaSSudarsana Reddy Kalluru 1253961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1254f29ffdb6SMintz, Yuval edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); 1255961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1256961acdeaSSudarsana Reddy Kalluru 1257961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1258f29ffdb6SMintz, Yuval __qede_lock(edev); 1259f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1260f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1261f29ffdb6SMintz, Yuval if (!vport_update_params) { 1262f29ffdb6SMintz, Yuval __qede_unlock(edev); 1263f29ffdb6SMintz, Yuval return -ENOMEM; 1264961acdeaSSudarsana Reddy Kalluru } 1265f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1266f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1267f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1268f29ffdb6SMintz, Yuval vfree(vport_update_params); 1269f29ffdb6SMintz, Yuval } 1270f29ffdb6SMintz, Yuval __qede_unlock(edev); 1271961acdeaSSudarsana Reddy Kalluru 1272f29ffdb6SMintz, Yuval return rc; 1273961acdeaSSudarsana Reddy Kalluru } 1274961acdeaSSudarsana Reddy Kalluru 1275961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1276961acdeaSSudarsana Reddy Kalluru { 1277961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 12783f2a2b8bSChopra, Manish int rc; 1279961acdeaSSudarsana Reddy Kalluru 1280961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1281961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 12823f2a2b8bSChopra, Manish rc = qede_set_rss_flags(edev, info); 12833f2a2b8bSChopra, Manish break; 12843f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLINS: 12853f2a2b8bSChopra, Manish rc = qede_add_cls_rule(edev, info); 12863f2a2b8bSChopra, Manish break; 12873f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLDEL: 12882ce9c93eSManish Chopra rc = qede_delete_flow_filter(edev, info->fs.location); 12893f2a2b8bSChopra, Manish break; 1290961acdeaSSudarsana Reddy Kalluru default: 1291961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 12923f2a2b8bSChopra, Manish rc = -EOPNOTSUPP; 1293961acdeaSSudarsana Reddy Kalluru } 12943f2a2b8bSChopra, Manish 12953f2a2b8bSChopra, Manish return rc; 1296961acdeaSSudarsana Reddy Kalluru } 1297961acdeaSSudarsana Reddy Kalluru 1298961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1299961acdeaSSudarsana Reddy Kalluru { 1300961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1301961acdeaSSudarsana Reddy Kalluru } 1302961acdeaSSudarsana Reddy Kalluru 1303961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1304961acdeaSSudarsana Reddy Kalluru { 1305961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1306961acdeaSSudarsana Reddy Kalluru 1307f29ffdb6SMintz, Yuval return sizeof(edev->rss_key); 1308961acdeaSSudarsana Reddy Kalluru } 1309961acdeaSSudarsana Reddy Kalluru 1310961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1311961acdeaSSudarsana Reddy Kalluru { 1312961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1313961acdeaSSudarsana Reddy Kalluru int i; 1314961acdeaSSudarsana Reddy Kalluru 1315961acdeaSSudarsana Reddy Kalluru if (hfunc) 1316961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1317961acdeaSSudarsana Reddy Kalluru 1318961acdeaSSudarsana Reddy Kalluru if (!indir) 1319961acdeaSSudarsana Reddy Kalluru return 0; 1320961acdeaSSudarsana Reddy Kalluru 1321961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1322f29ffdb6SMintz, Yuval indir[i] = edev->rss_ind_table[i]; 1323961acdeaSSudarsana Reddy Kalluru 1324961acdeaSSudarsana Reddy Kalluru if (key) 1325f29ffdb6SMintz, Yuval memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev)); 1326961acdeaSSudarsana Reddy Kalluru 1327961acdeaSSudarsana Reddy Kalluru return 0; 1328961acdeaSSudarsana Reddy Kalluru } 1329961acdeaSSudarsana Reddy Kalluru 1330961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1331961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1332961acdeaSSudarsana Reddy Kalluru { 1333f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1334961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1335f29ffdb6SMintz, Yuval int i, rc = 0; 1336961acdeaSSudarsana Reddy Kalluru 1337ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1338ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1339ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1340ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1341ba300ce3SSudarsana Reddy Kalluru } 1342ba300ce3SSudarsana Reddy Kalluru 1343961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1344961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1345961acdeaSSudarsana Reddy Kalluru 1346961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1347961acdeaSSudarsana Reddy Kalluru return 0; 1348961acdeaSSudarsana Reddy Kalluru 1349961acdeaSSudarsana Reddy Kalluru if (indir) { 1350961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1351f29ffdb6SMintz, Yuval edev->rss_ind_table[i] = indir[i]; 1352961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1353961acdeaSSudarsana Reddy Kalluru } 1354961acdeaSSudarsana Reddy Kalluru 1355961acdeaSSudarsana Reddy Kalluru if (key) { 1356f29ffdb6SMintz, Yuval memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev)); 1357961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1358961acdeaSSudarsana Reddy Kalluru } 1359961acdeaSSudarsana Reddy Kalluru 1360f29ffdb6SMintz, Yuval __qede_lock(edev); 1361f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1362f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1363f29ffdb6SMintz, Yuval if (!vport_update_params) { 1364f29ffdb6SMintz, Yuval __qede_unlock(edev); 1365f29ffdb6SMintz, Yuval return -ENOMEM; 1366961acdeaSSudarsana Reddy Kalluru } 1367f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1368f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1369f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1370f29ffdb6SMintz, Yuval vfree(vport_update_params); 1371f29ffdb6SMintz, Yuval } 1372f29ffdb6SMintz, Yuval __qede_unlock(edev); 1373961acdeaSSudarsana Reddy Kalluru 1374f29ffdb6SMintz, Yuval return rc; 1375961acdeaSSudarsana Reddy Kalluru } 1376961acdeaSSudarsana Reddy Kalluru 137716f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 137816f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 137916f46bf0SSudarsana Reddy Kalluru { 138016f46bf0SSudarsana Reddy Kalluru int i; 138116f46bf0SSudarsana Reddy Kalluru 138216f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 138316f46bf0SSudarsana Reddy Kalluru return; 138416f46bf0SSudarsana Reddy Kalluru 13859a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 138616f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 138716f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 138816f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 138916f46bf0SSudarsana Reddy Kalluru } 139016f46bf0SSudarsana Reddy Kalluru } 139116f46bf0SSudarsana Reddy Kalluru 139216f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 139316f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 139416f46bf0SSudarsana Reddy Kalluru { 139516f46bf0SSudarsana Reddy Kalluru int i; 139616f46bf0SSudarsana Reddy Kalluru 13979a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 139816f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 139916f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 140016f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 140116f46bf0SSudarsana Reddy Kalluru } 140216f46bf0SSudarsana Reddy Kalluru } 140316f46bf0SSudarsana Reddy Kalluru 140416f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 140516f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 140616f46bf0SSudarsana Reddy Kalluru { 14079a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 140816f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 140916f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 141048848a06SManish Chopra int i, idx; 141148848a06SManish Chopra u16 val; 141216f46bf0SSudarsana Reddy Kalluru 14139a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 14145e7baf0fSManish Chopra struct qede_fastpath *fp = &edev->fp_array[i]; 14155e7baf0fSManish Chopra 14165e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 14175e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 14189a4d7e86SSudarsana Reddy Kalluru break; 14199a4d7e86SSudarsana Reddy Kalluru } 14209a4d7e86SSudarsana Reddy Kalluru } 14219a4d7e86SSudarsana Reddy Kalluru 14229a4d7e86SSudarsana Reddy Kalluru if (!txq) { 14239a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 14249a4d7e86SSudarsana Reddy Kalluru return -1; 14259a4d7e86SSudarsana Reddy Kalluru } 14269a4d7e86SSudarsana Reddy Kalluru 142716f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 14285a052d62SSudarsana Reddy Kalluru idx = txq->sw_tx_prod; 1429cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = skb; 143016f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 143116f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 143216f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 143316f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1434351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 143548848a06SManish Chopra val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; 143648848a06SManish Chopra first_bd->data.bitfields |= cpu_to_le16(val); 143716f46bf0SSudarsana Reddy Kalluru 143816f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 143916f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 144016f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 144116f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 144216f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 144316f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 144416f46bf0SSudarsana Reddy Kalluru } 144516f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 144616f46bf0SSudarsana Reddy Kalluru 144716f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 144816f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 14495a052d62SSudarsana Reddy Kalluru txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; 145016f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 145148848a06SManish Chopra val = qed_chain_get_prod_idx(&txq->tx_pbl); 145248848a06SManish Chopra txq->tx_db.data.bd_prod = cpu_to_le16(val); 145316f46bf0SSudarsana Reddy Kalluru 145416f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 145516f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 145616f46bf0SSudarsana Reddy Kalluru */ 145716f46bf0SSudarsana Reddy Kalluru wmb(); 145816f46bf0SSudarsana Reddy Kalluru barrier(); 145916f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 146016f46bf0SSudarsana Reddy Kalluru 146116f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 146216f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 146316f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 146416f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 146516f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 146616f46bf0SSudarsana Reddy Kalluru */ 146716f46bf0SSudarsana Reddy Kalluru mmiowb(); 146816f46bf0SSudarsana Reddy Kalluru 146916f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 147016f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 147116f46bf0SSudarsana Reddy Kalluru break; 147216f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 147316f46bf0SSudarsana Reddy Kalluru } 147416f46bf0SSudarsana Reddy Kalluru 147516f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 147616f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 147716f46bf0SSudarsana Reddy Kalluru return -1; 147816f46bf0SSudarsana Reddy Kalluru } 147916f46bf0SSudarsana Reddy Kalluru 148016f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1481fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 148216f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 14835a052d62SSudarsana Reddy Kalluru txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; 1484cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = NULL; 148516f46bf0SSudarsana Reddy Kalluru 148616f46bf0SSudarsana Reddy Kalluru return 0; 148716f46bf0SSudarsana Reddy Kalluru } 148816f46bf0SSudarsana Reddy Kalluru 148916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 149016f46bf0SSudarsana Reddy Kalluru { 149116f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 149216f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 14939a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 149416f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 149516f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1496afe981d6SSudarsana Reddy Kalluru int i, iter, rc = 0; 149716f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 149816f46bf0SSudarsana Reddy Kalluru 14999a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 15009a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 15019a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 15029a4d7e86SSudarsana Reddy Kalluru break; 15039a4d7e86SSudarsana Reddy Kalluru } 15049a4d7e86SSudarsana Reddy Kalluru } 15059a4d7e86SSudarsana Reddy Kalluru 15069a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 15079a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 15089a4d7e86SSudarsana Reddy Kalluru return -1; 15099a4d7e86SSudarsana Reddy Kalluru } 15109a4d7e86SSudarsana Reddy Kalluru 151116f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 151216f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 151316f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 151416f46bf0SSudarsana Reddy Kalluru */ 1515afe981d6SSudarsana Reddy Kalluru for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { 151616f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1517837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1518837d4eb6SSudarsana Reddy Kalluru continue; 151916f46bf0SSudarsana Reddy Kalluru } 152016f46bf0SSudarsana Reddy Kalluru 152116f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 152216f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 152316f46bf0SSudarsana Reddy Kalluru 1524837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1525837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1526837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1527837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1528837d4eb6SSudarsana Reddy Kalluru * CQE. 152916f46bf0SSudarsana Reddy Kalluru */ 153016f46bf0SSudarsana Reddy Kalluru rmb(); 153116f46bf0SSudarsana Reddy Kalluru 153216f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 153316f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 153416f46bf0SSudarsana Reddy Kalluru 153516f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 153616f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 153716f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 153816f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 153916f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 154016f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1541837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 15428a863397SManish Chopra sw_rx_data->page_offset + 15438a863397SManish Chopra rxq->rx_headroom); 1544837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1545837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1546837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 154716f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 154816f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1549837d4eb6SSudarsana Reddy Kalluru rc = -1; 1550837d4eb6SSudarsana Reddy Kalluru break; 155116f46bf0SSudarsana Reddy Kalluru } 155216f46bf0SSudarsana Reddy Kalluru 15539eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1554837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1555837d4eb6SSudarsana Reddy Kalluru break; 1556837d4eb6SSudarsana Reddy Kalluru } 155716f46bf0SSudarsana Reddy Kalluru 1558837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 15599eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1560837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1561837d4eb6SSudarsana Reddy Kalluru } 1562837d4eb6SSudarsana Reddy Kalluru 1563afe981d6SSudarsana Reddy Kalluru if (iter == QEDE_SELFTEST_POLL_COUNT) { 1564837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1565837d4eb6SSudarsana Reddy Kalluru return -1; 1566837d4eb6SSudarsana Reddy Kalluru } 1567837d4eb6SSudarsana Reddy Kalluru 1568837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1569837d4eb6SSudarsana Reddy Kalluru 1570837d4eb6SSudarsana Reddy Kalluru return rc; 157116f46bf0SSudarsana Reddy Kalluru } 157216f46bf0SSudarsana Reddy Kalluru 157316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 157416f46bf0SSudarsana Reddy Kalluru { 157516f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 157616f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 157716f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 157816f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 157916f46bf0SSudarsana Reddy Kalluru u8 *packet; 158016f46bf0SSudarsana Reddy Kalluru 158116f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 158216f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 158316f46bf0SSudarsana Reddy Kalluru return -EINVAL; 158416f46bf0SSudarsana Reddy Kalluru } 158516f46bf0SSudarsana Reddy Kalluru 158616f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 158716f46bf0SSudarsana Reddy Kalluru 158816f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 158916f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 159016f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 159116f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 159216f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 159316f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 159416f46bf0SSudarsana Reddy Kalluru 159516f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 159616f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 159716f46bf0SSudarsana Reddy Kalluru 159816f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 159916f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 160016f46bf0SSudarsana Reddy Kalluru 160116f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 160216f46bf0SSudarsana Reddy Kalluru if (!skb) { 160316f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 160416f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 160516f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 160616f46bf0SSudarsana Reddy Kalluru } 160716f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 160816f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 160916f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 161016f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 161116f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 161216f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 161316f46bf0SSudarsana Reddy Kalluru 161416f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 161516f46bf0SSudarsana Reddy Kalluru if (rc) 161616f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 161716f46bf0SSudarsana Reddy Kalluru 161816f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 161916f46bf0SSudarsana Reddy Kalluru if (rc) 162016f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 162116f46bf0SSudarsana Reddy Kalluru 162216f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 162316f46bf0SSudarsana Reddy Kalluru 162416f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 162516f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 162616f46bf0SSudarsana Reddy Kalluru 162716f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 162816f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 162916f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 163016f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 163116f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 163216f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 163316f46bf0SSudarsana Reddy Kalluru 163416f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 163516f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 163616f46bf0SSudarsana Reddy Kalluru 163716f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 163816f46bf0SSudarsana Reddy Kalluru 163916f46bf0SSudarsana Reddy Kalluru return rc; 164016f46bf0SSudarsana Reddy Kalluru } 164116f46bf0SSudarsana Reddy Kalluru 16423044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 16433044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 16443044a02eSSudarsana Reddy Kalluru { 16453044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 16463044a02eSSudarsana Reddy Kalluru 16473044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 16483044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 16493044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 16503044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 16513044a02eSSudarsana Reddy Kalluru 16523044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 16533044a02eSSudarsana Reddy Kalluru 165416f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 165516f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 165616f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 165716f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 165816f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 165916f46bf0SSudarsana Reddy Kalluru } 166016f46bf0SSudarsana Reddy Kalluru } 166116f46bf0SSudarsana Reddy Kalluru 16623044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 16633044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 16643044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 16653044a02eSSudarsana Reddy Kalluru } 16663044a02eSSudarsana Reddy Kalluru 16673044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 16683044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 16693044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 16703044a02eSSudarsana Reddy Kalluru } 16713044a02eSSudarsana Reddy Kalluru 16723044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 16733044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 16743044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 16753044a02eSSudarsana Reddy Kalluru } 16763044a02eSSudarsana Reddy Kalluru 16773044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 16783044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 16793044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 16803044a02eSSudarsana Reddy Kalluru } 16817a4b21b7SMintz, Yuval 16827a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 16837a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 16847a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 16857a4b21b7SMintz, Yuval } 16863044a02eSSudarsana Reddy Kalluru } 16873044a02eSSudarsana Reddy Kalluru 16883d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 16893d789994SManish Chopra const struct ethtool_tunable *tuna, 16903d789994SManish Chopra const void *data) 16913d789994SManish Chopra { 16923d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 16933d789994SManish Chopra u32 val; 16943d789994SManish Chopra 16953d789994SManish Chopra switch (tuna->id) { 16963d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 16973d789994SManish Chopra val = *(u32 *)data; 16983d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 16993d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 17003d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 17013d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 17023d789994SManish Chopra return -EINVAL; 17033d789994SManish Chopra } 17043d789994SManish Chopra 17053d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 17063d789994SManish Chopra break; 17073d789994SManish Chopra default: 17083d789994SManish Chopra return -EOPNOTSUPP; 17093d789994SManish Chopra } 17103d789994SManish Chopra 17113d789994SManish Chopra return 0; 17123d789994SManish Chopra } 17133d789994SManish Chopra 17143d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 17153d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 17163d789994SManish Chopra { 17173d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 17183d789994SManish Chopra 17193d789994SManish Chopra switch (tuna->id) { 17203d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 17213d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 17223d789994SManish Chopra break; 17233d789994SManish Chopra default: 17243d789994SManish Chopra return -EOPNOTSUPP; 17253d789994SManish Chopra } 17263d789994SManish Chopra 17273d789994SManish Chopra return 0; 17283d789994SManish Chopra } 17293d789994SManish Chopra 1730c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata) 1731c3dc48f7SSudarsana Reddy Kalluru { 1732c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1733c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1734c3dc48f7SSudarsana Reddy Kalluru 1735c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1736c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1737c3dc48f7SSudarsana Reddy Kalluru 1738c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1739c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1740c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1741c3dc48f7SSudarsana Reddy Kalluru } 1742c3dc48f7SSudarsana Reddy Kalluru 1743c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_1G_ADV) 1744c3dc48f7SSudarsana Reddy Kalluru edata->advertised = ADVERTISED_1000baseT_Full; 1745c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_10G_ADV) 1746c3dc48f7SSudarsana Reddy Kalluru edata->advertised |= ADVERTISED_10000baseT_Full; 1747c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_1G_ADV) 1748c3dc48f7SSudarsana Reddy Kalluru edata->supported = ADVERTISED_1000baseT_Full; 1749c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_10G_ADV) 1750c3dc48f7SSudarsana Reddy Kalluru edata->supported |= ADVERTISED_10000baseT_Full; 1751c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV) 1752c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised = ADVERTISED_1000baseT_Full; 1753c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV) 1754c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised |= ADVERTISED_10000baseT_Full; 1755c3dc48f7SSudarsana Reddy Kalluru 1756c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_timer = current_link.eee.tx_lpi_timer; 1757c3dc48f7SSudarsana Reddy Kalluru edata->eee_enabled = current_link.eee.enable; 1758c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable; 1759c3dc48f7SSudarsana Reddy Kalluru edata->eee_active = current_link.eee_active; 1760c3dc48f7SSudarsana Reddy Kalluru 1761c3dc48f7SSudarsana Reddy Kalluru return 0; 1762c3dc48f7SSudarsana Reddy Kalluru } 1763c3dc48f7SSudarsana Reddy Kalluru 1764c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata) 1765c3dc48f7SSudarsana Reddy Kalluru { 1766c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1767c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1768c3dc48f7SSudarsana Reddy Kalluru struct qed_link_params params; 1769c3dc48f7SSudarsana Reddy Kalluru 1770c3dc48f7SSudarsana Reddy Kalluru if (!edev->ops->common->can_link_change(edev->cdev)) { 1771c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 1772c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1773c3dc48f7SSudarsana Reddy Kalluru } 1774c3dc48f7SSudarsana Reddy Kalluru 1775c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1776c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1777c3dc48f7SSudarsana Reddy Kalluru 1778c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1779c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1780c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1781c3dc48f7SSudarsana Reddy Kalluru } 1782c3dc48f7SSudarsana Reddy Kalluru 1783c3dc48f7SSudarsana Reddy Kalluru memset(¶ms, 0, sizeof(params)); 1784c3dc48f7SSudarsana Reddy Kalluru params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG; 1785c3dc48f7SSudarsana Reddy Kalluru 1786c3dc48f7SSudarsana Reddy Kalluru if (!(edata->advertised & (ADVERTISED_1000baseT_Full | 1787c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) || 1788c3dc48f7SSudarsana Reddy Kalluru ((edata->advertised & (ADVERTISED_1000baseT_Full | 1789c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) != 1790c3dc48f7SSudarsana Reddy Kalluru edata->advertised)) { 1791c3dc48f7SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1792c3dc48f7SSudarsana Reddy Kalluru "Invalid advertised capabilities %d\n", 1793c3dc48f7SSudarsana Reddy Kalluru edata->advertised); 1794c3dc48f7SSudarsana Reddy Kalluru return -EINVAL; 1795c3dc48f7SSudarsana Reddy Kalluru } 1796c3dc48f7SSudarsana Reddy Kalluru 1797c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_1000baseT_Full) 1798c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps = QED_EEE_1G_ADV; 1799c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_10000baseT_Full) 1800c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps |= QED_EEE_10G_ADV; 1801c3dc48f7SSudarsana Reddy Kalluru params.eee.enable = edata->eee_enabled; 1802c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_enable = edata->tx_lpi_enabled; 1803c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_timer = edata->tx_lpi_timer; 1804c3dc48f7SSudarsana Reddy Kalluru 1805c3dc48f7SSudarsana Reddy Kalluru params.link_up = true; 1806c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 1807c3dc48f7SSudarsana Reddy Kalluru 1808c3dc48f7SSudarsana Reddy Kalluru return 0; 1809c3dc48f7SSudarsana Reddy Kalluru } 1810c3dc48f7SSudarsana Reddy Kalluru 181197df0d65SSudarsana Reddy Kalluru static int qede_get_module_info(struct net_device *dev, 181297df0d65SSudarsana Reddy Kalluru struct ethtool_modinfo *modinfo) 181397df0d65SSudarsana Reddy Kalluru { 181497df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 181597df0d65SSudarsana Reddy Kalluru u8 buf[4]; 181697df0d65SSudarsana Reddy Kalluru int rc; 181797df0d65SSudarsana Reddy Kalluru 181897df0d65SSudarsana Reddy Kalluru /* Read first 4 bytes to find the sfp type */ 181997df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 182097df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 0, 4); 182197df0d65SSudarsana Reddy Kalluru if (rc) { 182297df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading EEPROM data %d\n", rc); 182397df0d65SSudarsana Reddy Kalluru return rc; 182497df0d65SSudarsana Reddy Kalluru } 182597df0d65SSudarsana Reddy Kalluru 182697df0d65SSudarsana Reddy Kalluru switch (buf[0]) { 182797df0d65SSudarsana Reddy Kalluru case 0x3: /* SFP, SFP+, SFP-28 */ 182897df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8472; 182997df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 183097df0d65SSudarsana Reddy Kalluru break; 183197df0d65SSudarsana Reddy Kalluru case 0xc: /* QSFP */ 183297df0d65SSudarsana Reddy Kalluru case 0xd: /* QSFP+ */ 183397df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8436; 183497df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; 183597df0d65SSudarsana Reddy Kalluru break; 183697df0d65SSudarsana Reddy Kalluru case 0x11: /* QSFP-28 */ 183797df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8636; 183897df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; 183997df0d65SSudarsana Reddy Kalluru break; 184097df0d65SSudarsana Reddy Kalluru default: 184197df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]); 184297df0d65SSudarsana Reddy Kalluru return -EINVAL; 184397df0d65SSudarsana Reddy Kalluru } 184497df0d65SSudarsana Reddy Kalluru 184597df0d65SSudarsana Reddy Kalluru return 0; 184697df0d65SSudarsana Reddy Kalluru } 184797df0d65SSudarsana Reddy Kalluru 184897df0d65SSudarsana Reddy Kalluru static int qede_get_module_eeprom(struct net_device *dev, 184997df0d65SSudarsana Reddy Kalluru struct ethtool_eeprom *ee, u8 *data) 185097df0d65SSudarsana Reddy Kalluru { 185197df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 185297df0d65SSudarsana Reddy Kalluru u32 start_addr = ee->offset, size = 0; 185397df0d65SSudarsana Reddy Kalluru u8 *buf = data; 185497df0d65SSudarsana Reddy Kalluru int rc = 0; 185597df0d65SSudarsana Reddy Kalluru 185697df0d65SSudarsana Reddy Kalluru /* Read A0 section */ 185797df0d65SSudarsana Reddy Kalluru if (ee->offset < ETH_MODULE_SFF_8079_LEN) { 185897df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A0 section boundary */ 185997df0d65SSudarsana Reddy Kalluru if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN) 186097df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8079_LEN - ee->offset; 186197df0d65SSudarsana Reddy Kalluru else 186297df0d65SSudarsana Reddy Kalluru size = ee->len; 186397df0d65SSudarsana Reddy Kalluru 186497df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 186597df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 186697df0d65SSudarsana Reddy Kalluru start_addr, size); 186797df0d65SSudarsana Reddy Kalluru if (rc) { 186897df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading A0 section %d\n", rc); 186997df0d65SSudarsana Reddy Kalluru return rc; 187097df0d65SSudarsana Reddy Kalluru } 187197df0d65SSudarsana Reddy Kalluru 187297df0d65SSudarsana Reddy Kalluru buf += size; 187397df0d65SSudarsana Reddy Kalluru start_addr += size; 187497df0d65SSudarsana Reddy Kalluru } 187597df0d65SSudarsana Reddy Kalluru 187697df0d65SSudarsana Reddy Kalluru /* Read A2 section */ 187797df0d65SSudarsana Reddy Kalluru if (start_addr >= ETH_MODULE_SFF_8079_LEN && 187897df0d65SSudarsana Reddy Kalluru start_addr < ETH_MODULE_SFF_8472_LEN) { 187997df0d65SSudarsana Reddy Kalluru size = ee->len - size; 188097df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A2 section boundary */ 188197df0d65SSudarsana Reddy Kalluru if (start_addr + size > ETH_MODULE_SFF_8472_LEN) 188297df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8472_LEN - start_addr; 188397df0d65SSudarsana Reddy Kalluru start_addr -= ETH_MODULE_SFF_8079_LEN; 188497df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 188597df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A2, 188697df0d65SSudarsana Reddy Kalluru start_addr, size); 188797df0d65SSudarsana Reddy Kalluru if (rc) { 188897df0d65SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 188997df0d65SSudarsana Reddy Kalluru "Failed reading A2 section %d\n", rc); 189097df0d65SSudarsana Reddy Kalluru return 0; 189197df0d65SSudarsana Reddy Kalluru } 189297df0d65SSudarsana Reddy Kalluru } 189397df0d65SSudarsana Reddy Kalluru 189497df0d65SSudarsana Reddy Kalluru return rc; 189597df0d65SSudarsana Reddy Kalluru } 189697df0d65SSudarsana Reddy Kalluru 1897133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1898054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1899054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1900133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1901e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1902e0971c83STomer Tayar .get_regs = qede_get_regs, 190314d39648SMintz, Yuval .get_wol = qede_get_wol, 190414d39648SMintz, Yuval .set_wol = qede_set_wol, 1905133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1906133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 190732a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1908133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1909d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1910d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 191101ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 191201ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 19130f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 19140f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1915133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 19163d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1917133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1918f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1919133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1920961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1921961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1922961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1923961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1924961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1925961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 19264c55215cSSudarsana Reddy Kalluru .get_ts_info = qede_get_ts_info, 19278edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 19288edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 19293044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 193097df0d65SSudarsana Reddy Kalluru .get_module_info = qede_get_module_info, 193197df0d65SSudarsana Reddy Kalluru .get_module_eeprom = qede_get_module_eeprom, 1932c3dc48f7SSudarsana Reddy Kalluru .get_eee = qede_get_eee, 1933c3dc48f7SSudarsana Reddy Kalluru .set_eee = qede_set_eee, 1934c3dc48f7SSudarsana Reddy Kalluru 19353d789994SManish Chopra .get_tunable = qede_get_tunable, 19363d789994SManish Chopra .set_tunable = qede_set_tunable, 1937ccfa110cSSudarsana Reddy Kalluru .flash_device = qede_flash_device, 1938133fac0eSSudarsana Kalluru }; 1939133fac0eSSudarsana Kalluru 1940fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1941054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1942fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1943fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1944fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1945fefb0202SYuval Mintz .get_link = qede_get_link, 1946477f2d14SRahul Verma .get_coalesce = qede_get_coalesce, 1947477f2d14SRahul Verma .set_coalesce = qede_set_coalesce, 1948fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1949fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1950fefb0202SYuval Mintz .get_strings = qede_get_strings, 1951fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1952fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1953fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1954fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1955fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1956fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1957fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1958fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1959fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1960fefb0202SYuval Mintz .get_channels = qede_get_channels, 1961fefb0202SYuval Mintz .set_channels = qede_set_channels, 19623d789994SManish Chopra .get_tunable = qede_get_tunable, 19633d789994SManish Chopra .set_tunable = qede_set_tunable, 1964fefb0202SYuval Mintz }; 1965fefb0202SYuval Mintz 1966133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1967133fac0eSSudarsana Kalluru { 1968fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1969fefb0202SYuval Mintz 1970fefb0202SYuval Mintz if (IS_VF(edev)) 1971fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1972fefb0202SYuval Mintz else 1973133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1974133fac0eSSudarsana Kalluru } 1975