1133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver 2133fac0eSSudarsana Kalluru * Copyright (c) 2015 QLogic Corporation 3133fac0eSSudarsana Kalluru * 4133fac0eSSudarsana Kalluru * This software is available under the terms of the GNU General Public License 5133fac0eSSudarsana Kalluru * (GPL) Version 2, available from the file COPYING in the main directory of 6133fac0eSSudarsana Kalluru * this source tree. 7133fac0eSSudarsana Kalluru */ 8133fac0eSSudarsana Kalluru 9133fac0eSSudarsana Kalluru #include <linux/version.h> 10133fac0eSSudarsana Kalluru #include <linux/types.h> 11133fac0eSSudarsana Kalluru #include <linux/netdevice.h> 1216f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h> 13133fac0eSSudarsana Kalluru #include <linux/ethtool.h> 14133fac0eSSudarsana Kalluru #include <linux/string.h> 15133fac0eSSudarsana Kalluru #include <linux/pci.h> 16133fac0eSSudarsana Kalluru #include <linux/capability.h> 17133fac0eSSudarsana Kalluru #include "qede.h" 18133fac0eSSudarsana Kalluru 19133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \ 20133fac0eSSudarsana Kalluru (offsetof(struct qede_rx_queue, stat_name)) 21133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name) 22133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \ 23133fac0eSSudarsana Kalluru {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} 2416f46bf0SSudarsana Reddy Kalluru 2516f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100 2616f46bf0SSudarsana Reddy Kalluru 27133fac0eSSudarsana Kalluru static const struct { 28133fac0eSSudarsana Kalluru u64 offset; 29133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 30133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = { 3168db9ec2SSudarsana Reddy Kalluru QEDE_RQSTAT(rcv_pkts), 32133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_hw_errors), 33133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_alloc_errors), 34c72a6125SManish Chopra QEDE_RQSTAT(rx_ip_frags), 35133fac0eSSudarsana Kalluru }; 36133fac0eSSudarsana Kalluru 37133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) 3868db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \ 3968db9ec2SSudarsana Reddy Kalluru (offsetof(struct qede_tx_queue, stat_name)) 4068db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name) 4168db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \ 4268db9ec2SSudarsana Reddy Kalluru {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)} 4368db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr) 4468db9ec2SSudarsana Reddy Kalluru static const struct { 4568db9ec2SSudarsana Reddy Kalluru u64 offset; 4668db9ec2SSudarsana Reddy Kalluru char string[ETH_GSTRING_LEN]; 4768db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = { 4868db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(xmit_pkts), 4968db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(stopped_cnt), 5068db9ec2SSudarsana Reddy Kalluru }; 5168db9ec2SSudarsana Reddy Kalluru 524dbcd640SMintz, Yuval #define QEDE_STAT_OFFSET(stat_name) (offsetof(struct qede_stats, stat_name)) 534dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name) (#stat_name) 544dbcd640SMintz, Yuval #define _QEDE_STAT(stat_name, pf_only) \ 554dbcd640SMintz, Yuval {QEDE_STAT_OFFSET(stat_name), QEDE_STAT_STRING(stat_name), pf_only} 564dbcd640SMintz, Yuval #define QEDE_PF_STAT(stat_name) _QEDE_STAT(stat_name, true) 574dbcd640SMintz, Yuval #define QEDE_STAT(stat_name) _QEDE_STAT(stat_name, false) 58133fac0eSSudarsana Kalluru static const struct { 59133fac0eSSudarsana Kalluru u64 offset; 60133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 61133fac0eSSudarsana Kalluru bool pf_only; 62133fac0eSSudarsana Kalluru } qede_stats_arr[] = { 63133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes), 64133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes), 65133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes), 66133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts), 67133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts), 68133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts), 69133fac0eSSudarsana Kalluru 70133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes), 71133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes), 72133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes), 73133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts), 74133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts), 75133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts), 76133fac0eSSudarsana Kalluru 77133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets), 78d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets), 79d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets), 80d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets), 81d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets), 82d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets), 83d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1519_to_1522_byte_packets), 84d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1519_to_2047_byte_packets), 85d4967cf3SYuval Mintz QEDE_PF_STAT(rx_2048_to_4095_byte_packets), 86d4967cf3SYuval Mintz QEDE_PF_STAT(rx_4096_to_9216_byte_packets), 87d4967cf3SYuval Mintz QEDE_PF_STAT(rx_9217_to_16383_byte_packets), 88133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets), 89133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets), 90133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets), 91133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets), 92133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets), 93133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets), 94133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1519_to_2047_byte_packets), 95133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_2048_to_4095_byte_packets), 96133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_4096_to_9216_byte_packets), 97133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_9217_to_16383_byte_packets), 98133fac0eSSudarsana Kalluru 99133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames), 100133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames), 101133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames), 102133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames), 103133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames), 104133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames), 105133fac0eSSudarsana Kalluru 106133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors), 107133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors), 108133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors), 109133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets), 110133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers), 111133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets), 112133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments), 113133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_lpi_entry_count), 114133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_total_collisions), 115133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates), 116133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards), 117133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards), 118133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards), 119133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards), 120133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1211a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1221a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 123133fac0eSSudarsana Kalluru 124133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 125133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 126133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 127133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 128133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 129133fac0eSSudarsana Kalluru }; 130133fac0eSSudarsana Kalluru 131133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 132133fac0eSSudarsana Kalluru 133f3e72109SYuval Mintz enum { 134f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 135f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 136f3e72109SYuval Mintz }; 137f3e72109SYuval Mintz 138f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 139f3e72109SYuval Mintz "Coupled-Function", 140f3e72109SYuval Mintz }; 141f3e72109SYuval Mintz 1423044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 14316f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 1443044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 1453044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 1463044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 1473044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 1487a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 1493044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 1503044a02eSSudarsana Reddy Kalluru }; 1513044a02eSSudarsana Reddy Kalluru 1523044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 15316f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 1543044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 1553044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 1563044a02eSSudarsana Reddy Kalluru "Register (online)\t", 1573044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 1587a4b21b7SMintz, Yuval "Nvram (online)\t\t", 1593044a02eSSudarsana Reddy Kalluru }; 1603044a02eSSudarsana Reddy Kalluru 1614dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev, 1624dbcd640SMintz, Yuval struct qede_tx_queue *txq, u8 **buf) 1634dbcd640SMintz, Yuval { 1644dbcd640SMintz, Yuval int i; 1654dbcd640SMintz, Yuval 1664dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 1674dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", txq->index, 1684dbcd640SMintz, Yuval qede_tqstats_arr[i].string); 1694dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 1704dbcd640SMintz, Yuval } 1714dbcd640SMintz, Yuval } 1724dbcd640SMintz, Yuval 1734dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev, 1744dbcd640SMintz, Yuval struct qede_rx_queue *rxq, u8 **buf) 1754dbcd640SMintz, Yuval { 1764dbcd640SMintz, Yuval int i; 1774dbcd640SMintz, Yuval 1784dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 1794dbcd640SMintz, Yuval sprintf(*buf, "%d: %s", rxq->rxq_id, 1804dbcd640SMintz, Yuval qede_rqstats_arr[i].string); 1814dbcd640SMintz, Yuval *buf += ETH_GSTRING_LEN; 1824dbcd640SMintz, Yuval } 1834dbcd640SMintz, Yuval } 1844dbcd640SMintz, Yuval 185133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 186133fac0eSSudarsana Kalluru { 1874dbcd640SMintz, Yuval struct qede_fastpath *fp; 1884dbcd640SMintz, Yuval int i; 189133fac0eSSudarsana Kalluru 1904dbcd640SMintz, Yuval /* Account for queue statistics */ 1914dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 1924dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 19368db9ec2SSudarsana Reddy Kalluru 1944dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 1954dbcd640SMintz, Yuval qede_get_strings_stats_rxq(edev, fp->rxq, &buf); 1964dbcd640SMintz, Yuval 1974dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_TX) 1984dbcd640SMintz, Yuval qede_get_strings_stats_txq(edev, fp->txq, &buf); 199cbbf049aSMintz, Yuval } 200cbbf049aSMintz, Yuval 2014dbcd640SMintz, Yuval /* Account for non-queue statistics */ 2024dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 203fefb0202SYuval Mintz if (IS_VF(edev) && qede_stats_arr[i].pf_only) 204fefb0202SYuval Mintz continue; 2054dbcd640SMintz, Yuval strcpy(buf, qede_stats_arr[i].string); 2064dbcd640SMintz, Yuval buf += ETH_GSTRING_LEN; 207133fac0eSSudarsana Kalluru } 208133fac0eSSudarsana Kalluru } 209133fac0eSSudarsana Kalluru 210133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 211133fac0eSSudarsana Kalluru { 212133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 213133fac0eSSudarsana Kalluru 214133fac0eSSudarsana Kalluru switch (stringset) { 215133fac0eSSudarsana Kalluru case ETH_SS_STATS: 216133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 217133fac0eSSudarsana Kalluru break; 218f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 219f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 220f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 221f3e72109SYuval Mintz break; 2223044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2233044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 2243044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 2253044a02eSSudarsana Reddy Kalluru break; 226133fac0eSSudarsana Kalluru default: 227133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 228133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 229133fac0eSSudarsana Kalluru } 230133fac0eSSudarsana Kalluru } 231133fac0eSSudarsana Kalluru 2324dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf) 2334dbcd640SMintz, Yuval { 2344dbcd640SMintz, Yuval int i; 2354dbcd640SMintz, Yuval 2364dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_TQSTATS; i++) { 2374dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset)); 2384dbcd640SMintz, Yuval (*buf)++; 2394dbcd640SMintz, Yuval } 2404dbcd640SMintz, Yuval } 2414dbcd640SMintz, Yuval 2424dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf) 2434dbcd640SMintz, Yuval { 2444dbcd640SMintz, Yuval int i; 2454dbcd640SMintz, Yuval 2464dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_RQSTATS; i++) { 2474dbcd640SMintz, Yuval **buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset)); 2484dbcd640SMintz, Yuval (*buf)++; 2494dbcd640SMintz, Yuval } 2504dbcd640SMintz, Yuval } 2514dbcd640SMintz, Yuval 252133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 253133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 254133fac0eSSudarsana Kalluru { 255133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 2564dbcd640SMintz, Yuval struct qede_fastpath *fp; 2574dbcd640SMintz, Yuval int i; 258133fac0eSSudarsana Kalluru 259133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 260133fac0eSSudarsana Kalluru 261567b3c12SMintz, Yuval /* Need to protect the access to the fastpath array */ 262567b3c12SMintz, Yuval __qede_lock(edev); 263567b3c12SMintz, Yuval 2644dbcd640SMintz, Yuval for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) { 2654dbcd640SMintz, Yuval fp = &edev->fp_array[i]; 266133fac0eSSudarsana Kalluru 2674dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_RX) 2684dbcd640SMintz, Yuval qede_get_ethtool_stats_rxq(fp->rxq, &buf); 26968db9ec2SSudarsana Reddy Kalluru 2704dbcd640SMintz, Yuval if (fp->type & QEDE_FASTPATH_TX) 2714dbcd640SMintz, Yuval qede_get_ethtool_stats_txq(fp->txq, &buf); 27268db9ec2SSudarsana Reddy Kalluru } 27368db9ec2SSudarsana Reddy Kalluru 2744dbcd640SMintz, Yuval for (i = 0; i < QEDE_NUM_STATS; i++) { 2754dbcd640SMintz, Yuval if (IS_VF(edev) && qede_stats_arr[i].pf_only) 276fefb0202SYuval Mintz continue; 2774dbcd640SMintz, Yuval *buf = *((u64 *)(((void *)&edev->stats) + 2784dbcd640SMintz, Yuval qede_stats_arr[i].offset)); 2794dbcd640SMintz, Yuval 2804dbcd640SMintz, Yuval buf++; 281fefb0202SYuval Mintz } 282133fac0eSSudarsana Kalluru 283567b3c12SMintz, Yuval __qede_unlock(edev); 284133fac0eSSudarsana Kalluru } 285133fac0eSSudarsana Kalluru 286133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 287133fac0eSSudarsana Kalluru { 288133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 289133fac0eSSudarsana Kalluru int num_stats = QEDE_NUM_STATS; 290133fac0eSSudarsana Kalluru 291133fac0eSSudarsana Kalluru switch (stringset) { 292133fac0eSSudarsana Kalluru case ETH_SS_STATS: 293fefb0202SYuval Mintz if (IS_VF(edev)) { 294fefb0202SYuval Mintz int i; 295fefb0202SYuval Mintz 296fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 297fefb0202SYuval Mintz if (qede_stats_arr[i].pf_only) 298fefb0202SYuval Mintz num_stats--; 299fefb0202SYuval Mintz } 3004dbcd640SMintz, Yuval 3014dbcd640SMintz, Yuval /* Account for the Regular Tx statistics */ 3024dbcd640SMintz, Yuval num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS; 3034dbcd640SMintz, Yuval 3044dbcd640SMintz, Yuval /* Account for the Regular Rx statistics */ 3054dbcd640SMintz, Yuval num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS; 3064dbcd640SMintz, Yuval 3074dbcd640SMintz, Yuval return num_stats; 3084dbcd640SMintz, Yuval 309f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 310f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 3113044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 3126ecb0a0cSYuval Mintz if (!IS_VF(edev)) 3133044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 3146ecb0a0cSYuval Mintz else 3156ecb0a0cSYuval Mintz return 0; 316133fac0eSSudarsana Kalluru default: 317133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 318133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 319133fac0eSSudarsana Kalluru return -EINVAL; 320133fac0eSSudarsana Kalluru } 321133fac0eSSudarsana Kalluru } 322133fac0eSSudarsana Kalluru 323f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 324f3e72109SYuval Mintz { 325f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 326f3e72109SYuval Mintz 327f3e72109SYuval Mintz return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; 328f3e72109SYuval Mintz } 329f3e72109SYuval Mintz 330054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 331054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 332054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 333054c67d1SSudarsana Reddy Kalluru }; 334054c67d1SSudarsana Reddy Kalluru 335054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 336054c67d1SSudarsana Reddy Kalluru {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, 337054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 338054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 339054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 340054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT}, 341054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 342054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 343054c67d1SSudarsana Reddy Kalluru {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 344054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 345054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 346054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 347054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 348054c67d1SSudarsana Reddy Kalluru }; 349054c67d1SSudarsana Reddy Kalluru 350054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 351054c67d1SSudarsana Reddy Kalluru { \ 352054c67d1SSudarsana Reddy Kalluru int i; \ 353054c67d1SSudarsana Reddy Kalluru \ 354d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 355054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 356054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 357054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 358054c67d1SSudarsana Reddy Kalluru } \ 359054c67d1SSudarsana Reddy Kalluru } 360054c67d1SSudarsana Reddy Kalluru 361054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 362054c67d1SSudarsana Reddy Kalluru { \ 363054c67d1SSudarsana Reddy Kalluru int i; \ 364054c67d1SSudarsana Reddy Kalluru \ 365d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 366054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 367054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 368054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 369054c67d1SSudarsana Reddy Kalluru } \ 370054c67d1SSudarsana Reddy Kalluru } 371054c67d1SSudarsana Reddy Kalluru 372054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 373054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 374133fac0eSSudarsana Kalluru { 375054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 376133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 377133fac0eSSudarsana Kalluru struct qed_link_output current_link; 378133fac0eSSudarsana Kalluru 379567b3c12SMintz, Yuval __qede_lock(edev); 380567b3c12SMintz, Yuval 381133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 382133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 383133fac0eSSudarsana Kalluru 384054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 385054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 386054c67d1SSudarsana Reddy Kalluru 387054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 388054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 389054c67d1SSudarsana Reddy Kalluru 390054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 391054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 392054c67d1SSudarsana Reddy Kalluru 393133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 394054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 395054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 396133fac0eSSudarsana Kalluru } else { 397054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 398054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 399133fac0eSSudarsana Kalluru } 400567b3c12SMintz, Yuval 401567b3c12SMintz, Yuval __qede_unlock(edev); 402567b3c12SMintz, Yuval 403054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 404054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 405133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 406133fac0eSSudarsana Kalluru 407133fac0eSSudarsana Kalluru return 0; 408133fac0eSSudarsana Kalluru } 409133fac0eSSudarsana Kalluru 410054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 411054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 412133fac0eSSudarsana Kalluru { 413054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 414133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 415133fac0eSSudarsana Kalluru struct qed_link_output current_link; 416133fac0eSSudarsana Kalluru struct qed_link_params params; 417133fac0eSSudarsana Kalluru 418fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 419054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 420133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 421133fac0eSSudarsana Kalluru } 422133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 423133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 424133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 425133fac0eSSudarsana Kalluru 426133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 427133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 428054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 429133fac0eSSudarsana Kalluru params.autoneg = true; 430133fac0eSSudarsana Kalluru params.forced_speed = 0; 431054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 432133fac0eSSudarsana Kalluru } else { /* forced speed */ 433133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 434133fac0eSSudarsana Kalluru params.autoneg = false; 435054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 436054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 437133fac0eSSudarsana Kalluru case SPEED_10000: 438133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 439054c67d1SSudarsana Reddy Kalluru QED_LM_10000baseKR_Full_BIT)) { 440133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 441133fac0eSSudarsana Kalluru return -EINVAL; 442133fac0eSSudarsana Kalluru } 443054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_10000baseKR_Full_BIT; 444054c67d1SSudarsana Reddy Kalluru break; 445054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 446054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 447054c67d1SSudarsana Reddy Kalluru QED_LM_25000baseKR_Full_BIT)) { 448054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 449054c67d1SSudarsana Reddy Kalluru return -EINVAL; 450054c67d1SSudarsana Reddy Kalluru } 451054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_25000baseKR_Full_BIT; 452133fac0eSSudarsana Kalluru break; 453133fac0eSSudarsana Kalluru case SPEED_40000: 454133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 455054c67d1SSudarsana Reddy Kalluru QED_LM_40000baseLR4_Full_BIT)) { 456133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 457133fac0eSSudarsana Kalluru return -EINVAL; 458133fac0eSSudarsana Kalluru } 459054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_40000baseLR4_Full_BIT; 460054c67d1SSudarsana Reddy Kalluru break; 46116d5946aSYuval Mintz case SPEED_50000: 462054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 463054c67d1SSudarsana Reddy Kalluru QED_LM_50000baseKR2_Full_BIT)) { 464054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 465054c67d1SSudarsana Reddy Kalluru return -EINVAL; 466054c67d1SSudarsana Reddy Kalluru } 467054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_50000baseKR2_Full_BIT; 468054c67d1SSudarsana Reddy Kalluru break; 46916d5946aSYuval Mintz case SPEED_100000: 470054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 471054c67d1SSudarsana Reddy Kalluru QED_LM_100000baseKR4_Full_BIT)) { 472054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 473054c67d1SSudarsana Reddy Kalluru return -EINVAL; 474054c67d1SSudarsana Reddy Kalluru } 475054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_100000baseKR4_Full_BIT; 476133fac0eSSudarsana Kalluru break; 477133fac0eSSudarsana Kalluru default: 478054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 479133fac0eSSudarsana Kalluru return -EINVAL; 480133fac0eSSudarsana Kalluru } 481133fac0eSSudarsana Kalluru } 482133fac0eSSudarsana Kalluru 483133fac0eSSudarsana Kalluru params.link_up = true; 484133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 485133fac0eSSudarsana Kalluru 486133fac0eSSudarsana Kalluru return 0; 487133fac0eSSudarsana Kalluru } 488133fac0eSSudarsana Kalluru 489133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 490133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 491133fac0eSSudarsana Kalluru { 492133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 493133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 494133fac0eSSudarsana Kalluru 495133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 496133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 497133fac0eSSudarsana Kalluru 498133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 499133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 500133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 501133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 502133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 503133fac0eSSudarsana Kalluru 504133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 505133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 506133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 507133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 508133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 509133fac0eSSudarsana Kalluru 510133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 511133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 512133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 513133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 514133fac0eSSudarsana Kalluru } else { 515133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 516133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 517133fac0eSSudarsana Kalluru } 518133fac0eSSudarsana Kalluru 519133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 520133fac0eSSudarsana Kalluru } 521133fac0eSSudarsana Kalluru 52214d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 52314d39648SMintz, Yuval { 52414d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 52514d39648SMintz, Yuval 52614d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 52714d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 52814d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 52914d39648SMintz, Yuval } 53014d39648SMintz, Yuval } 53114d39648SMintz, Yuval 53214d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 53314d39648SMintz, Yuval { 53414d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 53514d39648SMintz, Yuval bool wol_requested; 53614d39648SMintz, Yuval int rc; 53714d39648SMintz, Yuval 53814d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 53914d39648SMintz, Yuval DP_INFO(edev, 54014d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 54114d39648SMintz, Yuval return -EINVAL; 54214d39648SMintz, Yuval } 54314d39648SMintz, Yuval 54414d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 54514d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 54614d39648SMintz, Yuval return 0; 54714d39648SMintz, Yuval 54814d39648SMintz, Yuval /* Need to actually change configuration */ 54914d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 55014d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 55114d39648SMintz, Yuval return -EINVAL; 55214d39648SMintz, Yuval } 55314d39648SMintz, Yuval 55414d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 55514d39648SMintz, Yuval if (!rc) 55614d39648SMintz, Yuval edev->wol_enabled = wol_requested; 55714d39648SMintz, Yuval 55814d39648SMintz, Yuval return rc; 55914d39648SMintz, Yuval } 56014d39648SMintz, Yuval 561133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 562133fac0eSSudarsana Kalluru { 563133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 564133fac0eSSudarsana Kalluru 5651a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 566133fac0eSSudarsana Kalluru } 567133fac0eSSudarsana Kalluru 568133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 569133fac0eSSudarsana Kalluru { 570133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 571133fac0eSSudarsana Kalluru u32 dp_module = 0; 572133fac0eSSudarsana Kalluru u8 dp_level = 0; 573133fac0eSSudarsana Kalluru 574133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 575133fac0eSSudarsana Kalluru 576133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 577133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 578133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 579133fac0eSSudarsana Kalluru dp_module, dp_level); 580133fac0eSSudarsana Kalluru } 581133fac0eSSudarsana Kalluru 58232a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 58332a7a570SSudarsana Kalluru { 58432a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 58532a7a570SSudarsana Kalluru struct qed_link_output current_link; 58632a7a570SSudarsana Kalluru struct qed_link_params link_params; 58732a7a570SSudarsana Kalluru 588fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 5891a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 590fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 591fe7cd2bfSYuval Mintz } 592fe7cd2bfSYuval Mintz 59332a7a570SSudarsana Kalluru if (!netif_running(dev)) 59432a7a570SSudarsana Kalluru return 0; 59532a7a570SSudarsana Kalluru 59632a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 59732a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 59832a7a570SSudarsana Kalluru if (!current_link.link_up) 59932a7a570SSudarsana Kalluru return 0; 60032a7a570SSudarsana Kalluru 60132a7a570SSudarsana Kalluru /* Toggle the link */ 60232a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 60332a7a570SSudarsana Kalluru link_params.link_up = false; 60432a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 60532a7a570SSudarsana Kalluru link_params.link_up = true; 60632a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 60732a7a570SSudarsana Kalluru 60832a7a570SSudarsana Kalluru return 0; 60932a7a570SSudarsana Kalluru } 61032a7a570SSudarsana Kalluru 611133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 612133fac0eSSudarsana Kalluru { 613133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 614133fac0eSSudarsana Kalluru struct qed_link_output current_link; 615133fac0eSSudarsana Kalluru 616133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 617133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 618133fac0eSSudarsana Kalluru 619133fac0eSSudarsana Kalluru return current_link.link_up; 620133fac0eSSudarsana Kalluru } 621133fac0eSSudarsana Kalluru 622d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 623d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 624d552fa84SSudarsana Reddy Kalluru { 625d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 626d2890deaSSudarsana Reddy Kalluru u16 rxc, txc; 627d552fa84SSudarsana Reddy Kalluru 628d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 629d2890deaSSudarsana Reddy Kalluru edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc); 630d2890deaSSudarsana Reddy Kalluru 631d2890deaSSudarsana Reddy Kalluru coal->rx_coalesce_usecs = rxc; 632d2890deaSSudarsana Reddy Kalluru coal->tx_coalesce_usecs = txc; 633d552fa84SSudarsana Reddy Kalluru 634d552fa84SSudarsana Reddy Kalluru return 0; 635d552fa84SSudarsana Reddy Kalluru } 636d552fa84SSudarsana Reddy Kalluru 637d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 638d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 639d552fa84SSudarsana Reddy Kalluru { 640d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 641d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 642d552fa84SSudarsana Reddy Kalluru u16 rxc, txc; 643d552fa84SSudarsana Reddy Kalluru u8 sb_id; 644d552fa84SSudarsana Reddy Kalluru 645d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 646d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 647d552fa84SSudarsana Reddy Kalluru return -EINVAL; 648d552fa84SSudarsana Reddy Kalluru } 649d552fa84SSudarsana Reddy Kalluru 650d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 651d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 652d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 653d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 654d552fa84SSudarsana Reddy Kalluru coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" 655d552fa84SSudarsana Reddy Kalluru : "tx", 656d552fa84SSudarsana Reddy Kalluru QED_COALESCE_MAX); 657d552fa84SSudarsana Reddy Kalluru return -EINVAL; 658d552fa84SSudarsana Reddy Kalluru } 659d552fa84SSudarsana Reddy Kalluru 660d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 661d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 6629a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 663d552fa84SSudarsana Reddy Kalluru sb_id = edev->fp_array[i].sb_info->igu_sb_id; 664d552fa84SSudarsana Reddy Kalluru rc = edev->ops->common->set_coalesce(edev->cdev, rxc, txc, 665d552fa84SSudarsana Reddy Kalluru (u8)i, sb_id); 666d552fa84SSudarsana Reddy Kalluru if (rc) { 667d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Set coalesce error, rc = %d\n", rc); 668d552fa84SSudarsana Reddy Kalluru return rc; 669d552fa84SSudarsana Reddy Kalluru } 670d552fa84SSudarsana Reddy Kalluru } 671d552fa84SSudarsana Reddy Kalluru 672d552fa84SSudarsana Reddy Kalluru return rc; 673d552fa84SSudarsana Reddy Kalluru } 674d552fa84SSudarsana Reddy Kalluru 67501ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 67601ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 67701ef7e05SSudarsana Kalluru { 67801ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 67901ef7e05SSudarsana Kalluru 68001ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 68101ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 68201ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 68301ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 68401ef7e05SSudarsana Kalluru } 68501ef7e05SSudarsana Kalluru 68601ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 68701ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 68801ef7e05SSudarsana Kalluru { 68901ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 69001ef7e05SSudarsana Kalluru 69101ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 69201ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 69301ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 69401ef7e05SSudarsana Kalluru 69501ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 69601ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 69701ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 69801ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 69901ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 70001ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 70101ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 70201ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 70301ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 70401ef7e05SSudarsana Kalluru return -EINVAL; 70501ef7e05SSudarsana Kalluru } 70601ef7e05SSudarsana Kalluru 70701ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 70801ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 70901ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 71001ef7e05SSudarsana Kalluru 711567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 71201ef7e05SSudarsana Kalluru 71301ef7e05SSudarsana Kalluru return 0; 71401ef7e05SSudarsana Kalluru } 71501ef7e05SSudarsana Kalluru 7160f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 7170f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 7180f7db144SSudarsana Kalluru { 7190f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7200f7db144SSudarsana Kalluru struct qed_link_output current_link; 7210f7db144SSudarsana Kalluru 7220f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 7230f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 7240f7db144SSudarsana Kalluru 7250f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 7260f7db144SSudarsana Kalluru epause->autoneg = true; 7270f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 7280f7db144SSudarsana Kalluru epause->rx_pause = true; 7290f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 7300f7db144SSudarsana Kalluru epause->tx_pause = true; 7310f7db144SSudarsana Kalluru 7320f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 7330f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 7340f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 7350f7db144SSudarsana Kalluru epause->tx_pause); 7360f7db144SSudarsana Kalluru } 7370f7db144SSudarsana Kalluru 7380f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 7390f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 7400f7db144SSudarsana Kalluru { 7410f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7420f7db144SSudarsana Kalluru struct qed_link_params params; 7430f7db144SSudarsana Kalluru struct qed_link_output current_link; 7440f7db144SSudarsana Kalluru 745fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 7460f7db144SSudarsana Kalluru DP_INFO(edev, 747fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 7480f7db144SSudarsana Kalluru return -EOPNOTSUPP; 7490f7db144SSudarsana Kalluru } 7500f7db144SSudarsana Kalluru 7510f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 7520f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 7530f7db144SSudarsana Kalluru 7540f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 7550f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 7560f7db144SSudarsana Kalluru if (epause->autoneg) { 757d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 7580f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 7590f7db144SSudarsana Kalluru return -EINVAL; 7600f7db144SSudarsana Kalluru } 7610f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 7620f7db144SSudarsana Kalluru } 7630f7db144SSudarsana Kalluru if (epause->rx_pause) 7640f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 7650f7db144SSudarsana Kalluru if (epause->tx_pause) 7660f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 7670f7db144SSudarsana Kalluru 7680f7db144SSudarsana Kalluru params.link_up = true; 7690f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 7700f7db144SSudarsana Kalluru 7710f7db144SSudarsana Kalluru return 0; 7720f7db144SSudarsana Kalluru } 7730f7db144SSudarsana Kalluru 774e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 775e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 776e0971c83STomer Tayar { 777e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 778e0971c83STomer Tayar 779e0971c83STomer Tayar regs->version = 0; 780e0971c83STomer Tayar memset(buffer, 0, regs->len); 781e0971c83STomer Tayar 782e0971c83STomer Tayar if (edev->ops && edev->ops->common) 783e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 784e0971c83STomer Tayar } 785e0971c83STomer Tayar 786e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 787e0971c83STomer Tayar { 788e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 789e0971c83STomer Tayar 790e0971c83STomer Tayar if (edev->ops && edev->ops->common) 791e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 792e0971c83STomer Tayar else 793e0971c83STomer Tayar return -EINVAL; 794e0971c83STomer Tayar } 795e0971c83STomer Tayar 796567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev, 797567b3c12SMintz, Yuval struct qede_reload_args *args) 798133fac0eSSudarsana Kalluru { 799567b3c12SMintz, Yuval edev->ndev->mtu = args->u.mtu; 800133fac0eSSudarsana Kalluru } 801133fac0eSSudarsana Kalluru 802133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 803133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 804133fac0eSSudarsana Kalluru { 805133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 806567b3c12SMintz, Yuval struct qede_reload_args args; 807133fac0eSSudarsana Kalluru 808133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 809133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 810133fac0eSSudarsana Kalluru 811133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed */ 812567b3c12SMintz, Yuval args.u.mtu = new_mtu; 813567b3c12SMintz, Yuval args.func = &qede_update_mtu; 814567b3c12SMintz, Yuval qede_reload(edev, &args, false); 815133fac0eSSudarsana Kalluru 816567b3c12SMintz, Yuval edev->ops->common->update_mtu(edev->cdev, new_mtu); 8170fefbfbaSSudarsana Kalluru 818133fac0eSSudarsana Kalluru return 0; 819133fac0eSSudarsana Kalluru } 820133fac0eSSudarsana Kalluru 8218edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 8228edf049dSSudarsana Kalluru struct ethtool_channels *channels) 8238edf049dSSudarsana Kalluru { 8248edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8258edf049dSSudarsana Kalluru 8268edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 827bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 828bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 8299a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 8309a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 8319a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 8329a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 8338edf049dSSudarsana Kalluru } 8348edf049dSSudarsana Kalluru 8358edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 8368edf049dSSudarsana Kalluru struct ethtool_channels *channels) 8378edf049dSSudarsana Kalluru { 8388edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8399a4d7e86SSudarsana Reddy Kalluru u32 count; 8408edf049dSSudarsana Kalluru 8418edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8428edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 8438edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 8448edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 8458edf049dSSudarsana Kalluru 8469a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 8479a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 8489a4d7e86SSudarsana Reddy Kalluru 8499a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 8509a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 8518edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8528edf049dSSudarsana Kalluru "command parameters not supported\n"); 8538edf049dSSudarsana Kalluru return -EINVAL; 8548edf049dSSudarsana Kalluru } 8558edf049dSSudarsana Kalluru 8569a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 8579a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 8589a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8599a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 8609a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 8619a4d7e86SSudarsana Reddy Kalluru } 8629a4d7e86SSudarsana Reddy Kalluru 8639a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 8649a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8659a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 8669a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 8679a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 8689a4d7e86SSudarsana Reddy Kalluru } 8699a4d7e86SSudarsana Reddy Kalluru 8708edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 8719a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 8729a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 8739a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 8748edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8758edf049dSSudarsana Kalluru "No change in active parameters\n"); 8768edf049dSSudarsana Kalluru return 0; 8778edf049dSSudarsana Kalluru } 8788edf049dSSudarsana Kalluru 8798edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 8809a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 8819a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 8829a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 8838edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8849a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 8858edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 8868edf049dSSudarsana Kalluru return -EINVAL; 8878edf049dSSudarsana Kalluru } 8888edf049dSSudarsana Kalluru 8898edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 8909a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 8919a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 8929a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 893ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 894ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 895ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 896ed0dd915SSudarsana Reddy Kalluru memset(&edev->rss_params.rss_ind_table, 0, 897ed0dd915SSudarsana Reddy Kalluru sizeof(edev->rss_params.rss_ind_table)); 898ed0dd915SSudarsana Reddy Kalluru } 899ed0dd915SSudarsana Reddy Kalluru 900567b3c12SMintz, Yuval qede_reload(edev, NULL, false); 9018edf049dSSudarsana Kalluru 9028edf049dSSudarsana Kalluru return 0; 9038edf049dSSudarsana Kalluru } 9048edf049dSSudarsana Kalluru 9053d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 9063d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 9073d971cbdSSudarsana Kalluru { 9083d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 9093d971cbdSSudarsana Kalluru u8 led_state = 0; 9103d971cbdSSudarsana Kalluru 9113d971cbdSSudarsana Kalluru switch (state) { 9123d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 9133d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 9143d971cbdSSudarsana Kalluru 9153d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 9163d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 9173d971cbdSSudarsana Kalluru break; 9183d971cbdSSudarsana Kalluru 9193d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 9203d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 9213d971cbdSSudarsana Kalluru break; 9223d971cbdSSudarsana Kalluru 9233d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 9243d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 9253d971cbdSSudarsana Kalluru break; 9263d971cbdSSudarsana Kalluru } 9273d971cbdSSudarsana Kalluru 9283d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 9293d971cbdSSudarsana Kalluru 9303d971cbdSSudarsana Kalluru return 0; 9313d971cbdSSudarsana Kalluru } 9323d971cbdSSudarsana Kalluru 933961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 934961acdeaSSudarsana Reddy Kalluru { 935961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 936961acdeaSSudarsana Reddy Kalluru 937961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 938961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 939961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 940961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 941961acdeaSSudarsana Reddy Kalluru break; 942961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 943961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP) 944961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 945961acdeaSSudarsana Reddy Kalluru break; 946961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 947961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP) 948961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 949961acdeaSSudarsana Reddy Kalluru break; 950961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 951961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 952961acdeaSSudarsana Reddy Kalluru break; 953961acdeaSSudarsana Reddy Kalluru default: 954961acdeaSSudarsana Reddy Kalluru info->data = 0; 955961acdeaSSudarsana Reddy Kalluru break; 956961acdeaSSudarsana Reddy Kalluru } 957961acdeaSSudarsana Reddy Kalluru 958961acdeaSSudarsana Reddy Kalluru return 0; 959961acdeaSSudarsana Reddy Kalluru } 960961acdeaSSudarsana Reddy Kalluru 961961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 962961acdeaSSudarsana Reddy Kalluru u32 *rules __always_unused) 963961acdeaSSudarsana Reddy Kalluru { 964961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 965961acdeaSSudarsana Reddy Kalluru 966961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 967961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 9689a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 969961acdeaSSudarsana Reddy Kalluru return 0; 970961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 971961acdeaSSudarsana Reddy Kalluru return qede_get_rss_flags(edev, info); 972961acdeaSSudarsana Reddy Kalluru default: 973961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 974961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 975961acdeaSSudarsana Reddy Kalluru } 976961acdeaSSudarsana Reddy Kalluru } 977961acdeaSSudarsana Reddy Kalluru 978961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 979961acdeaSSudarsana Reddy Kalluru { 980961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 981961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 982961acdeaSSudarsana Reddy Kalluru 983961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 984961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 985961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 986961acdeaSSudarsana Reddy Kalluru 987961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 988961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 989961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 990961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 991961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 992961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 993961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 994961acdeaSSudarsana Reddy Kalluru return -EINVAL; 995961acdeaSSudarsana Reddy Kalluru } 996961acdeaSSudarsana Reddy Kalluru return 0; 997961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 998961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 999961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1000961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1001961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 1002961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1003961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1004961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1005961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 1006961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1007961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1008961acdeaSSudarsana Reddy Kalluru } else { 1009961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1010961acdeaSSudarsana Reddy Kalluru } 1011961acdeaSSudarsana Reddy Kalluru break; 1012961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 1013961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 1014961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 1015961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 1016961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 1017961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1018961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 1019961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 1020961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 1021961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 1022961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 1023961acdeaSSudarsana Reddy Kalluru } else { 1024961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1025961acdeaSSudarsana Reddy Kalluru } 1026961acdeaSSudarsana Reddy Kalluru break; 1027961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 1028961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 1029961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 1030961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 1031961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1032961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1033961acdeaSSudarsana Reddy Kalluru } 1034961acdeaSSudarsana Reddy Kalluru return 0; 1035961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1036961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1037961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1038961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1039961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1040961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1041961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1042961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1043961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1044961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1045961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1046961acdeaSSudarsana Reddy Kalluru if (info->data) { 1047961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1048961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1049961acdeaSSudarsana Reddy Kalluru } 1050961acdeaSSudarsana Reddy Kalluru return 0; 1051961acdeaSSudarsana Reddy Kalluru default: 1052961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1053961acdeaSSudarsana Reddy Kalluru } 1054961acdeaSSudarsana Reddy Kalluru 1055961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1056961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps & 1057961acdeaSSudarsana Reddy Kalluru ~clr_caps) | set_caps)) 1058961acdeaSSudarsana Reddy Kalluru return 0; 1059961acdeaSSudarsana Reddy Kalluru 1060961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1061961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) | 1062961acdeaSSudarsana Reddy Kalluru set_caps; 1063961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1064961acdeaSSudarsana Reddy Kalluru 1065961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1066961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1067961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1068961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1069961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1070961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1071961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1072961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1073961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1074961acdeaSSudarsana Reddy Kalluru } 1075961acdeaSSudarsana Reddy Kalluru 1076961acdeaSSudarsana Reddy Kalluru return 0; 1077961acdeaSSudarsana Reddy Kalluru } 1078961acdeaSSudarsana Reddy Kalluru 1079961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1080961acdeaSSudarsana Reddy Kalluru { 1081961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1082961acdeaSSudarsana Reddy Kalluru 1083961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1084961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 1085961acdeaSSudarsana Reddy Kalluru return qede_set_rss_flags(edev, info); 1086961acdeaSSudarsana Reddy Kalluru default: 1087961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1088961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1089961acdeaSSudarsana Reddy Kalluru } 1090961acdeaSSudarsana Reddy Kalluru } 1091961acdeaSSudarsana Reddy Kalluru 1092961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1093961acdeaSSudarsana Reddy Kalluru { 1094961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1095961acdeaSSudarsana Reddy Kalluru } 1096961acdeaSSudarsana Reddy Kalluru 1097961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1098961acdeaSSudarsana Reddy Kalluru { 1099961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1100961acdeaSSudarsana Reddy Kalluru 1101961acdeaSSudarsana Reddy Kalluru return sizeof(edev->rss_params.rss_key); 1102961acdeaSSudarsana Reddy Kalluru } 1103961acdeaSSudarsana Reddy Kalluru 1104961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1105961acdeaSSudarsana Reddy Kalluru { 1106961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1107961acdeaSSudarsana Reddy Kalluru int i; 1108961acdeaSSudarsana Reddy Kalluru 1109961acdeaSSudarsana Reddy Kalluru if (hfunc) 1110961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1111961acdeaSSudarsana Reddy Kalluru 1112961acdeaSSudarsana Reddy Kalluru if (!indir) 1113961acdeaSSudarsana Reddy Kalluru return 0; 1114961acdeaSSudarsana Reddy Kalluru 1115961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1116961acdeaSSudarsana Reddy Kalluru indir[i] = edev->rss_params.rss_ind_table[i]; 1117961acdeaSSudarsana Reddy Kalluru 1118961acdeaSSudarsana Reddy Kalluru if (key) 1119961acdeaSSudarsana Reddy Kalluru memcpy(key, edev->rss_params.rss_key, 1120961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1121961acdeaSSudarsana Reddy Kalluru 1122961acdeaSSudarsana Reddy Kalluru return 0; 1123961acdeaSSudarsana Reddy Kalluru } 1124961acdeaSSudarsana Reddy Kalluru 1125961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1126961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1127961acdeaSSudarsana Reddy Kalluru { 1128961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 1129961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1130961acdeaSSudarsana Reddy Kalluru int i; 1131961acdeaSSudarsana Reddy Kalluru 1132ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1133ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1134ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1135ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1136ba300ce3SSudarsana Reddy Kalluru } 1137ba300ce3SSudarsana Reddy Kalluru 1138961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1139961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1140961acdeaSSudarsana Reddy Kalluru 1141961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1142961acdeaSSudarsana Reddy Kalluru return 0; 1143961acdeaSSudarsana Reddy Kalluru 1144961acdeaSSudarsana Reddy Kalluru if (indir) { 1145961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1146961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_ind_table[i] = indir[i]; 1147961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1148961acdeaSSudarsana Reddy Kalluru } 1149961acdeaSSudarsana Reddy Kalluru 1150961acdeaSSudarsana Reddy Kalluru if (key) { 1151961acdeaSSudarsana Reddy Kalluru memcpy(&edev->rss_params.rss_key, key, 1152961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1153961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1154961acdeaSSudarsana Reddy Kalluru } 1155961acdeaSSudarsana Reddy Kalluru 1156961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1157961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1158961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1159961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1160961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1161961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1162961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1163961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1164961acdeaSSudarsana Reddy Kalluru } 1165961acdeaSSudarsana Reddy Kalluru 1166961acdeaSSudarsana Reddy Kalluru return 0; 1167961acdeaSSudarsana Reddy Kalluru } 1168961acdeaSSudarsana Reddy Kalluru 116916f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 117016f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 117116f46bf0SSudarsana Reddy Kalluru { 117216f46bf0SSudarsana Reddy Kalluru int i; 117316f46bf0SSudarsana Reddy Kalluru 117416f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 117516f46bf0SSudarsana Reddy Kalluru return; 117616f46bf0SSudarsana Reddy Kalluru 11779a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 117816f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 117916f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 118016f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 118116f46bf0SSudarsana Reddy Kalluru } 118216f46bf0SSudarsana Reddy Kalluru } 118316f46bf0SSudarsana Reddy Kalluru 118416f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 118516f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 118616f46bf0SSudarsana Reddy Kalluru { 118716f46bf0SSudarsana Reddy Kalluru int i; 118816f46bf0SSudarsana Reddy Kalluru 11899a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 119016f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 119116f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 119216f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 119316f46bf0SSudarsana Reddy Kalluru } 119416f46bf0SSudarsana Reddy Kalluru } 119516f46bf0SSudarsana Reddy Kalluru 119616f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 119716f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 119816f46bf0SSudarsana Reddy Kalluru { 11999a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 120016f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 120116f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 120216f46bf0SSudarsana Reddy Kalluru int i, idx, val; 120316f46bf0SSudarsana Reddy Kalluru 12049a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 12059a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 120680439a17SMintz, Yuval txq = edev->fp_array[i].txq; 12079a4d7e86SSudarsana Reddy Kalluru break; 12089a4d7e86SSudarsana Reddy Kalluru } 12099a4d7e86SSudarsana Reddy Kalluru } 12109a4d7e86SSudarsana Reddy Kalluru 12119a4d7e86SSudarsana Reddy Kalluru if (!txq) { 12129a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 12139a4d7e86SSudarsana Reddy Kalluru return -1; 12149a4d7e86SSudarsana Reddy Kalluru } 12159a4d7e86SSudarsana Reddy Kalluru 121616f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 121716f46bf0SSudarsana Reddy Kalluru idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; 121816f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = skb; 121916f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 122016f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 122116f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 122216f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1223351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 1224351a4dedSYuval Mintz first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); 122516f46bf0SSudarsana Reddy Kalluru 122616f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 122716f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 122816f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 122916f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 123016f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 123116f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 123216f46bf0SSudarsana Reddy Kalluru } 123316f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 123416f46bf0SSudarsana Reddy Kalluru 123516f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 123616f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 123716f46bf0SSudarsana Reddy Kalluru txq->sw_tx_prod++; 123816f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 123916f46bf0SSudarsana Reddy Kalluru val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl)); 124016f46bf0SSudarsana Reddy Kalluru txq->tx_db.data.bd_prod = val; 124116f46bf0SSudarsana Reddy Kalluru 124216f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 124316f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 124416f46bf0SSudarsana Reddy Kalluru */ 124516f46bf0SSudarsana Reddy Kalluru wmb(); 124616f46bf0SSudarsana Reddy Kalluru barrier(); 124716f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 124816f46bf0SSudarsana Reddy Kalluru 124916f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 125016f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 125116f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 125216f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 125316f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 125416f46bf0SSudarsana Reddy Kalluru */ 125516f46bf0SSudarsana Reddy Kalluru mmiowb(); 125616f46bf0SSudarsana Reddy Kalluru 125716f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 125816f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 125916f46bf0SSudarsana Reddy Kalluru break; 126016f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 126116f46bf0SSudarsana Reddy Kalluru } 126216f46bf0SSudarsana Reddy Kalluru 126316f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 126416f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 126516f46bf0SSudarsana Reddy Kalluru return -1; 126616f46bf0SSudarsana Reddy Kalluru } 126716f46bf0SSudarsana Reddy Kalluru 126816f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1269fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 127016f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 127116f46bf0SSudarsana Reddy Kalluru txq->sw_tx_cons++; 127216f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = NULL; 127316f46bf0SSudarsana Reddy Kalluru 127416f46bf0SSudarsana Reddy Kalluru return 0; 127516f46bf0SSudarsana Reddy Kalluru } 127616f46bf0SSudarsana Reddy Kalluru 127716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 127816f46bf0SSudarsana Reddy Kalluru { 127916f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 128016f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 12819a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 128216f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 128316f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1284837d4eb6SSudarsana Reddy Kalluru int i, rc = 0; 128516f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 128616f46bf0SSudarsana Reddy Kalluru 12879a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 12889a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 12899a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 12909a4d7e86SSudarsana Reddy Kalluru break; 12919a4d7e86SSudarsana Reddy Kalluru } 12929a4d7e86SSudarsana Reddy Kalluru } 12939a4d7e86SSudarsana Reddy Kalluru 12949a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 12959a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 12969a4d7e86SSudarsana Reddy Kalluru return -1; 12979a4d7e86SSudarsana Reddy Kalluru } 12989a4d7e86SSudarsana Reddy Kalluru 129916f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 130016f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 130116f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 130216f46bf0SSudarsana Reddy Kalluru */ 130316f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 130416f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1305837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1306837d4eb6SSudarsana Reddy Kalluru continue; 130716f46bf0SSudarsana Reddy Kalluru } 130816f46bf0SSudarsana Reddy Kalluru 130916f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 131016f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 131116f46bf0SSudarsana Reddy Kalluru 1312837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1313837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1314837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1315837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1316837d4eb6SSudarsana Reddy Kalluru * CQE. 131716f46bf0SSudarsana Reddy Kalluru */ 131816f46bf0SSudarsana Reddy Kalluru rmb(); 131916f46bf0SSudarsana Reddy Kalluru 132016f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 132116f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 132216f46bf0SSudarsana Reddy Kalluru 132316f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 132416f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 132516f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 132616f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 132716f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 132816f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1329837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 1330837d4eb6SSudarsana Reddy Kalluru sw_rx_data->page_offset); 1331837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1332837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1333837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 133416f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 133516f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1336837d4eb6SSudarsana Reddy Kalluru rc = -1; 1337837d4eb6SSudarsana Reddy Kalluru break; 133816f46bf0SSudarsana Reddy Kalluru } 133916f46bf0SSudarsana Reddy Kalluru 13409eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1341837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1342837d4eb6SSudarsana Reddy Kalluru break; 1343837d4eb6SSudarsana Reddy Kalluru } 134416f46bf0SSudarsana Reddy Kalluru 1345837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 13469eb22357SMintz, Yuval qede_recycle_rx_bd_ring(rxq, 1); 1347837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1348837d4eb6SSudarsana Reddy Kalluru } 1349837d4eb6SSudarsana Reddy Kalluru 1350837d4eb6SSudarsana Reddy Kalluru if (i == QEDE_SELFTEST_POLL_COUNT) { 1351837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1352837d4eb6SSudarsana Reddy Kalluru return -1; 1353837d4eb6SSudarsana Reddy Kalluru } 1354837d4eb6SSudarsana Reddy Kalluru 1355837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1356837d4eb6SSudarsana Reddy Kalluru 1357837d4eb6SSudarsana Reddy Kalluru return rc; 135816f46bf0SSudarsana Reddy Kalluru } 135916f46bf0SSudarsana Reddy Kalluru 136016f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 136116f46bf0SSudarsana Reddy Kalluru { 136216f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 136316f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 136416f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 136516f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 136616f46bf0SSudarsana Reddy Kalluru u8 *packet; 136716f46bf0SSudarsana Reddy Kalluru 136816f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 136916f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 137016f46bf0SSudarsana Reddy Kalluru return -EINVAL; 137116f46bf0SSudarsana Reddy Kalluru } 137216f46bf0SSudarsana Reddy Kalluru 137316f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 137416f46bf0SSudarsana Reddy Kalluru 137516f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 137616f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 137716f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 137816f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 137916f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 138016f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 138116f46bf0SSudarsana Reddy Kalluru 138216f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 138316f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 138416f46bf0SSudarsana Reddy Kalluru 138516f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 138616f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 138716f46bf0SSudarsana Reddy Kalluru 138816f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 138916f46bf0SSudarsana Reddy Kalluru if (!skb) { 139016f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 139116f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 139216f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 139316f46bf0SSudarsana Reddy Kalluru } 139416f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 139516f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 139616f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 139716f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 139816f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 139916f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 140016f46bf0SSudarsana Reddy Kalluru 140116f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 140216f46bf0SSudarsana Reddy Kalluru if (rc) 140316f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 140416f46bf0SSudarsana Reddy Kalluru 140516f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 140616f46bf0SSudarsana Reddy Kalluru if (rc) 140716f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 140816f46bf0SSudarsana Reddy Kalluru 140916f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 141016f46bf0SSudarsana Reddy Kalluru 141116f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 141216f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 141316f46bf0SSudarsana Reddy Kalluru 141416f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 141516f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 141616f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 141716f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 141816f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 141916f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 142016f46bf0SSudarsana Reddy Kalluru 142116f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 142216f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 142316f46bf0SSudarsana Reddy Kalluru 142416f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 142516f46bf0SSudarsana Reddy Kalluru 142616f46bf0SSudarsana Reddy Kalluru return rc; 142716f46bf0SSudarsana Reddy Kalluru } 142816f46bf0SSudarsana Reddy Kalluru 14293044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 14303044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 14313044a02eSSudarsana Reddy Kalluru { 14323044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 14333044a02eSSudarsana Reddy Kalluru 14343044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 14353044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 14363044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 14373044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 14383044a02eSSudarsana Reddy Kalluru 14393044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 14403044a02eSSudarsana Reddy Kalluru 144116f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 144216f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 144316f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 144416f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 144516f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 144616f46bf0SSudarsana Reddy Kalluru } 144716f46bf0SSudarsana Reddy Kalluru } 144816f46bf0SSudarsana Reddy Kalluru 14493044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 14503044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 14513044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14523044a02eSSudarsana Reddy Kalluru } 14533044a02eSSudarsana Reddy Kalluru 14543044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 14553044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 14563044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14573044a02eSSudarsana Reddy Kalluru } 14583044a02eSSudarsana Reddy Kalluru 14593044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 14603044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 14613044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14623044a02eSSudarsana Reddy Kalluru } 14633044a02eSSudarsana Reddy Kalluru 14643044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 14653044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 14663044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14673044a02eSSudarsana Reddy Kalluru } 14687a4b21b7SMintz, Yuval 14697a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 14707a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 14717a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 14727a4b21b7SMintz, Yuval } 14733044a02eSSudarsana Reddy Kalluru } 14743044a02eSSudarsana Reddy Kalluru 14753d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 14763d789994SManish Chopra const struct ethtool_tunable *tuna, 14773d789994SManish Chopra const void *data) 14783d789994SManish Chopra { 14793d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14803d789994SManish Chopra u32 val; 14813d789994SManish Chopra 14823d789994SManish Chopra switch (tuna->id) { 14833d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14843d789994SManish Chopra val = *(u32 *)data; 14853d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 14863d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 14873d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 14883d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 14893d789994SManish Chopra return -EINVAL; 14903d789994SManish Chopra } 14913d789994SManish Chopra 14923d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 14933d789994SManish Chopra break; 14943d789994SManish Chopra default: 14953d789994SManish Chopra return -EOPNOTSUPP; 14963d789994SManish Chopra } 14973d789994SManish Chopra 14983d789994SManish Chopra return 0; 14993d789994SManish Chopra } 15003d789994SManish Chopra 15013d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 15023d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 15033d789994SManish Chopra { 15043d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 15053d789994SManish Chopra 15063d789994SManish Chopra switch (tuna->id) { 15073d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 15083d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 15093d789994SManish Chopra break; 15103d789994SManish Chopra default: 15113d789994SManish Chopra return -EOPNOTSUPP; 15123d789994SManish Chopra } 15133d789994SManish Chopra 15143d789994SManish Chopra return 0; 15153d789994SManish Chopra } 15163d789994SManish Chopra 1517133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1518054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1519054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1520133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1521e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1522e0971c83STomer Tayar .get_regs = qede_get_regs, 152314d39648SMintz, Yuval .get_wol = qede_get_wol, 152414d39648SMintz, Yuval .set_wol = qede_set_wol, 1525133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1526133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 152732a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1528133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1529d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1530d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 153101ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 153201ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 15330f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 15340f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1535133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 15363d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1537133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1538f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1539133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1540961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1541961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1542961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1543961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1544961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1545961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 15468edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 15478edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 15483044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 15493d789994SManish Chopra .get_tunable = qede_get_tunable, 15503d789994SManish Chopra .set_tunable = qede_set_tunable, 1551133fac0eSSudarsana Kalluru }; 1552133fac0eSSudarsana Kalluru 1553fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1554054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1555fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1556fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1557fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1558fefb0202SYuval Mintz .get_link = qede_get_link, 1559fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1560fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1561fefb0202SYuval Mintz .get_strings = qede_get_strings, 1562fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1563fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1564fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1565fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1566fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1567fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1568fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1569fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1570fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1571fefb0202SYuval Mintz .get_channels = qede_get_channels, 1572fefb0202SYuval Mintz .set_channels = qede_set_channels, 15733d789994SManish Chopra .get_tunable = qede_get_tunable, 15743d789994SManish Chopra .set_tunable = qede_set_tunable, 1575fefb0202SYuval Mintz }; 1576fefb0202SYuval Mintz 1577133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1578133fac0eSSudarsana Kalluru { 1579fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1580fefb0202SYuval Mintz 1581fefb0202SYuval Mintz if (IS_VF(edev)) 1582fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1583fefb0202SYuval Mintz else 1584133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1585133fac0eSSudarsana Kalluru } 1586