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), 76dcc6abaeSMichael Shteinbok QEDE_TQSTAT(tx_mem_alloc_err), 7768db9ec2SSudarsana Reddy Kalluru }; 7868db9ec2SSudarsana Reddy Kalluru 799c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \ 809c79ddaaSMintz, Yuval (offsetof(type, stat_name) + (base)) 814dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name) (#stat_name) 829c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \ 839c79ddaaSMintz, Yuval {QEDE_STAT_OFFSET(stat_name, type, base), \ 849c79ddaaSMintz, Yuval QEDE_STAT_STRING(stat_name), \ 859c79ddaaSMintz, Yuval attr} 869c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \ 879c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0) 889c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \ 899c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_common, 0, \ 909c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY)) 919c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \ 929c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_bb, \ 939c79ddaaSMintz, Yuval offsetof(struct qede_stats, bb), \ 949c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY)) 959c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \ 969c79ddaaSMintz, Yuval _QEDE_STAT(stat_name, struct qede_stats_ah, \ 979c79ddaaSMintz, Yuval offsetof(struct qede_stats, ah), \ 989c79ddaaSMintz, Yuval BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY)) 99133fac0eSSudarsana Kalluru static const struct { 100133fac0eSSudarsana Kalluru u64 offset; 101133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 1029c79ddaaSMintz, Yuval unsigned long attr; 1039c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY 0 1049c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY 1 1059c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY 2 106133fac0eSSudarsana Kalluru } qede_stats_arr[] = { 107133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes), 108133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes), 109133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes), 110133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts), 111133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts), 112133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts), 113133fac0eSSudarsana Kalluru 114133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes), 115133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes), 116133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes), 117133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts), 118133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts), 119133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts), 120133fac0eSSudarsana Kalluru 121133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets), 122d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets), 123d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets), 124d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets), 125d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets), 126d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets), 1279c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets), 1289c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets), 1299c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets), 1309c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets), 1319c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets), 1329c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets), 133133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets), 134133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets), 135133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets), 136133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets), 137133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets), 138133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets), 1399c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets), 1409c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets), 1419c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets), 1429c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets), 1439c79ddaaSMintz, Yuval QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets), 144133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames), 145133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames), 146133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames), 147133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames), 148133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames), 149133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames), 150133fac0eSSudarsana Kalluru 151133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors), 152133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors), 153133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors), 154133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets), 155133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers), 156133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets), 157133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments), 1589c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_lpi_entry_count), 1599c79ddaaSMintz, Yuval QEDE_PF_BB_STAT(tx_total_collisions), 160133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates), 161133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards), 162133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards), 163133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards), 164133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards), 165608e00d0SManish Chopra QEDE_PF_STAT(gft_filter_drop), 166133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1671a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1681a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 169133fac0eSSudarsana Kalluru 170133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 171133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 172133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 173133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 174133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 17532d26a68SSudarsana Reddy Kalluru 17632d26a68SSudarsana Reddy Kalluru QEDE_STAT(link_change_count), 177133fac0eSSudarsana Kalluru }; 178133fac0eSSudarsana Kalluru 179133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 1809c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \ 1819c79ddaaSMintz, Yuval test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr) 1829c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \ 1839c79ddaaSMintz, Yuval test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr) 1849c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \ 1859c79ddaaSMintz, Yuval test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr) 186133fac0eSSudarsana Kalluru 187f3e72109SYuval Mintz enum { 188f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 189f15cff04SSudarsana Reddy Kalluru QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */ 190f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 191f3e72109SYuval Mintz }; 192f3e72109SYuval Mintz 193f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 194f3e72109SYuval Mintz "Coupled-Function", 195f15cff04SSudarsana Reddy Kalluru "SmartAN capable", 196f3e72109SYuval Mintz }; 197f3e72109SYuval Mintz 1983044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 19916f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 2003044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 2013044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 2023044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 2033044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 2047a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 2053044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 2063044a02eSSudarsana Reddy Kalluru }; 2073044a02eSSudarsana Reddy Kalluru 2083044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 20916f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 2103044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 2113044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 2123044a02eSSudarsana Reddy Kalluru "Register (online)\t", 2133044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 2147a4b21b7SMintz, Yuval "Nvram (online)\t\t", 2153044a02eSSudarsana Reddy Kalluru }; 2163044a02eSSudarsana Reddy Kalluru 2174dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev, 2184dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf) 2194dbcd640SMintz, Yuval { 2204dbcd640SMintz, Yuval int i; 2214dbcd640SMintz, Yuval 2224dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 223cb6aeb07SMintz, Yuval if (txq->is_xdp) 224cb6aeb07SMintz, Yuval sprintf(*buf, "%d [XDP]: %s", 225cb6aeb07SMintz, Yuval QEDE_TXQ_XDP_TO_IDX(edev, txq), 226cb6aeb07SMintz, Yuval qede_tqstats_arr[i].string); 227cb6aeb07SMintz, Yuval else 2285e7baf0fSManish Chopra sprintf(*buf, "%d_%d: %s", txq->index, txq->cos, 2294dbcd640SMintz, Yuval qede_tqstats_arr[i].string); 2304dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2314dbcd640SMintz, Yuval } 2324dbcd640SMintz, Yuval } 2334dbcd640SMintz, Yuval 2344dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev, 2354dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf) 2364dbcd640SMintz, Yuval { 2374dbcd640SMintz, Yuval int i; 2384dbcd640SMintz, Yuval 2394dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 2404dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id, 2414dbcd640SMintz, Yuval qede_rqstats_arr[i].string); 2424dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 2434dbcd640SMintz, Yuval } 2444dbcd640SMintz, Yuval } 2454dbcd640SMintz, Yuval 2469c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index) 2479c79ddaaSMintz, Yuval { 2489c79ddaaSMintz, Yuval return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) || 2499c79ddaaSMintz, Yuval (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) || 2509c79ddaaSMintz, Yuval (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index)); 2519c79ddaaSMintz, Yuval } 2529c79ddaaSMintz, Yuval 253133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 254133fac0eSSudarsana Kalluru { 2554dbcd640SMintz, Yuval struct qede_fastpath *fp; 2564dbcd640SMintz, Yuval int i; 257133fac0eSSudarsana Kalluru 2584dbcd640SMintz, Yuval /* Account for queue statistics */ 2594dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 2604dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 26168db9ec2SSudarsana Reddy Kalluru 2624dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 2634dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf); 2644dbcd640SMintz, Yuval 265cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 266cb6aeb07SMintz, Yuval qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf); 267cb6aeb07SMintz, Yuval 2685e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 2695e7baf0fSManish Chopra int cos; 2705e7baf0fSManish Chopra 2715e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 2725e7baf0fSManish Chopra qede_get_strings_stats_txq(edev, 2735e7baf0fSManish Chopra &fp->txq[cos], &buf); 2745e7baf0fSManish Chopra } 275cbbf049aSMintz, Yuval } 276cbbf049aSMintz, Yuval 2774dbcd640SMintz, Yuval /* Account for non-queue statistics */ 2784dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 2799c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 280fefb0202SYuval Mintz continue; 2814dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string); 2824dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN; 283133fac0eSSudarsana Kalluru } 284133fac0eSSudarsana Kalluru } 285133fac0eSSudarsana Kalluru 286133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 287133fac0eSSudarsana Kalluru { 288133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 289133fac0eSSudarsana Kalluru 290133fac0eSSudarsana Kalluru switch (stringset) { 291133fac0eSSudarsana Kalluru case ETH_SS_STATS: 292133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 293133fac0eSSudarsana Kalluru break; 294f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 295f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 296f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 297f3e72109SYuval Mintz break; 2983044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2993044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 3003044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 3013044a02eSSudarsana Reddy Kalluru break; 302133fac0eSSudarsana Kalluru default: 303133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 304133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 305133fac0eSSudarsana Kalluru } 306133fac0eSSudarsana Kalluru } 307133fac0eSSudarsana Kalluru 3084dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) 3094dbcd640SMintz, Yuval { 3104dbcd640SMintz, Yuval int i; 3114dbcd640SMintz, Yuval 3124dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 3134dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); 3144dbcd640SMintz, Yuval (*buf)++; 3154dbcd640SMintz, Yuval } 3164dbcd640SMintz, Yuval } 3174dbcd640SMintz, Yuval 3184dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) 3194dbcd640SMintz, Yuval { 3204dbcd640SMintz, Yuval int i; 3214dbcd640SMintz, Yuval 3224dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 3234dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); 3244dbcd640SMintz, Yuval (*buf)++; 3254dbcd640SMintz, Yuval } 3264dbcd640SMintz, Yuval } 3274dbcd640SMintz, Yuval 328133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 329133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 330133fac0eSSudarsana Kalluru { 331133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3324dbcd640SMintz, Yuval struct qede_fastpath *fp; 3334dbcd640SMintz, Yuval int i; 334133fac0eSSudarsana Kalluru 335133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 336133fac0eSSudarsana Kalluru 337567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */ 338567b3c12SMintz, Yuval __qede_lock(edev); 339567b3c12SMintz, Yuval 3404dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 3414dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 342133fac0eSSudarsana Kalluru 3434dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 3444dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf); 34568db9ec2SSudarsana Reddy Kalluru 346cb6aeb07SMintz, Yuval if (fp->type & QEDE_FASTPATH_XDP) 347cb6aeb07SMintz, Yuval qede_get_ethtool_stats_txq(fp->xdp_tx, &buf); 348cb6aeb07SMintz, Yuval 3495e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 3505e7baf0fSManish Chopra int cos; 3515e7baf0fSManish Chopra 3525e7baf0fSManish Chopra for_each_cos_in_txq(edev, cos) 3535e7baf0fSManish Chopra qede_get_ethtool_stats_txq(&fp->txq[cos], &buf); 3545e7baf0fSManish Chopra } 35568db9ec2SSudarsana Reddy Kalluru } 35668db9ec2SSudarsana Reddy Kalluru 3574dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 3589c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 359fefb0202SYuval Mintz continue; 3604dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) + 3614dbcd640SMintz, Yuval qede_stats_arr[i].offset)); 3624dbcd640SMintz, Yuval 3634dbcd640SMintz, Yuval buf++; 364fefb0202SYuval Mintz } 365133fac0eSSudarsana Kalluru 366567b3c12SMintz, Yuval __qede_unlock(edev); 367133fac0eSSudarsana Kalluru } 368133fac0eSSudarsana Kalluru 369133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 370133fac0eSSudarsana Kalluru { 371133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 3729c79ddaaSMintz, Yuval int num_stats = QEDE_NUM_STATS, i; 373133fac0eSSudarsana Kalluru 374133fac0eSSudarsana Kalluru switch (stringset) { 375133fac0eSSudarsana Kalluru case ETH_SS_STATS: 376fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 3779c79ddaaSMintz, Yuval if (qede_is_irrelevant_stat(edev, i)) 378fefb0202SYuval Mintz num_stats--; 3794dbcd640SMintz, Yuval 3804dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */ 3815e7baf0fSManish Chopra num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * 3825e7baf0fSManish Chopra edev->dev_info.num_tc; 3834dbcd640SMintz, Yuval 3844dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */ 3854dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; 3864dbcd640SMintz, Yuval 387cb6aeb07SMintz, Yuval /* Account for XDP statistics [if needed] */ 388cb6aeb07SMintz, Yuval if (edev->xdp_prog) 389cb6aeb07SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS; 3904dbcd640SMintz, Yuval return num_stats; 3914dbcd640SMintz, Yuval 392f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 393f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 3943044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 3956ecb0a0cSYuval Mintz if (!IS_VF(edev)) 3963044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 3976ecb0a0cSYuval Mintz else 3986ecb0a0cSYuval Mintz return 0; 399133fac0eSSudarsana Kalluru default: 400133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 401133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 402133fac0eSSudarsana Kalluru return -EINVAL; 403133fac0eSSudarsana Kalluru } 404133fac0eSSudarsana Kalluru } 405133fac0eSSudarsana Kalluru 406f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 407f3e72109SYuval Mintz { 408f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 409f15cff04SSudarsana Reddy Kalluru u32 flags = 0; 410f3e72109SYuval Mintz 411f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) 412f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_CMT); 413f15cff04SSudarsana Reddy Kalluru 414f15cff04SSudarsana Reddy Kalluru if (edev->dev_info.common.smart_an) 415f15cff04SSudarsana Reddy Kalluru flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT); 416f15cff04SSudarsana Reddy Kalluru 417f15cff04SSudarsana Reddy Kalluru return flags; 418f3e72109SYuval Mintz } 419f3e72109SYuval Mintz 420054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 421054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 422054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 423054c67d1SSudarsana Reddy Kalluru }; 424054c67d1SSudarsana Reddy Kalluru 425054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 426054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 427054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 428054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 429054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 430c56a8be7SRahul Verma {QED_LM_10000baseT_Full_BIT, ETHTOOL_LINK_MODE_10000baseT_Full_BIT}, 431c56a8be7SRahul Verma {QED_LM_2500baseX_Full_BIT, ETHTOOL_LINK_MODE_2500baseX_Full_BIT}, 432c56a8be7SRahul Verma {QED_LM_Backplane_BIT, ETHTOOL_LINK_MODE_Backplane_BIT}, 433c56a8be7SRahul Verma {QED_LM_1000baseKX_Full_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT}, 434c56a8be7SRahul Verma {QED_LM_10000baseKX4_Full_BIT, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT}, 435054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 436c56a8be7SRahul Verma {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 437c56a8be7SRahul Verma {QED_LM_10000baseR_FEC_BIT, ETHTOOL_LINK_MODE_10000baseR_FEC_BIT}, 438631b6707SSudarsana Reddy Kalluru {QED_LM_20000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT}, 439c56a8be7SRahul Verma {QED_LM_40000baseKR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT}, 440c56a8be7SRahul Verma {QED_LM_40000baseCR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT}, 441c56a8be7SRahul Verma {QED_LM_40000baseSR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT}, 442054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 443c56a8be7SRahul Verma {QED_LM_25000baseCR_Full_BIT, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT}, 444c56a8be7SRahul Verma {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 445c56a8be7SRahul Verma {QED_LM_25000baseSR_Full_BIT, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT}, 446c56a8be7SRahul Verma {QED_LM_50000baseCR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT}, 447054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 448054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 449054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 450c56a8be7SRahul Verma {QED_LM_100000baseSR4_Full_BIT, 451c56a8be7SRahul Verma ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT}, 452c56a8be7SRahul Verma {QED_LM_100000baseCR4_Full_BIT, 453c56a8be7SRahul Verma ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT}, 454c56a8be7SRahul Verma {QED_LM_100000baseLR4_ER4_Full_BIT, 455c56a8be7SRahul Verma ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT}, 456c56a8be7SRahul Verma {QED_LM_50000baseSR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT}, 457c56a8be7SRahul Verma {QED_LM_1000baseX_Full_BIT, ETHTOOL_LINK_MODE_1000baseX_Full_BIT}, 458c56a8be7SRahul Verma {QED_LM_10000baseCR_Full_BIT, ETHTOOL_LINK_MODE_10000baseCR_Full_BIT}, 459c56a8be7SRahul Verma {QED_LM_10000baseSR_Full_BIT, ETHTOOL_LINK_MODE_10000baseSR_Full_BIT}, 460c56a8be7SRahul Verma {QED_LM_10000baseLR_Full_BIT, ETHTOOL_LINK_MODE_10000baseLR_Full_BIT}, 461c56a8be7SRahul Verma {QED_LM_10000baseLRM_Full_BIT, ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT}, 462054c67d1SSudarsana Reddy Kalluru }; 463054c67d1SSudarsana Reddy Kalluru 464054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 465054c67d1SSudarsana Reddy Kalluru { \ 466054c67d1SSudarsana Reddy Kalluru int i; \ 467054c67d1SSudarsana Reddy Kalluru \ 468d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 469054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 470054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 471054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 472054c67d1SSudarsana Reddy Kalluru } \ 473054c67d1SSudarsana Reddy Kalluru } 474054c67d1SSudarsana Reddy Kalluru 475054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 476054c67d1SSudarsana Reddy Kalluru { \ 477054c67d1SSudarsana Reddy Kalluru int i; \ 478054c67d1SSudarsana Reddy Kalluru \ 479d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 480054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 481054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 482054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 483054c67d1SSudarsana Reddy Kalluru } \ 484054c67d1SSudarsana Reddy Kalluru } 485054c67d1SSudarsana Reddy Kalluru 486054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 487054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 488133fac0eSSudarsana Kalluru { 489054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 490133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 491133fac0eSSudarsana Kalluru struct qed_link_output current_link; 492133fac0eSSudarsana Kalluru 493567b3c12SMintz, Yuval __qede_lock(edev); 494567b3c12SMintz, Yuval 495133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 496133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 497133fac0eSSudarsana Kalluru 498054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 499054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 500054c67d1SSudarsana Reddy Kalluru 501054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 502054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 503054c67d1SSudarsana Reddy Kalluru 504054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 505054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 506054c67d1SSudarsana Reddy Kalluru 507133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 508054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 509054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 510133fac0eSSudarsana Kalluru } else { 511054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 512054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 513133fac0eSSudarsana Kalluru } 514567b3c12SMintz, Yuval 515567b3c12SMintz, Yuval __qede_unlock(edev); 516567b3c12SMintz, Yuval 517054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 518054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 519133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 520133fac0eSSudarsana Kalluru 521133fac0eSSudarsana Kalluru return 0; 522133fac0eSSudarsana Kalluru } 523133fac0eSSudarsana Kalluru 524054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 525054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 526133fac0eSSudarsana Kalluru { 527054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 528133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 529133fac0eSSudarsana Kalluru struct qed_link_output current_link; 530133fac0eSSudarsana Kalluru struct qed_link_params params; 5311e6e2dedSRahul Verma u32 sup_caps; 532133fac0eSSudarsana Kalluru 533fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 534054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 535133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 536133fac0eSSudarsana Kalluru } 537133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 538133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 539133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 540133fac0eSSudarsana Kalluru 541133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 542133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 543054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 544161adb04Ssudarsana.kalluru@cavium.com if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 545161adb04Ssudarsana.kalluru@cavium.com DP_INFO(edev, "Auto negotiation is not supported\n"); 546161adb04Ssudarsana.kalluru@cavium.com return -EOPNOTSUPP; 547161adb04Ssudarsana.kalluru@cavium.com } 548161adb04Ssudarsana.kalluru@cavium.com 549133fac0eSSudarsana Kalluru params.autoneg = true; 550133fac0eSSudarsana Kalluru params.forced_speed = 0; 551054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 552133fac0eSSudarsana Kalluru } else { /* forced speed */ 553133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 554133fac0eSSudarsana Kalluru params.autoneg = false; 555054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 556054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 5579ac4c546SSudarsana Reddy Kalluru case SPEED_1000: 5581e6e2dedSRahul Verma sup_caps = QED_LM_1000baseT_Full_BIT | 5591e6e2dedSRahul Verma QED_LM_1000baseKX_Full_BIT | 5601e6e2dedSRahul Verma QED_LM_1000baseX_Full_BIT; 5611e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 5629ac4c546SSudarsana Reddy Kalluru DP_INFO(edev, "1G speed not supported\n"); 5639ac4c546SSudarsana Reddy Kalluru return -EINVAL; 5649ac4c546SSudarsana Reddy Kalluru } 5651e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 5661e6e2dedSRahul Verma sup_caps; 5679ac4c546SSudarsana Reddy Kalluru break; 568133fac0eSSudarsana Kalluru case SPEED_10000: 5691e6e2dedSRahul Verma sup_caps = QED_LM_10000baseT_Full_BIT | 5701e6e2dedSRahul Verma QED_LM_10000baseKR_Full_BIT | 5711e6e2dedSRahul Verma QED_LM_10000baseKX4_Full_BIT | 5721e6e2dedSRahul Verma QED_LM_10000baseR_FEC_BIT | 5731e6e2dedSRahul Verma QED_LM_10000baseCR_Full_BIT | 5741e6e2dedSRahul Verma QED_LM_10000baseSR_Full_BIT | 5751e6e2dedSRahul Verma QED_LM_10000baseLR_Full_BIT | 5761e6e2dedSRahul Verma QED_LM_10000baseLRM_Full_BIT; 5771e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 578133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 579133fac0eSSudarsana Kalluru return -EINVAL; 580133fac0eSSudarsana Kalluru } 5811e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 5821e6e2dedSRahul Verma sup_caps; 583054c67d1SSudarsana Reddy Kalluru break; 584631b6707SSudarsana Reddy Kalluru case SPEED_20000: 585631b6707SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 586631b6707SSudarsana Reddy Kalluru QED_LM_20000baseKR2_Full_BIT)) { 587631b6707SSudarsana Reddy Kalluru DP_INFO(edev, "20G speed not supported\n"); 588631b6707SSudarsana Reddy Kalluru return -EINVAL; 589631b6707SSudarsana Reddy Kalluru } 590631b6707SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_20000baseKR2_Full_BIT; 591631b6707SSudarsana Reddy Kalluru break; 592054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 5931e6e2dedSRahul Verma sup_caps = QED_LM_25000baseKR_Full_BIT | 5941e6e2dedSRahul Verma QED_LM_25000baseCR_Full_BIT | 5951e6e2dedSRahul Verma QED_LM_25000baseSR_Full_BIT; 5961e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 597054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 598054c67d1SSudarsana Reddy Kalluru return -EINVAL; 599054c67d1SSudarsana Reddy Kalluru } 6001e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 6011e6e2dedSRahul Verma sup_caps; 602133fac0eSSudarsana Kalluru break; 603133fac0eSSudarsana Kalluru case SPEED_40000: 6041e6e2dedSRahul Verma sup_caps = QED_LM_40000baseLR4_Full_BIT | 6051e6e2dedSRahul Verma QED_LM_40000baseKR4_Full_BIT | 6061e6e2dedSRahul Verma QED_LM_40000baseCR4_Full_BIT | 6071e6e2dedSRahul Verma QED_LM_40000baseSR4_Full_BIT; 6081e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 609133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 610133fac0eSSudarsana Kalluru return -EINVAL; 611133fac0eSSudarsana Kalluru } 6121e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 6131e6e2dedSRahul Verma sup_caps; 614054c67d1SSudarsana Reddy Kalluru break; 61516d5946aSYuval Mintz case SPEED_50000: 6161e6e2dedSRahul Verma sup_caps = QED_LM_50000baseKR2_Full_BIT | 6171e6e2dedSRahul Verma QED_LM_50000baseCR2_Full_BIT | 6181e6e2dedSRahul Verma QED_LM_50000baseSR2_Full_BIT; 6191e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 620054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 621054c67d1SSudarsana Reddy Kalluru return -EINVAL; 622054c67d1SSudarsana Reddy Kalluru } 6231e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 6241e6e2dedSRahul Verma sup_caps; 625054c67d1SSudarsana Reddy Kalluru break; 62616d5946aSYuval Mintz case SPEED_100000: 6271e6e2dedSRahul Verma sup_caps = QED_LM_100000baseKR4_Full_BIT | 6281e6e2dedSRahul Verma QED_LM_100000baseSR4_Full_BIT | 6291e6e2dedSRahul Verma QED_LM_100000baseCR4_Full_BIT | 6301e6e2dedSRahul Verma QED_LM_100000baseLR4_ER4_Full_BIT; 6311e6e2dedSRahul Verma if (!(current_link.supported_caps & sup_caps)) { 632054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 633054c67d1SSudarsana Reddy Kalluru return -EINVAL; 634054c67d1SSudarsana Reddy Kalluru } 6351e6e2dedSRahul Verma params.adv_speeds = current_link.supported_caps & 6361e6e2dedSRahul Verma sup_caps; 637133fac0eSSudarsana Kalluru break; 638133fac0eSSudarsana Kalluru default: 639054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 640133fac0eSSudarsana Kalluru return -EINVAL; 641133fac0eSSudarsana Kalluru } 642133fac0eSSudarsana Kalluru } 643133fac0eSSudarsana Kalluru 644133fac0eSSudarsana Kalluru params.link_up = true; 645133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 646133fac0eSSudarsana Kalluru 647133fac0eSSudarsana Kalluru return 0; 648133fac0eSSudarsana Kalluru } 649133fac0eSSudarsana Kalluru 650133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 651133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 652133fac0eSSudarsana Kalluru { 653133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 654133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 655133fac0eSSudarsana Kalluru 656133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 657133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 658133fac0eSSudarsana Kalluru 659133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 660133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 661133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 662133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 663133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 664133fac0eSSudarsana Kalluru 665133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 666133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 667133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 668133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 669133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 670133fac0eSSudarsana Kalluru 671133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 672133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 673133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 674133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 675133fac0eSSudarsana Kalluru } else { 676133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 677133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 678133fac0eSSudarsana Kalluru } 679133fac0eSSudarsana Kalluru 680133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 681133fac0eSSudarsana Kalluru } 682133fac0eSSudarsana Kalluru 68314d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 68414d39648SMintz, Yuval { 68514d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 68614d39648SMintz, Yuval 68714d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 68814d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 68914d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 69014d39648SMintz, Yuval } 69114d39648SMintz, Yuval } 69214d39648SMintz, Yuval 69314d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 69414d39648SMintz, Yuval { 69514d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 69614d39648SMintz, Yuval bool wol_requested; 69714d39648SMintz, Yuval int rc; 69814d39648SMintz, Yuval 69914d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 70014d39648SMintz, Yuval DP_INFO(edev, 70114d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 70214d39648SMintz, Yuval return -EINVAL; 70314d39648SMintz, Yuval } 70414d39648SMintz, Yuval 70514d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 70614d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 70714d39648SMintz, Yuval return 0; 70814d39648SMintz, Yuval 70914d39648SMintz, Yuval /* Need to actually change configuration */ 71014d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 71114d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 71214d39648SMintz, Yuval return -EINVAL; 71314d39648SMintz, Yuval } 71414d39648SMintz, Yuval 71514d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 71614d39648SMintz, Yuval if (!rc) 71714d39648SMintz, Yuval edev->wol_enabled = wol_requested; 71814d39648SMintz, Yuval 71914d39648SMintz, Yuval return rc; 72014d39648SMintz, Yuval } 72114d39648SMintz, Yuval 722133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 723133fac0eSSudarsana Kalluru { 724133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 725133fac0eSSudarsana Kalluru 7261a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 727133fac0eSSudarsana Kalluru } 728133fac0eSSudarsana Kalluru 729133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 730133fac0eSSudarsana Kalluru { 731133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 732133fac0eSSudarsana Kalluru u32 dp_module = 0; 733133fac0eSSudarsana Kalluru u8 dp_level = 0; 734133fac0eSSudarsana Kalluru 735133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 736133fac0eSSudarsana Kalluru 737133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 738133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 739133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 740133fac0eSSudarsana Kalluru dp_module, dp_level); 741133fac0eSSudarsana Kalluru } 742133fac0eSSudarsana Kalluru 74332a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 74432a7a570SSudarsana Kalluru { 74532a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 74632a7a570SSudarsana Kalluru struct qed_link_output current_link; 74732a7a570SSudarsana Kalluru struct qed_link_params link_params; 74832a7a570SSudarsana Kalluru 749fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 7501a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 751fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 752fe7cd2bfSYuval Mintz } 753fe7cd2bfSYuval Mintz 75432a7a570SSudarsana Kalluru if (!netif_running(dev)) 75532a7a570SSudarsana Kalluru return 0; 75632a7a570SSudarsana Kalluru 75732a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 75832a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 75932a7a570SSudarsana Kalluru if (!current_link.link_up) 76032a7a570SSudarsana Kalluru return 0; 76132a7a570SSudarsana Kalluru 76232a7a570SSudarsana Kalluru /* Toggle the link */ 76332a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 76432a7a570SSudarsana Kalluru link_params.link_up = false; 76532a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 76632a7a570SSudarsana Kalluru link_params.link_up = true; 76732a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 76832a7a570SSudarsana Kalluru 76932a7a570SSudarsana Kalluru return 0; 77032a7a570SSudarsana Kalluru } 77132a7a570SSudarsana Kalluru 772133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 773133fac0eSSudarsana Kalluru { 774133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 775133fac0eSSudarsana Kalluru struct qed_link_output current_link; 776133fac0eSSudarsana Kalluru 777133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 778133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 779133fac0eSSudarsana Kalluru 780133fac0eSSudarsana Kalluru return current_link.link_up; 781133fac0eSSudarsana Kalluru } 782133fac0eSSudarsana Kalluru 783ccfa110cSSudarsana Reddy Kalluru static int qede_flash_device(struct net_device *dev, 784ccfa110cSSudarsana Reddy Kalluru struct ethtool_flash *flash) 785ccfa110cSSudarsana Reddy Kalluru { 786ccfa110cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 787ccfa110cSSudarsana Reddy Kalluru 788ccfa110cSSudarsana Reddy Kalluru return edev->ops->common->nvm_flash(edev->cdev, flash->data); 789ccfa110cSSudarsana Reddy Kalluru } 790ccfa110cSSudarsana Reddy Kalluru 791d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 792d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 793d552fa84SSudarsana Reddy Kalluru { 794bf5a94bfSRahul Verma void *rx_handle = NULL, *tx_handle = NULL; 795d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 796bf5a94bfSRahul Verma u16 rx_coal, tx_coal, i, rc = 0; 797bf5a94bfSRahul Verma struct qede_fastpath *fp; 798bf5a94bfSRahul Verma 799bf5a94bfSRahul Verma rx_coal = QED_DEFAULT_RX_USECS; 800bf5a94bfSRahul Verma tx_coal = QED_DEFAULT_TX_USECS; 801d552fa84SSudarsana Reddy Kalluru 802d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 803d2890deaSSudarsana Reddy Kalluru 804bf5a94bfSRahul Verma __qede_lock(edev); 805bf5a94bfSRahul Verma if (edev->state == QEDE_STATE_OPEN) { 806bf5a94bfSRahul Verma for_each_queue(i) { 807bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 808d552fa84SSudarsana Reddy Kalluru 809bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_RX) { 810bf5a94bfSRahul Verma rx_handle = fp->rxq->handle; 811bf5a94bfSRahul Verma break; 812bf5a94bfSRahul Verma } 813bf5a94bfSRahul Verma } 814bf5a94bfSRahul Verma 815bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle); 816bf5a94bfSRahul Verma if (rc) { 817bf5a94bfSRahul Verma DP_INFO(edev, "Read Rx coalesce error\n"); 818bf5a94bfSRahul Verma goto out; 819bf5a94bfSRahul Verma } 820bf5a94bfSRahul Verma 821bf5a94bfSRahul Verma for_each_queue(i) { 8225e7baf0fSManish Chopra struct qede_tx_queue *txq; 8235e7baf0fSManish Chopra 824bf5a94bfSRahul Verma fp = &edev->fp_array[i]; 8255e7baf0fSManish Chopra 8265e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 8275e7baf0fSManish Chopra * coalescing value, so no need to iterate over 8285e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 8295e7baf0fSManish Chopra */ 830bf5a94bfSRahul Verma if (fp->type & QEDE_FASTPATH_TX) { 8315e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 8325e7baf0fSManish Chopra tx_handle = txq->handle; 833bf5a94bfSRahul Verma break; 834bf5a94bfSRahul Verma } 835bf5a94bfSRahul Verma } 836bf5a94bfSRahul Verma 837bf5a94bfSRahul Verma rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle); 838bf5a94bfSRahul Verma if (rc) 839bf5a94bfSRahul Verma DP_INFO(edev, "Read Tx coalesce error\n"); 840bf5a94bfSRahul Verma } 841bf5a94bfSRahul Verma 842bf5a94bfSRahul Verma out: 843bf5a94bfSRahul Verma __qede_unlock(edev); 844bf5a94bfSRahul Verma 845bf5a94bfSRahul Verma coal->rx_coalesce_usecs = rx_coal; 846bf5a94bfSRahul Verma coal->tx_coalesce_usecs = tx_coal; 847bf5a94bfSRahul Verma 848bf5a94bfSRahul Verma return rc; 849d552fa84SSudarsana Reddy Kalluru } 850d552fa84SSudarsana Reddy Kalluru 851d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 852d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 853d552fa84SSudarsana Reddy Kalluru { 854d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 855477f2d14SRahul Verma struct qede_fastpath *fp; 856d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 857477f2d14SRahul Verma u16 rxc, txc; 858d552fa84SSudarsana Reddy Kalluru 859d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 860d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 861d552fa84SSudarsana Reddy Kalluru return -EINVAL; 862d552fa84SSudarsana Reddy Kalluru } 863d552fa84SSudarsana Reddy Kalluru 864d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 865d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 866d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 867d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 868477f2d14SRahul Verma coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" : 869477f2d14SRahul Verma "tx", QED_COALESCE_MAX); 870d552fa84SSudarsana Reddy Kalluru return -EINVAL; 871d552fa84SSudarsana Reddy Kalluru } 872d552fa84SSudarsana Reddy Kalluru 873d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 874d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 8759a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 876477f2d14SRahul Verma fp = &edev->fp_array[i]; 877477f2d14SRahul Verma 878477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 879477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 880477f2d14SRahul Verma rxc, 0, 881477f2d14SRahul Verma fp->rxq->handle); 882d552fa84SSudarsana Reddy Kalluru if (rc) { 883477f2d14SRahul Verma DP_INFO(edev, 884477f2d14SRahul Verma "Set RX coalesce error, rc = %d\n", rc); 885d552fa84SSudarsana Reddy Kalluru return rc; 886d552fa84SSudarsana Reddy Kalluru } 887d552fa84SSudarsana Reddy Kalluru } 888d552fa84SSudarsana Reddy Kalluru 889477f2d14SRahul Verma if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 8905e7baf0fSManish Chopra struct qede_tx_queue *txq; 8915e7baf0fSManish Chopra 8925e7baf0fSManish Chopra /* All TX queues of given fastpath uses same 8935e7baf0fSManish Chopra * coalescing value, so no need to iterate over 8945e7baf0fSManish Chopra * all TCs, TC0 txq should suffice. 8955e7baf0fSManish Chopra */ 8965e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 8975e7baf0fSManish Chopra 898477f2d14SRahul Verma rc = edev->ops->common->set_coalesce(edev->cdev, 899477f2d14SRahul Verma 0, txc, 9005e7baf0fSManish Chopra txq->handle); 901477f2d14SRahul Verma if (rc) { 902477f2d14SRahul Verma DP_INFO(edev, 903477f2d14SRahul Verma "Set TX coalesce error, rc = %d\n", rc); 904477f2d14SRahul Verma return rc; 905477f2d14SRahul Verma } 906477f2d14SRahul Verma } 907477f2d14SRahul Verma } 908477f2d14SRahul Verma 909d552fa84SSudarsana Reddy Kalluru return rc; 910d552fa84SSudarsana Reddy Kalluru } 911d552fa84SSudarsana Reddy Kalluru 91201ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 91301ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 91401ef7e05SSudarsana Kalluru { 91501ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 91601ef7e05SSudarsana Kalluru 91701ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 91801ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 91901ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 92001ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 92101ef7e05SSudarsana Kalluru } 92201ef7e05SSudarsana Kalluru 92301ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 92401ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 92501ef7e05SSudarsana Kalluru { 92601ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 92701ef7e05SSudarsana Kalluru 92801ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 92901ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 93001ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 93101ef7e05SSudarsana Kalluru 93201ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 93301ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 93401ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 93501ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 93601ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 93701ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 93801ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 93901ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 94001ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 94101ef7e05SSudarsana Kalluru return -EINVAL; 94201ef7e05SSudarsana Kalluru } 94301ef7e05SSudarsana Kalluru 94401ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 94501ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 94601ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 94701ef7e05SSudarsana Kalluru 948567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 94901ef7e05SSudarsana Kalluru 95001ef7e05SSudarsana Kalluru return 0; 95101ef7e05SSudarsana Kalluru } 95201ef7e05SSudarsana Kalluru 9530f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 9540f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 9550f7db144SSudarsana Kalluru { 9560f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9570f7db144SSudarsana Kalluru struct qed_link_output current_link; 9580f7db144SSudarsana Kalluru 9590f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 9600f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 9610f7db144SSudarsana Kalluru 9620f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 9630f7db144SSudarsana Kalluru epause->autoneg = true; 9640f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 9650f7db144SSudarsana Kalluru epause->rx_pause = true; 9660f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 9670f7db144SSudarsana Kalluru epause->tx_pause = true; 9680f7db144SSudarsana Kalluru 9690f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 9700f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 9710f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 9720f7db144SSudarsana Kalluru epause->tx_pause); 9730f7db144SSudarsana Kalluru } 9740f7db144SSudarsana Kalluru 9750f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 9760f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 9770f7db144SSudarsana Kalluru { 9780f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9790f7db144SSudarsana Kalluru struct qed_link_params params; 9800f7db144SSudarsana Kalluru struct qed_link_output current_link; 9810f7db144SSudarsana Kalluru 982fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 9830f7db144SSudarsana Kalluru DP_INFO(edev, 984fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 9850f7db144SSudarsana Kalluru return -EOPNOTSUPP; 9860f7db144SSudarsana Kalluru } 9870f7db144SSudarsana Kalluru 9880f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 9890f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 9900f7db144SSudarsana Kalluru 9910f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 9920f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 9930f7db144SSudarsana Kalluru if (epause->autoneg) { 994d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 9950f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 9960f7db144SSudarsana Kalluru return -EINVAL; 9970f7db144SSudarsana Kalluru } 9980f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 9990f7db144SSudarsana Kalluru } 10000f7db144SSudarsana Kalluru if (epause->rx_pause) 10010f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 10020f7db144SSudarsana Kalluru if (epause->tx_pause) 10030f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 10040f7db144SSudarsana Kalluru 10050f7db144SSudarsana Kalluru params.link_up = true; 10060f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 10070f7db144SSudarsana Kalluru 10080f7db144SSudarsana Kalluru return 0; 10090f7db144SSudarsana Kalluru } 10100f7db144SSudarsana Kalluru 1011e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 1012e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 1013e0971c83STomer Tayar { 1014e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 1015e0971c83STomer Tayar 1016e0971c83STomer Tayar regs->version = 0; 1017e0971c83STomer Tayar memset(buffer, 0, regs->len); 1018e0971c83STomer Tayar 1019e0971c83STomer Tayar if (edev->ops && edev->ops->common) 1020e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 1021e0971c83STomer Tayar } 1022e0971c83STomer Tayar 1023e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 1024e0971c83STomer Tayar { 1025e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 1026e0971c83STomer Tayar 1027e0971c83STomer Tayar if (edev->ops && edev->ops->common) 1028e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 1029e0971c83STomer Tayar else 1030e0971c83STomer Tayar return -EINVAL; 1031e0971c83STomer Tayar } 1032e0971c83STomer Tayar 1033567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev, 1034567b3c12SMintz, Yuval struct qede_reload_args *args) 1035133fac0eSSudarsana Kalluru { 1036567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu; 1037133fac0eSSudarsana Kalluru } 1038133fac0eSSudarsana Kalluru 1039133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 1040133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 1041133fac0eSSudarsana Kalluru { 1042133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 1043567b3c12SMintz, Yuval struct qede_reload_args args; 1044133fac0eSSudarsana Kalluru 1045133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 1046133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 1047133fac0eSSudarsana Kalluru 104818c602deSMichael Chan if (new_mtu > PAGE_SIZE) 104918c602deSMichael Chan ndev->features &= ~NETIF_F_GRO_HW; 105018c602deSMichael Chan 1051133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */ 1052567b3c12SMintz, Yuval args.u.mtu = new_mtu; 1053567b3c12SMintz, Yuval args.func = &qede_update_mtu; 1054567b3c12SMintz, Yuval qede_reload(edev, &args, false); 1055133fac0eSSudarsana Kalluru 1056567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu); 10570fefbfbaSSudarsana Kalluru 1058133fac0eSSudarsana Kalluru return 0; 1059133fac0eSSudarsana Kalluru } 1060133fac0eSSudarsana Kalluru 10618edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 10628edf049dSSudarsana Kalluru struct ethtool_channels *channels) 10638edf049dSSudarsana Kalluru { 10648edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10658edf049dSSudarsana Kalluru 10668edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 1067bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 1068bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 10699a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 10709a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 10719a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 10729a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 10738edf049dSSudarsana Kalluru } 10748edf049dSSudarsana Kalluru 10758edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 10768edf049dSSudarsana Kalluru struct ethtool_channels *channels) 10778edf049dSSudarsana Kalluru { 10788edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 10799a4d7e86SSudarsana Reddy Kalluru u32 count; 10808edf049dSSudarsana Kalluru 10818edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10828edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 10838edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 10848edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 10858edf049dSSudarsana Kalluru 10869a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 10879a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 10889a4d7e86SSudarsana Reddy Kalluru 10899a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 10909a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 10918edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10928edf049dSSudarsana Kalluru "command parameters not supported\n"); 10938edf049dSSudarsana Kalluru return -EINVAL; 10948edf049dSSudarsana Kalluru } 10958edf049dSSudarsana Kalluru 10969a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 10979a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 10989a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 10999a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 11009a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 11019a4d7e86SSudarsana Reddy Kalluru } 11029a4d7e86SSudarsana Reddy Kalluru 11039a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 11049a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 11059a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 11069a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 11079a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 11089a4d7e86SSudarsana Reddy Kalluru } 11099a4d7e86SSudarsana Reddy Kalluru 11108edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 11119a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 11129a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 11139a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 11148edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 11158edf049dSSudarsana Kalluru "No change in active parameters\n"); 11168edf049dSSudarsana Kalluru return 0; 11178edf049dSSudarsana Kalluru } 11188edf049dSSudarsana Kalluru 11198edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 11209a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 11219a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 11229a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 11238edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 11249a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 11258edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 11268edf049dSSudarsana Kalluru return -EINVAL; 11278edf049dSSudarsana Kalluru } 11288edf049dSSudarsana Kalluru 11298edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 11309a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 11319a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 11329a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 1133ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 1134ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 1135ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 1136f29ffdb6SMintz, Yuval memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table)); 1137ed0dd915SSudarsana Reddy Kalluru } 1138ed0dd915SSudarsana Reddy Kalluru 1139567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 11408edf049dSSudarsana Kalluru 11418edf049dSSudarsana Kalluru return 0; 11428edf049dSSudarsana Kalluru } 11438edf049dSSudarsana Kalluru 11444c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev, 11454c55215cSSudarsana Reddy Kalluru struct ethtool_ts_info *info) 11464c55215cSSudarsana Reddy Kalluru { 11474c55215cSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 11484c55215cSSudarsana Reddy Kalluru 11494c55215cSSudarsana Reddy Kalluru return qede_ptp_get_ts_info(edev, info); 11504c55215cSSudarsana Reddy Kalluru } 11514c55215cSSudarsana Reddy Kalluru 11523d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 11533d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 11543d971cbdSSudarsana Kalluru { 11553d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 11563d971cbdSSudarsana Kalluru u8 led_state = 0; 11573d971cbdSSudarsana Kalluru 11583d971cbdSSudarsana Kalluru switch (state) { 11593d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 11603d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 11613d971cbdSSudarsana Kalluru 11623d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 11633d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 11643d971cbdSSudarsana Kalluru break; 11653d971cbdSSudarsana Kalluru 11663d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 11673d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 11683d971cbdSSudarsana Kalluru break; 11693d971cbdSSudarsana Kalluru 11703d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 11713d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 11723d971cbdSSudarsana Kalluru break; 11733d971cbdSSudarsana Kalluru } 11743d971cbdSSudarsana Kalluru 11753d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 11763d971cbdSSudarsana Kalluru 11773d971cbdSSudarsana Kalluru return 0; 11783d971cbdSSudarsana Kalluru } 11793d971cbdSSudarsana Kalluru 1180961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1181961acdeaSSudarsana Reddy Kalluru { 1182961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 1183961acdeaSSudarsana Reddy Kalluru 1184961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1185961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1186961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1187961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1188961acdeaSSudarsana Reddy Kalluru break; 1189961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1190f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV4_UDP) 1191961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1192961acdeaSSudarsana Reddy Kalluru break; 1193961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1194f29ffdb6SMintz, Yuval if (edev->rss_caps & QED_RSS_IPV6_UDP) 1195961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 1196961acdeaSSudarsana Reddy Kalluru break; 1197961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1198961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1199961acdeaSSudarsana Reddy Kalluru break; 1200961acdeaSSudarsana Reddy Kalluru default: 1201961acdeaSSudarsana Reddy Kalluru info->data = 0; 1202961acdeaSSudarsana Reddy Kalluru break; 1203961acdeaSSudarsana Reddy Kalluru } 1204961acdeaSSudarsana Reddy Kalluru 1205961acdeaSSudarsana Reddy Kalluru return 0; 1206961acdeaSSudarsana Reddy Kalluru } 1207961acdeaSSudarsana Reddy Kalluru 1208961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 1209ec9b8dbdSChopra, Manish u32 *rule_locs) 1210961acdeaSSudarsana Reddy Kalluru { 1211961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1212ec9b8dbdSChopra, Manish int rc = 0; 1213961acdeaSSudarsana Reddy Kalluru 1214961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1215961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 12169a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 1217ec9b8dbdSChopra, Manish break; 1218961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 1219ec9b8dbdSChopra, Manish rc = qede_get_rss_flags(edev, info); 1220ec9b8dbdSChopra, Manish break; 1221ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLCNT: 1222ec9b8dbdSChopra, Manish info->rule_cnt = qede_get_arfs_filter_count(edev); 1223ec9b8dbdSChopra, Manish info->data = QEDE_RFS_MAX_FLTR; 1224ec9b8dbdSChopra, Manish break; 1225ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRULE: 1226ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_entry(edev, info); 1227ec9b8dbdSChopra, Manish break; 1228ec9b8dbdSChopra, Manish case ETHTOOL_GRXCLSRLALL: 1229ec9b8dbdSChopra, Manish rc = qede_get_cls_rule_all(edev, info, rule_locs); 1230ec9b8dbdSChopra, Manish break; 1231961acdeaSSudarsana Reddy Kalluru default: 1232961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 1233ec9b8dbdSChopra, Manish rc = -EOPNOTSUPP; 1234961acdeaSSudarsana Reddy Kalluru } 1235ec9b8dbdSChopra, Manish 1236ec9b8dbdSChopra, Manish return rc; 1237961acdeaSSudarsana Reddy Kalluru } 1238961acdeaSSudarsana Reddy Kalluru 1239961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 1240961acdeaSSudarsana Reddy Kalluru { 1241f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1242961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 1243f29ffdb6SMintz, Yuval int rc = 0; 1244961acdeaSSudarsana Reddy Kalluru 1245961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1246961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 1247961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 1248961acdeaSSudarsana Reddy Kalluru 1249961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 1250961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 1251961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 1252961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 1253961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 1254961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1255961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1256961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1257961acdeaSSudarsana Reddy Kalluru } 1258961acdeaSSudarsana Reddy Kalluru return 0; 1259961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 1260961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1261961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1262961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1263961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 1264961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1265961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1266961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1267961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 1268961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1269961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1270961acdeaSSudarsana Reddy Kalluru } else { 1271961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1272961acdeaSSudarsana Reddy Kalluru } 1273961acdeaSSudarsana Reddy Kalluru break; 1274961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1275961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1276961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1277961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1278961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 1279961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1280961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1281961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1282961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 1283961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1284961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1285961acdeaSSudarsana Reddy Kalluru } else { 1286961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1287961acdeaSSudarsana Reddy Kalluru } 1288961acdeaSSudarsana Reddy Kalluru break; 1289961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1290961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1291961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 1292961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 1293961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1294961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1295961acdeaSSudarsana Reddy Kalluru } 1296961acdeaSSudarsana Reddy Kalluru return 0; 1297961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1298961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1299961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1300961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1301961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1302961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1303961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1304961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1305961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1306961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1307961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1308961acdeaSSudarsana Reddy Kalluru if (info->data) { 1309961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1310961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1311961acdeaSSudarsana Reddy Kalluru } 1312961acdeaSSudarsana Reddy Kalluru return 0; 1313961acdeaSSudarsana Reddy Kalluru default: 1314961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1315961acdeaSSudarsana Reddy Kalluru } 1316961acdeaSSudarsana Reddy Kalluru 1317961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1318f29ffdb6SMintz, Yuval if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps)) 1319961acdeaSSudarsana Reddy Kalluru return 0; 1320961acdeaSSudarsana Reddy Kalluru 1321961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1322f29ffdb6SMintz, Yuval edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps); 1323961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1324961acdeaSSudarsana Reddy Kalluru 1325961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1326f29ffdb6SMintz, Yuval __qede_lock(edev); 1327f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1328f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1329f29ffdb6SMintz, Yuval if (!vport_update_params) { 1330f29ffdb6SMintz, Yuval __qede_unlock(edev); 1331f29ffdb6SMintz, Yuval return -ENOMEM; 1332961acdeaSSudarsana Reddy Kalluru } 1333f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1334f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1335f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1336f29ffdb6SMintz, Yuval vfree(vport_update_params); 1337f29ffdb6SMintz, Yuval } 1338f29ffdb6SMintz, Yuval __qede_unlock(edev); 1339961acdeaSSudarsana Reddy Kalluru 1340f29ffdb6SMintz, Yuval return rc; 1341961acdeaSSudarsana Reddy Kalluru } 1342961acdeaSSudarsana Reddy Kalluru 1343961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1344961acdeaSSudarsana Reddy Kalluru { 1345961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 13463f2a2b8bSChopra, Manish int rc; 1347961acdeaSSudarsana Reddy Kalluru 1348961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1349961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 13503f2a2b8bSChopra, Manish rc = qede_set_rss_flags(edev, info); 13513f2a2b8bSChopra, Manish break; 13523f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLINS: 13533f2a2b8bSChopra, Manish rc = qede_add_cls_rule(edev, info); 13543f2a2b8bSChopra, Manish break; 13553f2a2b8bSChopra, Manish case ETHTOOL_SRXCLSRLDEL: 13562ce9c93eSManish Chopra rc = qede_delete_flow_filter(edev, info->fs.location); 13573f2a2b8bSChopra, Manish break; 1358961acdeaSSudarsana Reddy Kalluru default: 1359961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 13603f2a2b8bSChopra, Manish rc = -EOPNOTSUPP; 1361961acdeaSSudarsana Reddy Kalluru } 13623f2a2b8bSChopra, Manish 13633f2a2b8bSChopra, Manish return rc; 1364961acdeaSSudarsana Reddy Kalluru } 1365961acdeaSSudarsana Reddy Kalluru 1366961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1367961acdeaSSudarsana Reddy Kalluru { 1368961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1369961acdeaSSudarsana Reddy Kalluru } 1370961acdeaSSudarsana Reddy Kalluru 1371961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1372961acdeaSSudarsana Reddy Kalluru { 1373961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1374961acdeaSSudarsana Reddy Kalluru 1375f29ffdb6SMintz, Yuval return sizeof(edev->rss_key); 1376961acdeaSSudarsana Reddy Kalluru } 1377961acdeaSSudarsana Reddy Kalluru 1378961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1379961acdeaSSudarsana Reddy Kalluru { 1380961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1381961acdeaSSudarsana Reddy Kalluru int i; 1382961acdeaSSudarsana Reddy Kalluru 1383961acdeaSSudarsana Reddy Kalluru if (hfunc) 1384961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1385961acdeaSSudarsana Reddy Kalluru 1386961acdeaSSudarsana Reddy Kalluru if (!indir) 1387961acdeaSSudarsana Reddy Kalluru return 0; 1388961acdeaSSudarsana Reddy Kalluru 1389961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1390f29ffdb6SMintz, Yuval indir[i] = edev->rss_ind_table[i]; 1391961acdeaSSudarsana Reddy Kalluru 1392961acdeaSSudarsana Reddy Kalluru if (key) 1393f29ffdb6SMintz, Yuval memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev)); 1394961acdeaSSudarsana Reddy Kalluru 1395961acdeaSSudarsana Reddy Kalluru return 0; 1396961acdeaSSudarsana Reddy Kalluru } 1397961acdeaSSudarsana Reddy Kalluru 1398961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1399961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1400961acdeaSSudarsana Reddy Kalluru { 1401f29ffdb6SMintz, Yuval struct qed_update_vport_params *vport_update_params; 1402961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1403f29ffdb6SMintz, Yuval int i, rc = 0; 1404961acdeaSSudarsana Reddy Kalluru 1405ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1406ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1407ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1408ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1409ba300ce3SSudarsana Reddy Kalluru } 1410ba300ce3SSudarsana Reddy Kalluru 1411961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1412961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1413961acdeaSSudarsana Reddy Kalluru 1414961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1415961acdeaSSudarsana Reddy Kalluru return 0; 1416961acdeaSSudarsana Reddy Kalluru 1417961acdeaSSudarsana Reddy Kalluru if (indir) { 1418961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1419f29ffdb6SMintz, Yuval edev->rss_ind_table[i] = indir[i]; 1420961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1421961acdeaSSudarsana Reddy Kalluru } 1422961acdeaSSudarsana Reddy Kalluru 1423961acdeaSSudarsana Reddy Kalluru if (key) { 1424f29ffdb6SMintz, Yuval memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev)); 1425961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1426961acdeaSSudarsana Reddy Kalluru } 1427961acdeaSSudarsana Reddy Kalluru 1428f29ffdb6SMintz, Yuval __qede_lock(edev); 1429f29ffdb6SMintz, Yuval if (edev->state == QEDE_STATE_OPEN) { 1430f29ffdb6SMintz, Yuval vport_update_params = vzalloc(sizeof(*vport_update_params)); 1431f29ffdb6SMintz, Yuval if (!vport_update_params) { 1432f29ffdb6SMintz, Yuval __qede_unlock(edev); 1433f29ffdb6SMintz, Yuval return -ENOMEM; 1434961acdeaSSudarsana Reddy Kalluru } 1435f29ffdb6SMintz, Yuval qede_fill_rss_params(edev, &vport_update_params->rss_params, 1436f29ffdb6SMintz, Yuval &vport_update_params->update_rss_flg); 1437f29ffdb6SMintz, Yuval rc = edev->ops->vport_update(edev->cdev, vport_update_params); 1438f29ffdb6SMintz, Yuval vfree(vport_update_params); 1439f29ffdb6SMintz, Yuval } 1440f29ffdb6SMintz, Yuval __qede_unlock(edev); 1441961acdeaSSudarsana Reddy Kalluru 1442f29ffdb6SMintz, Yuval return rc; 1443961acdeaSSudarsana Reddy Kalluru } 1444961acdeaSSudarsana Reddy Kalluru 144516f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 144616f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 144716f46bf0SSudarsana Reddy Kalluru { 144816f46bf0SSudarsana Reddy Kalluru int i; 144916f46bf0SSudarsana Reddy Kalluru 145016f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 145116f46bf0SSudarsana Reddy Kalluru return; 145216f46bf0SSudarsana Reddy Kalluru 14539a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 145416f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 145516f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 145616f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 145716f46bf0SSudarsana Reddy Kalluru } 145816f46bf0SSudarsana Reddy Kalluru } 145916f46bf0SSudarsana Reddy Kalluru 146016f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 146116f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 146216f46bf0SSudarsana Reddy Kalluru { 146316f46bf0SSudarsana Reddy Kalluru int i; 146416f46bf0SSudarsana Reddy Kalluru 14659a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 146616f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 146716f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 146816f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 146916f46bf0SSudarsana Reddy Kalluru } 147016f46bf0SSudarsana Reddy Kalluru } 147116f46bf0SSudarsana Reddy Kalluru 147216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 147316f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 147416f46bf0SSudarsana Reddy Kalluru { 14759a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 147616f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 147716f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 147848848a06SManish Chopra int i, idx; 147948848a06SManish Chopra u16 val; 148016f46bf0SSudarsana Reddy Kalluru 14819a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 14825e7baf0fSManish Chopra struct qede_fastpath *fp = &edev->fp_array[i]; 14835e7baf0fSManish Chopra 14845e7baf0fSManish Chopra if (fp->type & QEDE_FASTPATH_TX) { 14855e7baf0fSManish Chopra txq = QEDE_FP_TC0_TXQ(fp); 14869a4d7e86SSudarsana Reddy Kalluru break; 14879a4d7e86SSudarsana Reddy Kalluru } 14889a4d7e86SSudarsana Reddy Kalluru } 14899a4d7e86SSudarsana Reddy Kalluru 14909a4d7e86SSudarsana Reddy Kalluru if (!txq) { 14919a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 14929a4d7e86SSudarsana Reddy Kalluru return -1; 14939a4d7e86SSudarsana Reddy Kalluru } 14949a4d7e86SSudarsana Reddy Kalluru 149516f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 14965a052d62SSudarsana Reddy Kalluru idx = txq->sw_tx_prod; 1497cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = skb; 149816f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 149916f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 150016f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 150116f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1502351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 150348848a06SManish Chopra val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT; 150448848a06SManish Chopra first_bd->data.bitfields |= cpu_to_le16(val); 150516f46bf0SSudarsana Reddy Kalluru 150616f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 150716f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 150816f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 150916f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 151016f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 151116f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 151216f46bf0SSudarsana Reddy Kalluru } 151316f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 151416f46bf0SSudarsana Reddy Kalluru 151516f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 151616f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 15175a052d62SSudarsana Reddy Kalluru txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers; 151816f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 151948848a06SManish Chopra val = qed_chain_get_prod_idx(&txq->tx_pbl); 152048848a06SManish Chopra txq->tx_db.data.bd_prod = cpu_to_le16(val); 152116f46bf0SSudarsana Reddy Kalluru 152216f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 152316f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 152416f46bf0SSudarsana Reddy Kalluru */ 152516f46bf0SSudarsana Reddy Kalluru wmb(); 152616f46bf0SSudarsana Reddy Kalluru barrier(); 152716f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 152816f46bf0SSudarsana Reddy Kalluru 152916f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 153016f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 153116f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 153216f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 153316f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 153416f46bf0SSudarsana Reddy Kalluru */ 153516f46bf0SSudarsana Reddy Kalluru mmiowb(); 153616f46bf0SSudarsana Reddy Kalluru 153716f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 153816f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 153916f46bf0SSudarsana Reddy Kalluru break; 154016f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 154116f46bf0SSudarsana Reddy Kalluru } 154216f46bf0SSudarsana Reddy Kalluru 154316f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 154416f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 154516f46bf0SSudarsana Reddy Kalluru return -1; 154616f46bf0SSudarsana Reddy Kalluru } 154716f46bf0SSudarsana Reddy Kalluru 154816f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1549fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 155016f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 15515a052d62SSudarsana Reddy Kalluru txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers; 1552cb6aeb07SMintz, Yuval txq->sw_tx_ring.skbs[idx].skb = NULL; 155316f46bf0SSudarsana Reddy Kalluru 155416f46bf0SSudarsana Reddy Kalluru return 0; 155516f46bf0SSudarsana Reddy Kalluru } 155616f46bf0SSudarsana Reddy Kalluru 155716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 155816f46bf0SSudarsana Reddy Kalluru { 155916f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 156016f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 15619a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 156216f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 156316f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1564afe981d6SSudarsana Reddy Kalluru int i, iter, rc = 0; 156516f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 156616f46bf0SSudarsana Reddy Kalluru 15679a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 15689a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 15699a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 15709a4d7e86SSudarsana Reddy Kalluru break; 15719a4d7e86SSudarsana Reddy Kalluru } 15729a4d7e86SSudarsana Reddy Kalluru } 15739a4d7e86SSudarsana Reddy Kalluru 15749a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 15759a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 15769a4d7e86SSudarsana Reddy Kalluru return -1; 15779a4d7e86SSudarsana Reddy Kalluru } 15789a4d7e86SSudarsana Reddy Kalluru 157916f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 158016f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 158116f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 158216f46bf0SSudarsana Reddy Kalluru */ 1583afe981d6SSudarsana Reddy Kalluru for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) { 158416f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1585837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1586837d4eb6SSudarsana Reddy Kalluru continue; 158716f46bf0SSudarsana Reddy Kalluru } 158816f46bf0SSudarsana Reddy Kalluru 158916f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 159016f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 159116f46bf0SSudarsana Reddy Kalluru 1592837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1593837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1594837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1595837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1596837d4eb6SSudarsana Reddy Kalluru * CQE. 159716f46bf0SSudarsana Reddy Kalluru */ 159816f46bf0SSudarsana Reddy Kalluru rmb(); 159916f46bf0SSudarsana Reddy Kalluru 160016f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 160116f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 160216f46bf0SSudarsana Reddy Kalluru 160316f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 160416f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 160516f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 160616f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 160716f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 160816f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1609837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 16108a863397SManish Chopra sw_rx_data->page_offset + 16118a863397SManish Chopra rxq->rx_headroom); 1612837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1613837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1614837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 161516f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 161616f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1617837d4eb6SSudarsana Reddy Kalluru rc = -1; 1618837d4eb6SSudarsana Reddy Kalluru break; 161916f46bf0SSudarsana Reddy Kalluru } 162016f46bf0SSudarsana Reddy Kalluru 16219eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1622837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1623837d4eb6SSudarsana Reddy Kalluru break; 1624837d4eb6SSudarsana Reddy Kalluru } 162516f46bf0SSudarsana Reddy Kalluru 1626837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 16279eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1628837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1629837d4eb6SSudarsana Reddy Kalluru } 1630837d4eb6SSudarsana Reddy Kalluru 1631afe981d6SSudarsana Reddy Kalluru if (iter == QEDE_SELFTEST_POLL_COUNT) { 1632837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1633837d4eb6SSudarsana Reddy Kalluru return -1; 1634837d4eb6SSudarsana Reddy Kalluru } 1635837d4eb6SSudarsana Reddy Kalluru 1636837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1637837d4eb6SSudarsana Reddy Kalluru 1638837d4eb6SSudarsana Reddy Kalluru return rc; 163916f46bf0SSudarsana Reddy Kalluru } 164016f46bf0SSudarsana Reddy Kalluru 164116f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 164216f46bf0SSudarsana Reddy Kalluru { 164316f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 164416f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 164516f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 164616f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 164716f46bf0SSudarsana Reddy Kalluru u8 *packet; 164816f46bf0SSudarsana Reddy Kalluru 164916f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 165016f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 165116f46bf0SSudarsana Reddy Kalluru return -EINVAL; 165216f46bf0SSudarsana Reddy Kalluru } 165316f46bf0SSudarsana Reddy Kalluru 165416f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 165516f46bf0SSudarsana Reddy Kalluru 165616f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 165716f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 165816f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 165916f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 166016f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 166116f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 166216f46bf0SSudarsana Reddy Kalluru 166316f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 166416f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 166516f46bf0SSudarsana Reddy Kalluru 166616f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 166716f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 166816f46bf0SSudarsana Reddy Kalluru 166916f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 167016f46bf0SSudarsana Reddy Kalluru if (!skb) { 167116f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 167216f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 167316f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 167416f46bf0SSudarsana Reddy Kalluru } 167516f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 167616f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 167716f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 167816f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 167916f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 168016f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 168116f46bf0SSudarsana Reddy Kalluru 168216f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 168316f46bf0SSudarsana Reddy Kalluru if (rc) 168416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 168516f46bf0SSudarsana Reddy Kalluru 168616f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 168716f46bf0SSudarsana Reddy Kalluru if (rc) 168816f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 168916f46bf0SSudarsana Reddy Kalluru 169016f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 169116f46bf0SSudarsana Reddy Kalluru 169216f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 169316f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 169416f46bf0SSudarsana Reddy Kalluru 169516f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 169616f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 169716f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 169816f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 169916f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 170016f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 170116f46bf0SSudarsana Reddy Kalluru 170216f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 170316f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 170416f46bf0SSudarsana Reddy Kalluru 170516f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 170616f46bf0SSudarsana Reddy Kalluru 170716f46bf0SSudarsana Reddy Kalluru return rc; 170816f46bf0SSudarsana Reddy Kalluru } 170916f46bf0SSudarsana Reddy Kalluru 17103044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 17113044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 17123044a02eSSudarsana Reddy Kalluru { 17133044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 17143044a02eSSudarsana Reddy Kalluru 17153044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 17163044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 17173044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 17183044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 17193044a02eSSudarsana Reddy Kalluru 17203044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 17213044a02eSSudarsana Reddy Kalluru 172216f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 172316f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 172416f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 172516f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 172616f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 172716f46bf0SSudarsana Reddy Kalluru } 172816f46bf0SSudarsana Reddy Kalluru } 172916f46bf0SSudarsana Reddy Kalluru 17303044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 17313044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 17323044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17333044a02eSSudarsana Reddy Kalluru } 17343044a02eSSudarsana Reddy Kalluru 17353044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 17363044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 17373044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17383044a02eSSudarsana Reddy Kalluru } 17393044a02eSSudarsana Reddy Kalluru 17403044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 17413044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 17423044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17433044a02eSSudarsana Reddy Kalluru } 17443044a02eSSudarsana Reddy Kalluru 17453044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 17463044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 17473044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 17483044a02eSSudarsana Reddy Kalluru } 17497a4b21b7SMintz, Yuval 17507a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 17517a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 17527a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 17537a4b21b7SMintz, Yuval } 17543044a02eSSudarsana Reddy Kalluru } 17553044a02eSSudarsana Reddy Kalluru 17563d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 17573d789994SManish Chopra const struct ethtool_tunable *tuna, 17583d789994SManish Chopra const void *data) 17593d789994SManish Chopra { 17603d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 17613d789994SManish Chopra u32 val; 17623d789994SManish Chopra 17633d789994SManish Chopra switch (tuna->id) { 17643d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 17653d789994SManish Chopra val = *(u32 *)data; 17663d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 17673d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 17683d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 17693d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 17703d789994SManish Chopra return -EINVAL; 17713d789994SManish Chopra } 17723d789994SManish Chopra 17733d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 17743d789994SManish Chopra break; 17753d789994SManish Chopra default: 17763d789994SManish Chopra return -EOPNOTSUPP; 17773d789994SManish Chopra } 17783d789994SManish Chopra 17793d789994SManish Chopra return 0; 17803d789994SManish Chopra } 17813d789994SManish Chopra 17823d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 17833d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 17843d789994SManish Chopra { 17853d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 17863d789994SManish Chopra 17873d789994SManish Chopra switch (tuna->id) { 17883d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 17893d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 17903d789994SManish Chopra break; 17913d789994SManish Chopra default: 17923d789994SManish Chopra return -EOPNOTSUPP; 17933d789994SManish Chopra } 17943d789994SManish Chopra 17953d789994SManish Chopra return 0; 17963d789994SManish Chopra } 17973d789994SManish Chopra 1798c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata) 1799c3dc48f7SSudarsana Reddy Kalluru { 1800c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1801c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1802c3dc48f7SSudarsana Reddy Kalluru 1803c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1804c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1805c3dc48f7SSudarsana Reddy Kalluru 1806c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1807c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1808c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1809c3dc48f7SSudarsana Reddy Kalluru } 1810c3dc48f7SSudarsana Reddy Kalluru 1811c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_1G_ADV) 1812c3dc48f7SSudarsana Reddy Kalluru edata->advertised = ADVERTISED_1000baseT_Full; 1813c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.adv_caps & QED_EEE_10G_ADV) 1814c3dc48f7SSudarsana Reddy Kalluru edata->advertised |= ADVERTISED_10000baseT_Full; 1815c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_1G_ADV) 1816c3dc48f7SSudarsana Reddy Kalluru edata->supported = ADVERTISED_1000baseT_Full; 1817c3dc48f7SSudarsana Reddy Kalluru if (current_link.sup_caps & QED_EEE_10G_ADV) 1818c3dc48f7SSudarsana Reddy Kalluru edata->supported |= ADVERTISED_10000baseT_Full; 1819c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV) 1820c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised = ADVERTISED_1000baseT_Full; 1821c3dc48f7SSudarsana Reddy Kalluru if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV) 1822c3dc48f7SSudarsana Reddy Kalluru edata->lp_advertised |= ADVERTISED_10000baseT_Full; 1823c3dc48f7SSudarsana Reddy Kalluru 1824c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_timer = current_link.eee.tx_lpi_timer; 1825c3dc48f7SSudarsana Reddy Kalluru edata->eee_enabled = current_link.eee.enable; 1826c3dc48f7SSudarsana Reddy Kalluru edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable; 1827c3dc48f7SSudarsana Reddy Kalluru edata->eee_active = current_link.eee_active; 1828c3dc48f7SSudarsana Reddy Kalluru 1829c3dc48f7SSudarsana Reddy Kalluru return 0; 1830c3dc48f7SSudarsana Reddy Kalluru } 1831c3dc48f7SSudarsana Reddy Kalluru 1832c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata) 1833c3dc48f7SSudarsana Reddy Kalluru { 1834c3dc48f7SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1835c3dc48f7SSudarsana Reddy Kalluru struct qed_link_output current_link; 1836c3dc48f7SSudarsana Reddy Kalluru struct qed_link_params params; 1837c3dc48f7SSudarsana Reddy Kalluru 1838c3dc48f7SSudarsana Reddy Kalluru if (!edev->ops->common->can_link_change(edev->cdev)) { 1839c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 1840c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1841c3dc48f7SSudarsana Reddy Kalluru } 1842c3dc48f7SSudarsana Reddy Kalluru 1843c3dc48f7SSudarsana Reddy Kalluru memset(¤t_link, 0, sizeof(current_link)); 1844c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 1845c3dc48f7SSudarsana Reddy Kalluru 1846c3dc48f7SSudarsana Reddy Kalluru if (!current_link.eee_supported) { 1847c3dc48f7SSudarsana Reddy Kalluru DP_INFO(edev, "EEE is not supported\n"); 1848c3dc48f7SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1849c3dc48f7SSudarsana Reddy Kalluru } 1850c3dc48f7SSudarsana Reddy Kalluru 1851c3dc48f7SSudarsana Reddy Kalluru memset(¶ms, 0, sizeof(params)); 1852c3dc48f7SSudarsana Reddy Kalluru params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG; 1853c3dc48f7SSudarsana Reddy Kalluru 1854c3dc48f7SSudarsana Reddy Kalluru if (!(edata->advertised & (ADVERTISED_1000baseT_Full | 1855c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) || 1856c3dc48f7SSudarsana Reddy Kalluru ((edata->advertised & (ADVERTISED_1000baseT_Full | 1857c3dc48f7SSudarsana Reddy Kalluru ADVERTISED_10000baseT_Full)) != 1858c3dc48f7SSudarsana Reddy Kalluru edata->advertised)) { 1859c3dc48f7SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1860c3dc48f7SSudarsana Reddy Kalluru "Invalid advertised capabilities %d\n", 1861c3dc48f7SSudarsana Reddy Kalluru edata->advertised); 1862c3dc48f7SSudarsana Reddy Kalluru return -EINVAL; 1863c3dc48f7SSudarsana Reddy Kalluru } 1864c3dc48f7SSudarsana Reddy Kalluru 1865c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_1000baseT_Full) 1866c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps = QED_EEE_1G_ADV; 1867c3dc48f7SSudarsana Reddy Kalluru if (edata->advertised & ADVERTISED_10000baseT_Full) 1868c3dc48f7SSudarsana Reddy Kalluru params.eee.adv_caps |= QED_EEE_10G_ADV; 1869c3dc48f7SSudarsana Reddy Kalluru params.eee.enable = edata->eee_enabled; 1870c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_enable = edata->tx_lpi_enabled; 1871c3dc48f7SSudarsana Reddy Kalluru params.eee.tx_lpi_timer = edata->tx_lpi_timer; 1872c3dc48f7SSudarsana Reddy Kalluru 1873c3dc48f7SSudarsana Reddy Kalluru params.link_up = true; 1874c3dc48f7SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 1875c3dc48f7SSudarsana Reddy Kalluru 1876c3dc48f7SSudarsana Reddy Kalluru return 0; 1877c3dc48f7SSudarsana Reddy Kalluru } 1878c3dc48f7SSudarsana Reddy Kalluru 187997df0d65SSudarsana Reddy Kalluru static int qede_get_module_info(struct net_device *dev, 188097df0d65SSudarsana Reddy Kalluru struct ethtool_modinfo *modinfo) 188197df0d65SSudarsana Reddy Kalluru { 188297df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 188397df0d65SSudarsana Reddy Kalluru u8 buf[4]; 188497df0d65SSudarsana Reddy Kalluru int rc; 188597df0d65SSudarsana Reddy Kalluru 188697df0d65SSudarsana Reddy Kalluru /* Read first 4 bytes to find the sfp type */ 188797df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 188897df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 0, 4); 188997df0d65SSudarsana Reddy Kalluru if (rc) { 189097df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading EEPROM data %d\n", rc); 189197df0d65SSudarsana Reddy Kalluru return rc; 189297df0d65SSudarsana Reddy Kalluru } 189397df0d65SSudarsana Reddy Kalluru 189497df0d65SSudarsana Reddy Kalluru switch (buf[0]) { 189597df0d65SSudarsana Reddy Kalluru case 0x3: /* SFP, SFP+, SFP-28 */ 189697df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8472; 189797df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 189897df0d65SSudarsana Reddy Kalluru break; 189997df0d65SSudarsana Reddy Kalluru case 0xc: /* QSFP */ 190097df0d65SSudarsana Reddy Kalluru case 0xd: /* QSFP+ */ 190197df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8436; 190297df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; 190397df0d65SSudarsana Reddy Kalluru break; 190497df0d65SSudarsana Reddy Kalluru case 0x11: /* QSFP-28 */ 190597df0d65SSudarsana Reddy Kalluru modinfo->type = ETH_MODULE_SFF_8636; 190697df0d65SSudarsana Reddy Kalluru modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; 190797df0d65SSudarsana Reddy Kalluru break; 190897df0d65SSudarsana Reddy Kalluru default: 190997df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]); 191097df0d65SSudarsana Reddy Kalluru return -EINVAL; 191197df0d65SSudarsana Reddy Kalluru } 191297df0d65SSudarsana Reddy Kalluru 191397df0d65SSudarsana Reddy Kalluru return 0; 191497df0d65SSudarsana Reddy Kalluru } 191597df0d65SSudarsana Reddy Kalluru 191697df0d65SSudarsana Reddy Kalluru static int qede_get_module_eeprom(struct net_device *dev, 191797df0d65SSudarsana Reddy Kalluru struct ethtool_eeprom *ee, u8 *data) 191897df0d65SSudarsana Reddy Kalluru { 191997df0d65SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 192097df0d65SSudarsana Reddy Kalluru u32 start_addr = ee->offset, size = 0; 192197df0d65SSudarsana Reddy Kalluru u8 *buf = data; 192297df0d65SSudarsana Reddy Kalluru int rc = 0; 192397df0d65SSudarsana Reddy Kalluru 192497df0d65SSudarsana Reddy Kalluru /* Read A0 section */ 192597df0d65SSudarsana Reddy Kalluru if (ee->offset < ETH_MODULE_SFF_8079_LEN) { 192697df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A0 section boundary */ 192797df0d65SSudarsana Reddy Kalluru if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN) 192897df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8079_LEN - ee->offset; 192997df0d65SSudarsana Reddy Kalluru else 193097df0d65SSudarsana Reddy Kalluru size = ee->len; 193197df0d65SSudarsana Reddy Kalluru 193297df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 193397df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A0, 193497df0d65SSudarsana Reddy Kalluru start_addr, size); 193597df0d65SSudarsana Reddy Kalluru if (rc) { 193697df0d65SSudarsana Reddy Kalluru DP_ERR(edev, "Failed reading A0 section %d\n", rc); 193797df0d65SSudarsana Reddy Kalluru return rc; 193897df0d65SSudarsana Reddy Kalluru } 193997df0d65SSudarsana Reddy Kalluru 194097df0d65SSudarsana Reddy Kalluru buf += size; 194197df0d65SSudarsana Reddy Kalluru start_addr += size; 194297df0d65SSudarsana Reddy Kalluru } 194397df0d65SSudarsana Reddy Kalluru 194497df0d65SSudarsana Reddy Kalluru /* Read A2 section */ 194597df0d65SSudarsana Reddy Kalluru if (start_addr >= ETH_MODULE_SFF_8079_LEN && 194697df0d65SSudarsana Reddy Kalluru start_addr < ETH_MODULE_SFF_8472_LEN) { 194797df0d65SSudarsana Reddy Kalluru size = ee->len - size; 194897df0d65SSudarsana Reddy Kalluru /* Limit transfer size to the A2 section boundary */ 194997df0d65SSudarsana Reddy Kalluru if (start_addr + size > ETH_MODULE_SFF_8472_LEN) 195097df0d65SSudarsana Reddy Kalluru size = ETH_MODULE_SFF_8472_LEN - start_addr; 195197df0d65SSudarsana Reddy Kalluru start_addr -= ETH_MODULE_SFF_8079_LEN; 195297df0d65SSudarsana Reddy Kalluru rc = edev->ops->common->read_module_eeprom(edev->cdev, buf, 195397df0d65SSudarsana Reddy Kalluru QED_I2C_DEV_ADDR_A2, 195497df0d65SSudarsana Reddy Kalluru start_addr, size); 195597df0d65SSudarsana Reddy Kalluru if (rc) { 195697df0d65SSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 195797df0d65SSudarsana Reddy Kalluru "Failed reading A2 section %d\n", rc); 195897df0d65SSudarsana Reddy Kalluru return 0; 195997df0d65SSudarsana Reddy Kalluru } 196097df0d65SSudarsana Reddy Kalluru } 196197df0d65SSudarsana Reddy Kalluru 196297df0d65SSudarsana Reddy Kalluru return rc; 196397df0d65SSudarsana Reddy Kalluru } 196497df0d65SSudarsana Reddy Kalluru 1965133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1966054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1967054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1968133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1969e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1970e0971c83STomer Tayar .get_regs = qede_get_regs, 197114d39648SMintz, Yuval .get_wol = qede_get_wol, 197214d39648SMintz, Yuval .set_wol = qede_set_wol, 1973133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1974133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 197532a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1976133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1977d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1978d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 197901ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 198001ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 19810f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 19820f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1983133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 19843d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1985133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1986f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1987133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1988961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1989961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1990961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1991961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1992961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1993961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 19944c55215cSSudarsana Reddy Kalluru .get_ts_info = qede_get_ts_info, 19958edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 19968edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 19973044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 199897df0d65SSudarsana Reddy Kalluru .get_module_info = qede_get_module_info, 199997df0d65SSudarsana Reddy Kalluru .get_module_eeprom = qede_get_module_eeprom, 2000c3dc48f7SSudarsana Reddy Kalluru .get_eee = qede_get_eee, 2001c3dc48f7SSudarsana Reddy Kalluru .set_eee = qede_set_eee, 2002c3dc48f7SSudarsana Reddy Kalluru 20033d789994SManish Chopra .get_tunable = qede_get_tunable, 20043d789994SManish Chopra .set_tunable = qede_set_tunable, 2005ccfa110cSSudarsana Reddy Kalluru .flash_device = qede_flash_device, 2006133fac0eSSudarsana Kalluru }; 2007133fac0eSSudarsana Kalluru 2008fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 2009054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 2010fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 2011fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 2012fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 2013fefb0202SYuval Mintz .get_link = qede_get_link, 2014477f2d14SRahul Verma .get_coalesce = qede_get_coalesce, 2015477f2d14SRahul Verma .set_coalesce = qede_set_coalesce, 2016fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 2017fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 2018fefb0202SYuval Mintz .get_strings = qede_get_strings, 2019fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 2020fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 2021fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 2022fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 2023fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 2024fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 2025fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 2026fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 2027fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 2028fefb0202SYuval Mintz .get_channels = qede_get_channels, 2029fefb0202SYuval Mintz .set_channels = qede_set_channels, 20303d789994SManish Chopra .get_tunable = qede_get_tunable, 20313d789994SManish Chopra .set_tunable = qede_set_tunable, 2032fefb0202SYuval Mintz }; 2033fefb0202SYuval Mintz 2034133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 2035133fac0eSSudarsana Kalluru { 2036fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 2037fefb0202SYuval Mintz 2038fefb0202SYuval Mintz if (IS_VF(edev)) 2039fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 2040fefb0202SYuval Mintz else 2041133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 2042133fac0eSSudarsana Kalluru } 2043