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), 164133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1651a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1661a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 167133fac0eSSudarsana Kalluru 168133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 169133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 170133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 171133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 172133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 173133fac0eSSudarsana Kalluru }; 174133fac0eSSudarsana Kalluru 175133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 1769c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \ 1779c79ddaaSMintz, Yuval test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr) 1789c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \ 1799c79ddaaSMintz, Yuval test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr) 1809c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \ 1819c79ddaaSMintz, Yuval test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr) 182133fac0eSSudarsana Kalluru 183f3e72109SYuval Mintz enum { 184f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 185f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 186f3e72109SYuval Mintz }; 187f3e72109SYuval Mintz 188f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 189f3e72109SYuval Mintz "Coupled-Function", 190f3e72109SYuval Mintz }; 191f3e72109SYuval Mintz 1923044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 19316f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 1943044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 1953044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 1963044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 1973044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 1987a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 1993044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 2003044a02eSSudarsana Reddy Kalluru }; 2013044a02eSSudarsana Reddy Kalluru 2023044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 20316f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 2043044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 2053044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 2063044a02eSSudarsana Reddy Kalluru "Register (online)\t", 2073044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 2087a4b21b7SMintz, Yuval "Nvram (online)\t\t", 2093044a02eSSudarsana Reddy Kalluru }; 2103044a02eSSudarsana Reddy Kalluru 2114dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev, 2124dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf) 2134dbcd640SMintz, Yuval { 2144dbcd640SMintz, Yuval int i; 2154dbcd640SMintz, Yuval 2164dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 217cb6aeb07SMintz, Yuval if (txq->is_xdp) 218cb6aeb07SMintz, Yuval sprintf(*buf, "%d [XDP]: %s", 219cb6aeb07SMintz, Yuval QEDE_TXQ_XDP_TO_IDX(edev, txq), 220cb6aeb07SMintz, Yuval qede_tqstats_arr[i].string); 221cb6aeb07SMintz, Yuval else 2224dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", txq->index, 2234dbcd640SMintz, Yuval qede_tqstats_arr[i].string); 2244dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2254dbcd640SMintz, Yuval } 2264dbcd640SMintz, Yuval } 2274dbcd640SMintz, Yuval 2284dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev, 2294dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf) 2304dbcd640SMintz, Yuval { 2314dbcd640SMintz, Yuval int i; 2324dbcd640SMintz, Yuval 2334dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 2344dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id, 2354dbcd640SMintz, Yuval qede_rqstats_arr[i].string); 2364dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2374dbcd640SMintz, Yuval } 2384dbcd640SMintz, Yuval } 2394dbcd640SMintz, Yuval 2409c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index) 2419c79ddaaSMintz, Yuval { 2429c79ddaaSMintz, Yuval return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) || 2439c79ddaaSMintz, Yuval (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) || 2449c79ddaaSMintz, Yuval (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index)); 2459c79ddaaSMintz, Yuval } 2469c79ddaaSMintz, Yuval 247133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 248133fac0eSSudarsana Kalluru { 2494dbcd640SMintz, Yuval struct qede_fastpath *fp; 2504dbcd640SMintz, Yuval int i; 251133fac0eSSudarsana Kalluru 2524dbcd640SMintz, Yuval /* Account for queue statistics */ 2534dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 2544dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 25568db9ec2SSudarsana Reddy Kalluru 2564dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 2574dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf); 2584dbcd640SMintz, Yuval 259cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 260cb6aeb07SMintz, Yuval qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf); 261cb6aeb07SMintz, Yuval 2624dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_TX) 2634dbcd640SMintz, Yuval qede_get_strings_stats_txq(edev, fp->txq, &buf); 264cbbf049aSMintz, Yuval } 265cbbf049aSMintz, Yuval 2664dbcd640SMintz, Yuval /* Account for non-queue statistics */ 2674dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 2689c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 269fefb0202SYuval Mintz continue; 2704dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string); 2714dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN; 272133fac0eSSudarsana Kalluru } 273133fac0eSSudarsana Kalluru } 274133fac0eSSudarsana Kalluru 275133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 276133fac0eSSudarsana Kalluru { 277133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 278133fac0eSSudarsana Kalluru 279133fac0eSSudarsana Kalluru switch (stringset) { 280133fac0eSSudarsana Kalluru case ETH_SS_STATS: 281133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 282133fac0eSSudarsana Kalluru break; 283f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 284f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 285f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 286f3e72109SYuval Mintz break; 2873044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2883044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 2893044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 2903044a02eSSudarsana Reddy Kalluru break; 291133fac0eSSudarsana Kalluru default: 292133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 293133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 294133fac0eSSudarsana Kalluru } 295133fac0eSSudarsana Kalluru } 296133fac0eSSudarsana Kalluru 2974dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) 2984dbcd640SMintz, Yuval { 2994dbcd640SMintz, Yuval int i; 3004dbcd640SMintz, Yuval 3014dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 3024dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); 3034dbcd640SMintz, Yuval (*buf)++; 3044dbcd640SMintz, Yuval } 3054dbcd640SMintz, Yuval } 3064dbcd640SMintz, Yuval 3074dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) 3084dbcd640SMintz, Yuval { 3094dbcd640SMintz, Yuval int i; 3104dbcd640SMintz, Yuval 3114dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 3124dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); 3134dbcd640SMintz, Yuval (*buf)++; 3144dbcd640SMintz, Yuval } 3154dbcd640SMintz, Yuval } 3164dbcd640SMintz, Yuval 317133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 318133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 319133fac0eSSudarsana Kalluru { 320133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3214dbcd640SMintz, Yuval struct qede_fastpath *fp; 3224dbcd640SMintz, Yuval int i; 323133fac0eSSudarsana Kalluru 324133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 325133fac0eSSudarsana Kalluru 326567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */ 327567b3c12SMintz, Yuval __qede_lock(edev); 328567b3c12SMintz, Yuval 3294dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 3304dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 331133fac0eSSudarsana Kalluru 3324dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 3334dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf); 33468db9ec2SSudarsana Reddy Kalluru 335cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 336cb6aeb07SMintz, Yuval qede_get_ethtool_stats_txq(fp->xdp_tx, &buf); 337cb6aeb07SMintz, Yuval 3384dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_TX) 3394dbcd640SMintz, Yuval qede_get_ethtool_stats_txq(fp->txq, &buf); 34068db9ec2SSudarsana Reddy Kalluru } 34168db9ec2SSudarsana Reddy Kalluru 3424dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 3439c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 344fefb0202SYuval Mintz continue; 3454dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) + 3464dbcd640SMintz, Yuval qede_stats_arr[i].offset)); 3474dbcd640SMintz, Yuval 3484dbcd640SMintz, Yuval buf++; 349fefb0202SYuval Mintz } 350133fac0eSSudarsana Kalluru 351567b3c12SMintz, Yuval __qede_unlock(edev); 352133fac0eSSudarsana Kalluru } 353133fac0eSSudarsana Kalluru 354133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 355133fac0eSSudarsana Kalluru { 356133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3579c79ddaaSMintz, Yuval int num_stats = QEDE_NUM_STATS, i; 358133fac0eSSudarsana Kalluru 359133fac0eSSudarsana Kalluru switch (stringset) { 360133fac0eSSudarsana Kalluru case ETH_SS_STATS: 361fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 3629c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 363fefb0202SYuval Mintz num_stats--; 3644dbcd640SMintz, Yuval 3654dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */ 3664dbcd640SMintz, Yuval num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS; 3674dbcd640SMintz, Yuval 3684dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */ 3694dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; 3704dbcd640SMintz, Yuval 371cb6aeb07SMintz, Yuval /* Account for XDP statistics [if needed] */ 372cb6aeb07SMintz, Yuval if (edev->xdp_prog) 373cb6aeb07SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; 3744dbcd640SMintz, Yuval return num_stats; 3754dbcd640SMintz, Yuval 376f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 377f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 3783044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 3796ecb0a0cSYuval Mintz if (!IS_VF(edev)) 3803044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 3816ecb0a0cSYuval Mintz else 3826ecb0a0cSYuval Mintz return 0; 383133fac0eSSudarsana Kalluru default: 384133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 385133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 386133fac0eSSudarsana Kalluru return -EINVAL; 387133fac0eSSudarsana Kalluru } 388133fac0eSSudarsana Kalluru } 389133fac0eSSudarsana Kalluru 390f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 391f3e72109SYuval Mintz { 392f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 393f3e72109SYuval Mintz 394f3e72109SYuval Mintz return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; 395f3e72109SYuval Mintz } 396f3e72109SYuval Mintz 397054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 398054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 399054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 400054c67d1SSudarsana Reddy Kalluru }; 401054c67d1SSudarsana Reddy Kalluru 402054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 403054c67d1SSudarsana Reddy Kalluru {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, 404054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 405054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 406054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 407054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT}, 408054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 409054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 410054c67d1SSudarsana Reddy Kalluru {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 411054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 412054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 413054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 414054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 415054c67d1SSudarsana Reddy Kalluru }; 416054c67d1SSudarsana Reddy Kalluru 417054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 418054c67d1SSudarsana Reddy Kalluru { \ 419054c67d1SSudarsana Reddy Kalluru int i; \ 420054c67d1SSudarsana Reddy Kalluru \ 421d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 422054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 423054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 424054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 425054c67d1SSudarsana Reddy Kalluru } \ 426054c67d1SSudarsana Reddy Kalluru } 427054c67d1SSudarsana Reddy Kalluru 428054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 429054c67d1SSudarsana Reddy Kalluru { \ 430054c67d1SSudarsana Reddy Kalluru int i; \ 431054c67d1SSudarsana Reddy Kalluru \ 432d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 433054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 434054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 435054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 436054c67d1SSudarsana Reddy Kalluru } \ 437054c67d1SSudarsana Reddy Kalluru } 438054c67d1SSudarsana Reddy Kalluru 439054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 440054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 441133fac0eSSudarsana Kalluru { 442054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 443133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 444133fac0eSSudarsana Kalluru struct qed_link_output current_link; 445133fac0eSSudarsana Kalluru 446567b3c12SMintz, Yuval __qede_lock(edev); 447567b3c12SMintz, Yuval 448133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 449133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 450133fac0eSSudarsana Kalluru 451054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 452054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 453054c67d1SSudarsana Reddy Kalluru 454054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 455054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 456054c67d1SSudarsana Reddy Kalluru 457054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 458054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 459054c67d1SSudarsana Reddy Kalluru 460133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 461054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 462054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 463133fac0eSSudarsana Kalluru } else { 464054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 465054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 466133fac0eSSudarsana Kalluru } 467567b3c12SMintz, Yuval 468567b3c12SMintz, Yuval __qede_unlock(edev); 469567b3c12SMintz, Yuval 470054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 471054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 472133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 473133fac0eSSudarsana Kalluru 474133fac0eSSudarsana Kalluru return 0; 475133fac0eSSudarsana Kalluru } 476133fac0eSSudarsana Kalluru 477054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 478054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 479133fac0eSSudarsana Kalluru { 480054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 481133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 482133fac0eSSudarsana Kalluru struct qed_link_output current_link; 483133fac0eSSudarsana Kalluru struct qed_link_params params; 484133fac0eSSudarsana Kalluru 485fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 486054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 487133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 488133fac0eSSudarsana Kalluru } 489133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 490133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 491133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 492133fac0eSSudarsana Kalluru 493133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 494133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 495054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 496161adb04Ssudarsana.kalluru@cavium.com if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 497161adb04Ssudarsana.kalluru@cavium.com DP_INFO(edev, "Auto negotiation is not supported\n"); 498161adb04Ssudarsana.kalluru@cavium.com return -EOPNOTSUPP; 499161adb04Ssudarsana.kalluru@cavium.com } 500161adb04Ssudarsana.kalluru@cavium.com 501133fac0eSSudarsana Kalluru params.autoneg = true; 502133fac0eSSudarsana Kalluru params.forced_speed = 0; 503054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 504133fac0eSSudarsana Kalluru } else { /* forced speed */ 505133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 506133fac0eSSudarsana Kalluru params.autoneg = false; 507054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 508054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 5099ac4c546SSudarsana Reddy Kalluru case SPEED_1000: 5109ac4c546SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 5119ac4c546SSudarsana Reddy Kalluru QED_LM_1000baseT_Full_BIT)) { 5129ac4c546SSudarsana Reddy Kalluru DP_INFO(edev, "1G speed not supported\n"); 5139ac4c546SSudarsana Reddy Kalluru return -EINVAL; 5149ac4c546SSudarsana Reddy Kalluru } 5159ac4c546SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_1000baseT_Full_BIT; 5169ac4c546SSudarsana Reddy Kalluru break; 517133fac0eSSudarsana Kalluru case SPEED_10000: 518133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 519054c67d1SSudarsana Reddy Kalluru QED_LM_10000baseKR_Full_BIT)) { 520133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 521133fac0eSSudarsana Kalluru return -EINVAL; 522133fac0eSSudarsana Kalluru } 523054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_10000baseKR_Full_BIT; 524054c67d1SSudarsana Reddy Kalluru break; 525054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 526054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 527054c67d1SSudarsana Reddy Kalluru QED_LM_25000baseKR_Full_BIT)) { 528054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 529054c67d1SSudarsana Reddy Kalluru return -EINVAL; 530054c67d1SSudarsana Reddy Kalluru } 531054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_25000baseKR_Full_BIT; 532133fac0eSSudarsana Kalluru break; 533133fac0eSSudarsana Kalluru case SPEED_40000: 534133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 535054c67d1SSudarsana Reddy Kalluru QED_LM_40000baseLR4_Full_BIT)) { 536133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 537133fac0eSSudarsana Kalluru return -EINVAL; 538133fac0eSSudarsana Kalluru } 539054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_40000baseLR4_Full_BIT; 540054c67d1SSudarsana Reddy Kalluru break; 54116d5946aSYuval Mintz case SPEED_50000: 542054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 543054c67d1SSudarsana Reddy Kalluru QED_LM_50000baseKR2_Full_BIT)) { 544054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 545054c67d1SSudarsana Reddy Kalluru return -EINVAL; 546054c67d1SSudarsana Reddy Kalluru } 547054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_50000baseKR2_Full_BIT; 548054c67d1SSudarsana Reddy Kalluru break; 54916d5946aSYuval Mintz case SPEED_100000: 550054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 551054c67d1SSudarsana Reddy Kalluru QED_LM_100000baseKR4_Full_BIT)) { 552054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 553054c67d1SSudarsana Reddy Kalluru return -EINVAL; 554054c67d1SSudarsana Reddy Kalluru } 555054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_100000baseKR4_Full_BIT; 556133fac0eSSudarsana Kalluru break; 557133fac0eSSudarsana Kalluru default: 558054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 559133fac0eSSudarsana Kalluru return -EINVAL; 560133fac0eSSudarsana Kalluru } 561133fac0eSSudarsana Kalluru } 562133fac0eSSudarsana Kalluru 563133fac0eSSudarsana Kalluru params.link_up = true; 564133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 565133fac0eSSudarsana Kalluru 566133fac0eSSudarsana Kalluru return 0; 567133fac0eSSudarsana Kalluru } 568133fac0eSSudarsana Kalluru 569133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 570133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 571133fac0eSSudarsana Kalluru { 572133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 573133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 574133fac0eSSudarsana Kalluru 575133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 576133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 577133fac0eSSudarsana Kalluru 578133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 579133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 580133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 581133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 582133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 583133fac0eSSudarsana Kalluru 584133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 585133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 586133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 587133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 588133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 589133fac0eSSudarsana Kalluru 590133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 591133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 592133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 593133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 594133fac0eSSudarsana Kalluru } else { 595133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 596133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 597133fac0eSSudarsana Kalluru } 598133fac0eSSudarsana Kalluru 599133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 600133fac0eSSudarsana Kalluru } 601133fac0eSSudarsana Kalluru 60214d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 60314d39648SMintz, Yuval { 60414d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 60514d39648SMintz, Yuval 60614d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 60714d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 60814d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 60914d39648SMintz, Yuval } 61014d39648SMintz, Yuval } 61114d39648SMintz, Yuval 61214d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 61314d39648SMintz, Yuval { 61414d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 61514d39648SMintz, Yuval bool wol_requested; 61614d39648SMintz, Yuval int rc; 61714d39648SMintz, Yuval 61814d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 61914d39648SMintz, Yuval DP_INFO(edev, 62014d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 62114d39648SMintz, Yuval return -EINVAL; 62214d39648SMintz, Yuval } 62314d39648SMintz, Yuval 62414d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 62514d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 62614d39648SMintz, Yuval return 0; 62714d39648SMintz, Yuval 62814d39648SMintz, Yuval /* Need to actually change configuration */ 62914d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 63014d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 63114d39648SMintz, Yuval return -EINVAL; 63214d39648SMintz, Yuval } 63314d39648SMintz, Yuval 63414d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 63514d39648SMintz, Yuval if (!rc) 63614d39648SMintz, Yuval edev->wol_enabled = wol_requested; 63714d39648SMintz, Yuval 63814d39648SMintz, Yuval return rc; 63914d39648SMintz, Yuval } 64014d39648SMintz, Yuval 641133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 642133fac0eSSudarsana Kalluru { 643133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 644133fac0eSSudarsana Kalluru 6451a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 646133fac0eSSudarsana Kalluru } 647133fac0eSSudarsana Kalluru 648133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 649133fac0eSSudarsana Kalluru { 650133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 651133fac0eSSudarsana Kalluru u32 dp_module = 0; 652133fac0eSSudarsana Kalluru u8 dp_level = 0; 653133fac0eSSudarsana Kalluru 654133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 655133fac0eSSudarsana Kalluru 656133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 657133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 658133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 659133fac0eSSudarsana Kalluru dp_module, dp_level); 660133fac0eSSudarsana Kalluru } 661133fac0eSSudarsana Kalluru 66232a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 66332a7a570SSudarsana Kalluru { 66432a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 66532a7a570SSudarsana Kalluru struct qed_link_output current_link; 66632a7a570SSudarsana Kalluru struct qed_link_params link_params; 66732a7a570SSudarsana Kalluru 668fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 6691a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 670fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 671fe7cd2bfSYuval Mintz } 672fe7cd2bfSYuval Mintz 67332a7a570SSudarsana Kalluru if (!netif_running(dev)) 67432a7a570SSudarsana Kalluru return 0; 67532a7a570SSudarsana Kalluru 67632a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 67732a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 67832a7a570SSudarsana Kalluru if (!current_link.link_up) 67932a7a570SSudarsana Kalluru return 0; 68032a7a570SSudarsana Kalluru 68132a7a570SSudarsana Kalluru /* Toggle the link */ 68232a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 68332a7a570SSudarsana Kalluru link_params.link_up = false; 68432a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 68532a7a570SSudarsana Kalluru link_params.link_up = true; 68632a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 68732a7a570SSudarsana Kalluru 68832a7a570SSudarsana Kalluru return 0; 68932a7a570SSudarsana Kalluru } 69032a7a570SSudarsana Kalluru 691133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 692133fac0eSSudarsana Kalluru { 693133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 694133fac0eSSudarsana Kalluru struct qed_link_output current_link; 695133fac0eSSudarsana Kalluru 696133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 697133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 698133fac0eSSudarsana Kalluru 699133fac0eSSudarsana Kalluru return current_link.link_up; 700133fac0eSSudarsana Kalluru } 701133fac0eSSudarsana Kalluru 702d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 703d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 704d552fa84SSudarsana Reddy Kalluru { 705d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 706d2890deaSSudarsana Reddy Kalluru u16 rxc, txc; 707d552fa84SSudarsana Reddy Kalluru 708d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 709d2890deaSSudarsana Reddy Kalluru edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc); 710d2890deaSSudarsana Reddy Kalluru 711d2890deaSSudarsana Reddy Kalluru coal->rx_coalesce_usecs = rxc; 712d2890deaSSudarsana Reddy Kalluru coal->tx_coalesce_usecs = txc; 713d552fa84SSudarsana Reddy Kalluru 714d552fa84SSudarsana Reddy Kalluru return 0; 715d552fa84SSudarsana Reddy Kalluru } 716d552fa84SSudarsana Reddy Kalluru 717d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 718d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 719d552fa84SSudarsana Reddy Kalluru { 720d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 721d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 722f870a3c6Ssudarsana.kalluru@cavium.com u16 rxc, txc, sb_id; 723d552fa84SSudarsana Reddy Kalluru 724d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 725d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 726d552fa84SSudarsana Reddy Kalluru return -EINVAL; 727d552fa84SSudarsana Reddy Kalluru } 728d552fa84SSudarsana Reddy Kalluru 729d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 730d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 731d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 732d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 733d552fa84SSudarsana Reddy Kalluru coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" 734d552fa84SSudarsana Reddy Kalluru : "tx", 735d552fa84SSudarsana Reddy Kalluru QED_COALESCE_MAX); 736d552fa84SSudarsana Reddy Kalluru return -EINVAL; 737d552fa84SSudarsana Reddy Kalluru } 738d552fa84SSudarsana Reddy Kalluru 739d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 740d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 7419a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 742d552fa84SSudarsana Reddy Kalluru sb_id = edev->fp_array[i].sb_info->igu_sb_id; 743d552fa84SSudarsana Reddy Kalluru rc = edev->ops->common->set_coalesce(edev->cdev, rxc, txc, 744f870a3c6Ssudarsana.kalluru@cavium.com (u16)i, sb_id); 745d552fa84SSudarsana Reddy Kalluru if (rc) { 746d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Set coalesce error, rc = %d\n", rc); 747d552fa84SSudarsana Reddy Kalluru return rc; 748d552fa84SSudarsana Reddy Kalluru } 749d552fa84SSudarsana Reddy Kalluru } 750d552fa84SSudarsana Reddy Kalluru 751d552fa84SSudarsana Reddy Kalluru return rc; 752d552fa84SSudarsana Reddy Kalluru } 753d552fa84SSudarsana Reddy Kalluru 75401ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 75501ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 75601ef7e05SSudarsana Kalluru { 75701ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 75801ef7e05SSudarsana Kalluru 75901ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 76001ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 76101ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 76201ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 76301ef7e05SSudarsana Kalluru } 76401ef7e05SSudarsana Kalluru 76501ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 76601ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 76701ef7e05SSudarsana Kalluru { 76801ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 76901ef7e05SSudarsana Kalluru 77001ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 77101ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 77201ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 77301ef7e05SSudarsana Kalluru 77401ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 77501ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 77601ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 77701ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 77801ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 77901ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 78001ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 78101ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 78201ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 78301ef7e05SSudarsana Kalluru return -EINVAL; 78401ef7e05SSudarsana Kalluru } 78501ef7e05SSudarsana Kalluru 78601ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 78701ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 78801ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 78901ef7e05SSudarsana Kalluru 790567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 79101ef7e05SSudarsana Kalluru 79201ef7e05SSudarsana Kalluru return 0; 79301ef7e05SSudarsana Kalluru } 79401ef7e05SSudarsana Kalluru 7950f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 7960f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 7970f7db144SSudarsana Kalluru { 7980f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7990f7db144SSudarsana Kalluru struct qed_link_output current_link; 8000f7db144SSudarsana Kalluru 8010f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 8020f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 8030f7db144SSudarsana Kalluru 8040f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 8050f7db144SSudarsana Kalluru epause->autoneg = true; 8060f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 8070f7db144SSudarsana Kalluru epause->rx_pause = true; 8080f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 8090f7db144SSudarsana Kalluru epause->tx_pause = true; 8100f7db144SSudarsana Kalluru 8110f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 8120f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 8130f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 8140f7db144SSudarsana Kalluru epause->tx_pause); 8150f7db144SSudarsana Kalluru } 8160f7db144SSudarsana Kalluru 8170f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 8180f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 8190f7db144SSudarsana Kalluru { 8200f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8210f7db144SSudarsana Kalluru struct qed_link_params params; 8220f7db144SSudarsana Kalluru struct qed_link_output current_link; 8230f7db144SSudarsana Kalluru 824fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 8250f7db144SSudarsana Kalluru DP_INFO(edev, 826fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 8270f7db144SSudarsana Kalluru return -EOPNOTSUPP; 8280f7db144SSudarsana Kalluru } 8290f7db144SSudarsana Kalluru 8300f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 8310f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 8320f7db144SSudarsana Kalluru 8330f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 8340f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 8350f7db144SSudarsana Kalluru if (epause->autoneg) { 836d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 8370f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 8380f7db144SSudarsana Kalluru return -EINVAL; 8390f7db144SSudarsana Kalluru } 8400f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 8410f7db144SSudarsana Kalluru } 8420f7db144SSudarsana Kalluru if (epause->rx_pause) 8430f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 8440f7db144SSudarsana Kalluru if (epause->tx_pause) 8450f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 8460f7db144SSudarsana Kalluru 8470f7db144SSudarsana Kalluru params.link_up = true; 8480f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 8490f7db144SSudarsana Kalluru 8500f7db144SSudarsana Kalluru return 0; 8510f7db144SSudarsana Kalluru } 8520f7db144SSudarsana Kalluru 853e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 854e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 855e0971c83STomer Tayar { 856e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 857e0971c83STomer Tayar 858e0971c83STomer Tayar regs->version = 0; 859e0971c83STomer Tayar memset(buffer, 0, regs->len); 860e0971c83STomer Tayar 861e0971c83STomer Tayar if (edev->ops && edev->ops->common) 862e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 863e0971c83STomer Tayar } 864e0971c83STomer Tayar 865e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 866e0971c83STomer Tayar { 867e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 868e0971c83STomer Tayar 869e0971c83STomer Tayar if (edev->ops && edev->ops->common) 870e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 871e0971c83STomer Tayar else 872e0971c83STomer Tayar return -EINVAL; 873e0971c83STomer Tayar } 874e0971c83STomer Tayar 875567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev, 876567b3c12SMintz, Yuval struct qede_reload_args *args) 877133fac0eSSudarsana Kalluru { 878567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu; 879133fac0eSSudarsana Kalluru } 880133fac0eSSudarsana Kalluru 881133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 882133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 883133fac0eSSudarsana Kalluru { 884133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 885567b3c12SMintz, Yuval struct qede_reload_args args; 886133fac0eSSudarsana Kalluru 887133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 888133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 889133fac0eSSudarsana Kalluru 890133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */ 891567b3c12SMintz, Yuval args.u.mtu = new_mtu; 892567b3c12SMintz, Yuval args.func = &qede_update_mtu; 893567b3c12SMintz, Yuval qede_reload(edev, &args, false); 894133fac0eSSudarsana Kalluru 895567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu); 8960fefbfbaSSudarsana Kalluru 897133fac0eSSudarsana Kalluru return 0; 898133fac0eSSudarsana Kalluru } 899133fac0eSSudarsana Kalluru 9008edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 9018edf049dSSudarsana Kalluru struct ethtool_channels *channels) 9028edf049dSSudarsana Kalluru { 9038edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9048edf049dSSudarsana Kalluru 9058edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 906bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 907bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 9089a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 9099a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 9109a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 9119a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 9128edf049dSSudarsana Kalluru } 9138edf049dSSudarsana Kalluru 9148edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 9158edf049dSSudarsana Kalluru struct ethtool_channels *channels) 9168edf049dSSudarsana Kalluru { 9178edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9189a4d7e86SSudarsana Reddy Kalluru u32 count; 9198edf049dSSudarsana Kalluru 9208edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9218edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 9228edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 9238edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 9248edf049dSSudarsana Kalluru 9259a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 9269a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 9279a4d7e86SSudarsana Reddy Kalluru 9289a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 9299a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 9308edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9318edf049dSSudarsana Kalluru "command parameters not supported\n"); 9328edf049dSSudarsana Kalluru return -EINVAL; 9338edf049dSSudarsana Kalluru } 9348edf049dSSudarsana Kalluru 9359a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 9369a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 9379a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9389a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 9399a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 9409a4d7e86SSudarsana Reddy Kalluru } 9419a4d7e86SSudarsana Reddy Kalluru 9429a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 9439a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9449a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 9459a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 9469a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 9479a4d7e86SSudarsana Reddy Kalluru } 9489a4d7e86SSudarsana Reddy Kalluru 9498edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 9509a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 9519a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 9529a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 9538edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9548edf049dSSudarsana Kalluru "No change in active parameters\n"); 9558edf049dSSudarsana Kalluru return 0; 9568edf049dSSudarsana Kalluru } 9578edf049dSSudarsana Kalluru 9588edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 9599a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 9609a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 9619a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 9628edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 9639a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 9648edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 9658edf049dSSudarsana Kalluru return -EINVAL; 9668edf049dSSudarsana Kalluru } 9678edf049dSSudarsana Kalluru 9688edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 9699a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 9709a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 9719a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 972ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 973ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 974ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 975f29ffdb6SMintz, Yuval memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); 976ed0dd915SSudarsana Reddy Kalluru } 977ed0dd915SSudarsana Reddy Kalluru 978567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 9798edf049dSSudarsana Kalluru 9808edf049dSSudarsana Kalluru return 0; 9818edf049dSSudarsana Kalluru } 9828edf049dSSudarsana Kalluru 9834c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev, 9844c55215cSSudarsana Reddy Kalluru struct ethtool_ts_info *info) 9854c55215cSSudarsana Reddy Kalluru { 9864c55215cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 9874c55215cSSudarsana Reddy Kalluru 9884c55215cSSudarsana Reddy Kalluru return qede_ptp_get_ts_info(edev, info); 9894c55215cSSudarsana Reddy Kalluru } 9904c55215cSSudarsana Reddy Kalluru 9913d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 9923d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 9933d971cbdSSudarsana Kalluru { 9943d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9953d971cbdSSudarsana Kalluru u8 led_state = 0; 9963d971cbdSSudarsana Kalluru 9973d971cbdSSudarsana Kalluru switch (state) { 9983d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 9993d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 10003d971cbdSSudarsana Kalluru 10013d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 10023d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 10033d971cbdSSudarsana Kalluru break; 10043d971cbdSSudarsana Kalluru 10053d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 10063d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 10073d971cbdSSudarsana Kalluru break; 10083d971cbdSSudarsana Kalluru 10093d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 10103d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 10113d971cbdSSudarsana Kalluru break; 10123d971cbdSSudarsana Kalluru } 10133d971cbdSSudarsana Kalluru 10143d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 10153d971cbdSSudarsana Kalluru 10163d971cbdSSudarsana Kalluru return 0; 10173d971cbdSSudarsana Kalluru } 10183d971cbdSSudarsana Kalluru 1019961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1020961acdeaSSudarsana Reddy Kalluru { 1021961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 1022961acdeaSSudarsana Reddy Kalluru 1023961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1024961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1025961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1026961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1027961acdeaSSudarsana Reddy Kalluru break; 1028961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1029f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV4_UDP) 1030961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1031961acdeaSSudarsana Reddy Kalluru break; 1032961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1033f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV6_UDP) 1034961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1035961acdeaSSudarsana Reddy Kalluru break; 1036961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1037961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1038961acdeaSSudarsana Reddy Kalluru break; 1039961acdeaSSudarsana Reddy Kalluru default: 1040961acdeaSSudarsana Reddy Kalluru info->data = 0; 1041961acdeaSSudarsana Reddy Kalluru break; 1042961acdeaSSudarsana Reddy Kalluru } 1043961acdeaSSudarsana Reddy Kalluru 1044961acdeaSSudarsana Reddy Kalluru return 0; 1045961acdeaSSudarsana Reddy Kalluru } 1046961acdeaSSudarsana Reddy Kalluru 1047961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 1048ec9b8dbdSChopra, Manish u32 *rule_locs) 1049961acdeaSSudarsana Reddy Kalluru { 1050961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1051ec9b8dbdSChopra, Manish int rc = 0; 1052961acdeaSSudarsana Reddy Kalluru 1053961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1054961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 10559a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 1056ec9b8dbdSChopra, Manish break; 1057961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 1058ec9b8dbdSChopra, Manish rc = qede_get_rss_flags(edev, info); 1059ec9b8dbdSChopra, Manish break; 1060ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLCNT: 1061ec9b8dbdSChopra, Manish info->rule_cnt = qede_get_arfs_filter_count(edev); 1062ec9b8dbdSChopra, Manish info->data = QEDE_RFS_MAX_FLTR; 1063ec9b8dbdSChopra, Manish break; 1064ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRULE: 1065ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_entry(edev, info); 1066ec9b8dbdSChopra, Manish break; 1067ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLALL: 1068ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_all(edev, info, rule_locs); 1069ec9b8dbdSChopra, Manish break; 1070961acdeaSSudarsana Reddy Kalluru default: 1071961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 1072ec9b8dbdSChopra, Manish rc = -EOPNOTSUPP; 1073961acdeaSSudarsana Reddy Kalluru } 1074ec9b8dbdSChopra, Manish 1075ec9b8dbdSChopra, Manish return rc; 1076961acdeaSSudarsana Reddy Kalluru } 1077961acdeaSSudarsana Reddy Kalluru 1078961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1079961acdeaSSudarsana Reddy Kalluru { 1080f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1081961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 1082f29ffdb6SMintz, Yuval int rc = 0; 1083961acdeaSSudarsana Reddy Kalluru 1084961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1085961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 1086961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 1087961acdeaSSudarsana Reddy Kalluru 1088961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1089961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1090961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1091961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 1092961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 1093961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1094961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1095961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1096961acdeaSSudarsana Reddy Kalluru } 1097961acdeaSSudarsana Reddy Kalluru return 0; 1098961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1099961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1100961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1101961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1102961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 1103961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1104961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1105961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1106961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 1107961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1108961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1109961acdeaSSudarsana Reddy Kalluru } else { 1110961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1111961acdeaSSudarsana Reddy Kalluru } 1112961acdeaSSudarsana Reddy Kalluru break; 1113961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1114961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1115961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1116961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1117961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 1118961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1119961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1120961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1121961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 1122961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1123961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1124961acdeaSSudarsana Reddy Kalluru } else { 1125961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1126961acdeaSSudarsana Reddy Kalluru } 1127961acdeaSSudarsana Reddy Kalluru break; 1128961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1129961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1130961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 1131961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 1132961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1133961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1134961acdeaSSudarsana Reddy Kalluru } 1135961acdeaSSudarsana Reddy Kalluru return 0; 1136961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1137961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1138961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1139961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1140961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1141961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1142961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1143961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1144961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1145961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1146961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1147961acdeaSSudarsana Reddy Kalluru if (info->data) { 1148961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1149961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1150961acdeaSSudarsana Reddy Kalluru } 1151961acdeaSSudarsana Reddy Kalluru return 0; 1152961acdeaSSudarsana Reddy Kalluru default: 1153961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1154961acdeaSSudarsana Reddy Kalluru } 1155961acdeaSSudarsana Reddy Kalluru 1156961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1157f29ffdb6SMintz, Yuval if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) 1158961acdeaSSudarsana Reddy Kalluru return 0; 1159961acdeaSSudarsana Reddy Kalluru 1160961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1161f29ffdb6SMintz, Yuval edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); 1162961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1163961acdeaSSudarsana Reddy Kalluru 1164961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1165f29ffdb6SMintz, Yuval __qede_lock(edev); 1166f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1167f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1168f29ffdb6SMintz, Yuval if (!vport_update_params) { 1169f29ffdb6SMintz, Yuval __qede_unlock(edev); 1170f29ffdb6SMintz, Yuval return -ENOMEM; 1171961acdeaSSudarsana Reddy Kalluru } 1172f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1173f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1174f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1175f29ffdb6SMintz, Yuval vfree(vport_update_params); 1176f29ffdb6SMintz, Yuval } 1177f29ffdb6SMintz, Yuval __qede_unlock(edev); 1178961acdeaSSudarsana Reddy Kalluru 1179f29ffdb6SMintz, Yuval return rc; 1180961acdeaSSudarsana Reddy Kalluru } 1181961acdeaSSudarsana Reddy Kalluru 1182961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1183961acdeaSSudarsana Reddy Kalluru { 1184961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1185961acdeaSSudarsana Reddy Kalluru 1186961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1187961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 1188961acdeaSSudarsana Reddy Kalluru return qede_set_rss_flags(edev, info); 1189961acdeaSSudarsana Reddy Kalluru default: 1190961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1191961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1192961acdeaSSudarsana Reddy Kalluru } 1193961acdeaSSudarsana Reddy Kalluru } 1194961acdeaSSudarsana Reddy Kalluru 1195961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1196961acdeaSSudarsana Reddy Kalluru { 1197961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1198961acdeaSSudarsana Reddy Kalluru } 1199961acdeaSSudarsana Reddy Kalluru 1200961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1201961acdeaSSudarsana Reddy Kalluru { 1202961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1203961acdeaSSudarsana Reddy Kalluru 1204f29ffdb6SMintz, Yuval return sizeof(edev->rss_key); 1205961acdeaSSudarsana Reddy Kalluru } 1206961acdeaSSudarsana Reddy Kalluru 1207961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1208961acdeaSSudarsana Reddy Kalluru { 1209961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1210961acdeaSSudarsana Reddy Kalluru int i; 1211961acdeaSSudarsana Reddy Kalluru 1212961acdeaSSudarsana Reddy Kalluru if (hfunc) 1213961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1214961acdeaSSudarsana Reddy Kalluru 1215961acdeaSSudarsana Reddy Kalluru if (!indir) 1216961acdeaSSudarsana Reddy Kalluru return 0; 1217961acdeaSSudarsana Reddy Kalluru 1218961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1219f29ffdb6SMintz, Yuval indir[i] = edev->rss_ind_table[i]; 1220961acdeaSSudarsana Reddy Kalluru 1221961acdeaSSudarsana Reddy Kalluru if (key) 1222f29ffdb6SMintz, Yuval memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev)); 1223961acdeaSSudarsana Reddy Kalluru 1224961acdeaSSudarsana Reddy Kalluru return 0; 1225961acdeaSSudarsana Reddy Kalluru } 1226961acdeaSSudarsana Reddy Kalluru 1227961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1228961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1229961acdeaSSudarsana Reddy Kalluru { 1230f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1231961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1232f29ffdb6SMintz, Yuval int i, rc = 0; 1233961acdeaSSudarsana Reddy Kalluru 1234ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1235ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1236ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1237ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1238ba300ce3SSudarsana Reddy Kalluru } 1239ba300ce3SSudarsana Reddy Kalluru 1240961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1241961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1242961acdeaSSudarsana Reddy Kalluru 1243961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1244961acdeaSSudarsana Reddy Kalluru return 0; 1245961acdeaSSudarsana Reddy Kalluru 1246961acdeaSSudarsana Reddy Kalluru if (indir) { 1247961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1248f29ffdb6SMintz, Yuval edev->rss_ind_table[i] = indir[i]; 1249961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1250961acdeaSSudarsana Reddy Kalluru } 1251961acdeaSSudarsana Reddy Kalluru 1252961acdeaSSudarsana Reddy Kalluru if (key) { 1253f29ffdb6SMintz, Yuval memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev)); 1254961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1255961acdeaSSudarsana Reddy Kalluru } 1256961acdeaSSudarsana Reddy Kalluru 1257f29ffdb6SMintz, Yuval __qede_lock(edev); 1258f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1259f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1260f29ffdb6SMintz, Yuval if (!vport_update_params) { 1261f29ffdb6SMintz, Yuval __qede_unlock(edev); 1262f29ffdb6SMintz, Yuval return -ENOMEM; 1263961acdeaSSudarsana Reddy Kalluru } 1264f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1265f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1266f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1267f29ffdb6SMintz, Yuval vfree(vport_update_params); 1268f29ffdb6SMintz, Yuval } 1269f29ffdb6SMintz, Yuval __qede_unlock(edev); 1270961acdeaSSudarsana Reddy Kalluru 1271f29ffdb6SMintz, Yuval return rc; 1272961acdeaSSudarsana Reddy Kalluru } 1273961acdeaSSudarsana Reddy Kalluru 127416f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 127516f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 127616f46bf0SSudarsana Reddy Kalluru { 127716f46bf0SSudarsana Reddy Kalluru int i; 127816f46bf0SSudarsana Reddy Kalluru 127916f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 128016f46bf0SSudarsana Reddy Kalluru return; 128116f46bf0SSudarsana Reddy Kalluru 12829a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 128316f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 128416f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 128516f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 128616f46bf0SSudarsana Reddy Kalluru } 128716f46bf0SSudarsana Reddy Kalluru } 128816f46bf0SSudarsana Reddy Kalluru 128916f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 129016f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 129116f46bf0SSudarsana Reddy Kalluru { 129216f46bf0SSudarsana Reddy Kalluru int i; 129316f46bf0SSudarsana Reddy Kalluru 12949a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 129516f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 129616f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 129716f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 129816f46bf0SSudarsana Reddy Kalluru } 129916f46bf0SSudarsana Reddy Kalluru } 130016f46bf0SSudarsana Reddy Kalluru 130116f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 130216f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 130316f46bf0SSudarsana Reddy Kalluru { 13049a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 130516f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 130616f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 130748848a06SManish Chopra int i, idx; 130848848a06SManish Chopra u16 val; 130916f46bf0SSudarsana Reddy Kalluru 13109a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 13119a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 131280439a17SMintz, Yuval txq = edev->fp_array[i].txq; 13139a4d7e86SSudarsana Reddy Kalluru break; 13149a4d7e86SSudarsana Reddy Kalluru } 13159a4d7e86SSudarsana Reddy Kalluru } 13169a4d7e86SSudarsana Reddy Kalluru 13179a4d7e86SSudarsana Reddy Kalluru if (!txq) { 13189a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 13199a4d7e86SSudarsana Reddy Kalluru return -1; 13209a4d7e86SSudarsana Reddy Kalluru } 13219a4d7e86SSudarsana Reddy Kalluru 132216f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 13235a052d62SSudarsana Reddy Kalluru idx = txq->sw_tx_prod; 1324cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = skb; 132516f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 132616f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 132716f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 132816f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1329351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 133048848a06SManish Chopra val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; 133148848a06SManish Chopra first_bd->data.bitfields |= cpu_to_le16(val); 133216f46bf0SSudarsana Reddy Kalluru 133316f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 133416f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 133516f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 133616f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 133716f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 133816f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 133916f46bf0SSudarsana Reddy Kalluru } 134016f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 134116f46bf0SSudarsana Reddy Kalluru 134216f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 134316f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 13445a052d62SSudarsana Reddy Kalluru txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; 134516f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 134648848a06SManish Chopra val = qed_chain_get_prod_idx(&txq->tx_pbl); 134748848a06SManish Chopra txq->tx_db.data.bd_prod = cpu_to_le16(val); 134816f46bf0SSudarsana Reddy Kalluru 134916f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 135016f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 135116f46bf0SSudarsana Reddy Kalluru */ 135216f46bf0SSudarsana Reddy Kalluru wmb(); 135316f46bf0SSudarsana Reddy Kalluru barrier(); 135416f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 135516f46bf0SSudarsana Reddy Kalluru 135616f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 135716f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 135816f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 135916f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 136016f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 136116f46bf0SSudarsana Reddy Kalluru */ 136216f46bf0SSudarsana Reddy Kalluru mmiowb(); 136316f46bf0SSudarsana Reddy Kalluru 136416f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 136516f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 136616f46bf0SSudarsana Reddy Kalluru break; 136716f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 136816f46bf0SSudarsana Reddy Kalluru } 136916f46bf0SSudarsana Reddy Kalluru 137016f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 137116f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 137216f46bf0SSudarsana Reddy Kalluru return -1; 137316f46bf0SSudarsana Reddy Kalluru } 137416f46bf0SSudarsana Reddy Kalluru 137516f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1376fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 137716f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 13785a052d62SSudarsana Reddy Kalluru txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; 1379cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = NULL; 138016f46bf0SSudarsana Reddy Kalluru 138116f46bf0SSudarsana Reddy Kalluru return 0; 138216f46bf0SSudarsana Reddy Kalluru } 138316f46bf0SSudarsana Reddy Kalluru 138416f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 138516f46bf0SSudarsana Reddy Kalluru { 138616f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 138716f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 13889a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 138916f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 139016f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1391afe981d6SSudarsana Reddy Kalluru int i, iter, rc = 0; 139216f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 139316f46bf0SSudarsana Reddy Kalluru 13949a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 13959a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 13969a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 13979a4d7e86SSudarsana Reddy Kalluru break; 13989a4d7e86SSudarsana Reddy Kalluru } 13999a4d7e86SSudarsana Reddy Kalluru } 14009a4d7e86SSudarsana Reddy Kalluru 14019a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 14029a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 14039a4d7e86SSudarsana Reddy Kalluru return -1; 14049a4d7e86SSudarsana Reddy Kalluru } 14059a4d7e86SSudarsana Reddy Kalluru 140616f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 140716f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 140816f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 140916f46bf0SSudarsana Reddy Kalluru */ 1410afe981d6SSudarsana Reddy Kalluru for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { 141116f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1412837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1413837d4eb6SSudarsana Reddy Kalluru continue; 141416f46bf0SSudarsana Reddy Kalluru } 141516f46bf0SSudarsana Reddy Kalluru 141616f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 141716f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 141816f46bf0SSudarsana Reddy Kalluru 1419837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1420837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1421837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1422837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1423837d4eb6SSudarsana Reddy Kalluru * CQE. 142416f46bf0SSudarsana Reddy Kalluru */ 142516f46bf0SSudarsana Reddy Kalluru rmb(); 142616f46bf0SSudarsana Reddy Kalluru 142716f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 142816f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 142916f46bf0SSudarsana Reddy Kalluru 143016f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 143116f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 143216f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 143316f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 143416f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 143516f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1436837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 1437837d4eb6SSudarsana Reddy Kalluru sw_rx_data->page_offset); 1438837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1439837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1440837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 144116f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 144216f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1443837d4eb6SSudarsana Reddy Kalluru rc = -1; 1444837d4eb6SSudarsana Reddy Kalluru break; 144516f46bf0SSudarsana Reddy Kalluru } 144616f46bf0SSudarsana Reddy Kalluru 14479eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1448837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1449837d4eb6SSudarsana Reddy Kalluru break; 1450837d4eb6SSudarsana Reddy Kalluru } 145116f46bf0SSudarsana Reddy Kalluru 1452837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 14539eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1454837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1455837d4eb6SSudarsana Reddy Kalluru } 1456837d4eb6SSudarsana Reddy Kalluru 1457afe981d6SSudarsana Reddy Kalluru if (iter == QEDE_SELFTEST_POLL_COUNT) { 1458837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1459837d4eb6SSudarsana Reddy Kalluru return -1; 1460837d4eb6SSudarsana Reddy Kalluru } 1461837d4eb6SSudarsana Reddy Kalluru 1462837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1463837d4eb6SSudarsana Reddy Kalluru 1464837d4eb6SSudarsana Reddy Kalluru return rc; 146516f46bf0SSudarsana Reddy Kalluru } 146616f46bf0SSudarsana Reddy Kalluru 146716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 146816f46bf0SSudarsana Reddy Kalluru { 146916f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 147016f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 147116f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 147216f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 147316f46bf0SSudarsana Reddy Kalluru u8 *packet; 147416f46bf0SSudarsana Reddy Kalluru 147516f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 147616f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 147716f46bf0SSudarsana Reddy Kalluru return -EINVAL; 147816f46bf0SSudarsana Reddy Kalluru } 147916f46bf0SSudarsana Reddy Kalluru 148016f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 148116f46bf0SSudarsana Reddy Kalluru 148216f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 148316f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 148416f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 148516f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 148616f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 148716f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 148816f46bf0SSudarsana Reddy Kalluru 148916f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 149016f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 149116f46bf0SSudarsana Reddy Kalluru 149216f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 149316f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 149416f46bf0SSudarsana Reddy Kalluru 149516f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 149616f46bf0SSudarsana Reddy Kalluru if (!skb) { 149716f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 149816f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 149916f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 150016f46bf0SSudarsana Reddy Kalluru } 150116f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 150216f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 150316f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 150416f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 150516f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 150616f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 150716f46bf0SSudarsana Reddy Kalluru 150816f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 150916f46bf0SSudarsana Reddy Kalluru if (rc) 151016f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 151116f46bf0SSudarsana Reddy Kalluru 151216f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 151316f46bf0SSudarsana Reddy Kalluru if (rc) 151416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 151516f46bf0SSudarsana Reddy Kalluru 151616f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 151716f46bf0SSudarsana Reddy Kalluru 151816f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 151916f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 152016f46bf0SSudarsana Reddy Kalluru 152116f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 152216f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 152316f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 152416f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 152516f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 152616f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 152716f46bf0SSudarsana Reddy Kalluru 152816f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 152916f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 153016f46bf0SSudarsana Reddy Kalluru 153116f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 153216f46bf0SSudarsana Reddy Kalluru 153316f46bf0SSudarsana Reddy Kalluru return rc; 153416f46bf0SSudarsana Reddy Kalluru } 153516f46bf0SSudarsana Reddy Kalluru 15363044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 15373044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 15383044a02eSSudarsana Reddy Kalluru { 15393044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 15403044a02eSSudarsana Reddy Kalluru 15413044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 15423044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 15433044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 15443044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 15453044a02eSSudarsana Reddy Kalluru 15463044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 15473044a02eSSudarsana Reddy Kalluru 154816f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 154916f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 155016f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 155116f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 155216f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 155316f46bf0SSudarsana Reddy Kalluru } 155416f46bf0SSudarsana Reddy Kalluru } 155516f46bf0SSudarsana Reddy Kalluru 15563044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 15573044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 15583044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 15593044a02eSSudarsana Reddy Kalluru } 15603044a02eSSudarsana Reddy Kalluru 15613044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 15623044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 15633044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 15643044a02eSSudarsana Reddy Kalluru } 15653044a02eSSudarsana Reddy Kalluru 15663044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 15673044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 15683044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 15693044a02eSSudarsana Reddy Kalluru } 15703044a02eSSudarsana Reddy Kalluru 15713044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 15723044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 15733044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 15743044a02eSSudarsana Reddy Kalluru } 15757a4b21b7SMintz, Yuval 15767a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 15777a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 15787a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 15797a4b21b7SMintz, Yuval } 15803044a02eSSudarsana Reddy Kalluru } 15813044a02eSSudarsana Reddy Kalluru 15823d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 15833d789994SManish Chopra const struct ethtool_tunable *tuna, 15843d789994SManish Chopra const void *data) 15853d789994SManish Chopra { 15863d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 15873d789994SManish Chopra u32 val; 15883d789994SManish Chopra 15893d789994SManish Chopra switch (tuna->id) { 15903d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 15913d789994SManish Chopra val = *(u32 *)data; 15923d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 15933d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 15943d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 15953d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 15963d789994SManish Chopra return -EINVAL; 15973d789994SManish Chopra } 15983d789994SManish Chopra 15993d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 16003d789994SManish Chopra break; 16013d789994SManish Chopra default: 16023d789994SManish Chopra return -EOPNOTSUPP; 16033d789994SManish Chopra } 16043d789994SManish Chopra 16053d789994SManish Chopra return 0; 16063d789994SManish Chopra } 16073d789994SManish Chopra 16083d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 16093d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 16103d789994SManish Chopra { 16113d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 16123d789994SManish Chopra 16133d789994SManish Chopra switch (tuna->id) { 16143d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 16153d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 16163d789994SManish Chopra break; 16173d789994SManish Chopra default: 16183d789994SManish Chopra return -EOPNOTSUPP; 16193d789994SManish Chopra } 16203d789994SManish Chopra 16213d789994SManish Chopra return 0; 16223d789994SManish Chopra } 16233d789994SManish Chopra 1624133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1625054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1626054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1627133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1628e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1629e0971c83STomer Tayar .get_regs = qede_get_regs, 163014d39648SMintz, Yuval .get_wol = qede_get_wol, 163114d39648SMintz, Yuval .set_wol = qede_set_wol, 1632133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1633133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 163432a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1635133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1636d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1637d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 163801ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 163901ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 16400f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 16410f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1642133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 16433d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1644133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1645f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1646133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1647961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1648961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1649961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1650961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1651961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1652961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 16534c55215cSSudarsana Reddy Kalluru .get_ts_info = qede_get_ts_info, 16548edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 16558edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 16563044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 16573d789994SManish Chopra .get_tunable = qede_get_tunable, 16583d789994SManish Chopra .set_tunable = qede_set_tunable, 1659133fac0eSSudarsana Kalluru }; 1660133fac0eSSudarsana Kalluru 1661fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1662054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1663fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1664fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1665fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1666fefb0202SYuval Mintz .get_link = qede_get_link, 1667fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1668fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1669fefb0202SYuval Mintz .get_strings = qede_get_strings, 1670fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1671fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1672fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1673fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1674fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1675fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1676fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1677fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1678fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1679fefb0202SYuval Mintz .get_channels = qede_get_channels, 1680fefb0202SYuval Mintz .set_channels = qede_set_channels, 16813d789994SManish Chopra .get_tunable = qede_get_tunable, 16823d789994SManish Chopra .set_tunable = qede_set_tunable, 1683fefb0202SYuval Mintz }; 1684fefb0202SYuval Mintz 1685133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1686133fac0eSSudarsana Kalluru { 1687fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1688fefb0202SYuval Mintz 1689fefb0202SYuval Mintz if (IS_VF(edev)) 1690fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1691fefb0202SYuval Mintz else 1692133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1693133fac0eSSudarsana Kalluru } 1694