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_STAT_OFFSET(stat_name) (offsetof(struct qede_stats, stat_name)) 20133fac0eSSudarsana Kalluru #define QEDE_STAT_STRING(stat_name) (#stat_name) 21133fac0eSSudarsana Kalluru #define _QEDE_STAT(stat_name, pf_only) \ 22133fac0eSSudarsana Kalluru {QEDE_STAT_OFFSET(stat_name), QEDE_STAT_STRING(stat_name), pf_only} 23133fac0eSSudarsana Kalluru #define QEDE_PF_STAT(stat_name) _QEDE_STAT(stat_name, true) 24133fac0eSSudarsana Kalluru #define QEDE_STAT(stat_name) _QEDE_STAT(stat_name, false) 25133fac0eSSudarsana Kalluru 26133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \ 27133fac0eSSudarsana Kalluru (offsetof(struct qede_rx_queue, stat_name)) 28133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name) 29133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \ 30133fac0eSSudarsana Kalluru {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} 3116f46bf0SSudarsana Reddy Kalluru 3216f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100 3316f46bf0SSudarsana Reddy Kalluru 34133fac0eSSudarsana Kalluru static const struct { 35133fac0eSSudarsana Kalluru u64 offset; 36133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 37133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = { 3868db9ec2SSudarsana Reddy Kalluru QEDE_RQSTAT(rcv_pkts), 39133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_hw_errors), 40133fac0eSSudarsana Kalluru QEDE_RQSTAT(rx_alloc_errors), 41c72a6125SManish Chopra QEDE_RQSTAT(rx_ip_frags), 42133fac0eSSudarsana Kalluru }; 43133fac0eSSudarsana Kalluru 44133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) 45133fac0eSSudarsana Kalluru #define QEDE_RQSTATS_DATA(dev, sindex, rqindex) \ 46133fac0eSSudarsana Kalluru (*((u64 *)(((char *)(dev->fp_array[(rqindex)].rxq)) +\ 47133fac0eSSudarsana Kalluru qede_rqstats_arr[(sindex)].offset))) 4868db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \ 4968db9ec2SSudarsana Reddy Kalluru (offsetof(struct qede_tx_queue, stat_name)) 5068db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name) 5168db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \ 5268db9ec2SSudarsana Reddy Kalluru {QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)} 5368db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr) 5468db9ec2SSudarsana Reddy Kalluru static const struct { 5568db9ec2SSudarsana Reddy Kalluru u64 offset; 5668db9ec2SSudarsana Reddy Kalluru char string[ETH_GSTRING_LEN]; 5768db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = { 5868db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(xmit_pkts), 5968db9ec2SSudarsana Reddy Kalluru QEDE_TQSTAT(stopped_cnt), 6068db9ec2SSudarsana Reddy Kalluru }; 6168db9ec2SSudarsana Reddy Kalluru 6268db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTATS_DATA(dev, sindex, tssid, tcid) \ 6384fd1b19SArnd Bergmann (*((u64 *)(((void *)(&dev->fp_array[tssid].txqs[tcid])) +\ 6468db9ec2SSudarsana Reddy Kalluru qede_tqstats_arr[(sindex)].offset))) 6568db9ec2SSudarsana Reddy Kalluru 66133fac0eSSudarsana Kalluru static const struct { 67133fac0eSSudarsana Kalluru u64 offset; 68133fac0eSSudarsana Kalluru char string[ETH_GSTRING_LEN]; 69133fac0eSSudarsana Kalluru bool pf_only; 70133fac0eSSudarsana Kalluru } qede_stats_arr[] = { 71133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_bytes), 72133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_bytes), 73133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_bytes), 74133fac0eSSudarsana Kalluru QEDE_STAT(rx_ucast_pkts), 75133fac0eSSudarsana Kalluru QEDE_STAT(rx_mcast_pkts), 76133fac0eSSudarsana Kalluru QEDE_STAT(rx_bcast_pkts), 77133fac0eSSudarsana Kalluru 78133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_bytes), 79133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_bytes), 80133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_bytes), 81133fac0eSSudarsana Kalluru QEDE_STAT(tx_ucast_pkts), 82133fac0eSSudarsana Kalluru QEDE_STAT(tx_mcast_pkts), 83133fac0eSSudarsana Kalluru QEDE_STAT(tx_bcast_pkts), 84133fac0eSSudarsana Kalluru 85133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_64_byte_packets), 86d4967cf3SYuval Mintz QEDE_PF_STAT(rx_65_to_127_byte_packets), 87d4967cf3SYuval Mintz QEDE_PF_STAT(rx_128_to_255_byte_packets), 88d4967cf3SYuval Mintz QEDE_PF_STAT(rx_256_to_511_byte_packets), 89d4967cf3SYuval Mintz QEDE_PF_STAT(rx_512_to_1023_byte_packets), 90d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1024_to_1518_byte_packets), 91d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1519_to_1522_byte_packets), 92d4967cf3SYuval Mintz QEDE_PF_STAT(rx_1519_to_2047_byte_packets), 93d4967cf3SYuval Mintz QEDE_PF_STAT(rx_2048_to_4095_byte_packets), 94d4967cf3SYuval Mintz QEDE_PF_STAT(rx_4096_to_9216_byte_packets), 95d4967cf3SYuval Mintz QEDE_PF_STAT(rx_9217_to_16383_byte_packets), 96133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_64_byte_packets), 97133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_65_to_127_byte_packets), 98133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_128_to_255_byte_packets), 99133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_256_to_511_byte_packets), 100133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_512_to_1023_byte_packets), 101133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1024_to_1518_byte_packets), 102133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_1519_to_2047_byte_packets), 103133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_2048_to_4095_byte_packets), 104133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_4096_to_9216_byte_packets), 105133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_9217_to_16383_byte_packets), 106133fac0eSSudarsana Kalluru 107133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_mac_crtl_frames), 108133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_mac_ctrl_frames), 109133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pause_frames), 110133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pause_frames), 111133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_pfc_frames), 112133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_pfc_frames), 113133fac0eSSudarsana Kalluru 114133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_crc_errors), 115133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_align_errors), 116133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_carrier_errors), 117133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_oversize_packets), 118133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_jabbers), 119133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_undersize_packets), 120133fac0eSSudarsana Kalluru QEDE_PF_STAT(rx_fragments), 121133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_lpi_entry_count), 122133fac0eSSudarsana Kalluru QEDE_PF_STAT(tx_total_collisions), 123133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_truncates), 124133fac0eSSudarsana Kalluru QEDE_PF_STAT(brb_discards), 125133fac0eSSudarsana Kalluru QEDE_STAT(no_buff_discards), 126133fac0eSSudarsana Kalluru QEDE_PF_STAT(mftag_filter_discards), 127133fac0eSSudarsana Kalluru QEDE_PF_STAT(mac_filter_discards), 128133fac0eSSudarsana Kalluru QEDE_STAT(tx_err_drop_pkts), 1291a5a366fSSudarsana Reddy Kalluru QEDE_STAT(ttl0_discard), 1301a5a366fSSudarsana Reddy Kalluru QEDE_STAT(packet_too_big_discard), 131133fac0eSSudarsana Kalluru 132133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_pkts), 133133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_events), 134133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_aborts_num), 135133fac0eSSudarsana Kalluru QEDE_STAT(non_coalesced_pkts), 136133fac0eSSudarsana Kalluru QEDE_STAT(coalesced_bytes), 137133fac0eSSudarsana Kalluru }; 138133fac0eSSudarsana Kalluru 139133fac0eSSudarsana Kalluru #define QEDE_STATS_DATA(dev, index) \ 140133fac0eSSudarsana Kalluru (*((u64 *)(((char *)(dev)) + offsetof(struct qede_dev, stats) \ 141133fac0eSSudarsana Kalluru + qede_stats_arr[(index)].offset))) 142133fac0eSSudarsana Kalluru 143133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) 144133fac0eSSudarsana Kalluru 145f3e72109SYuval Mintz enum { 146f3e72109SYuval Mintz QEDE_PRI_FLAG_CMT, 147f3e72109SYuval Mintz QEDE_PRI_FLAG_LEN, 148f3e72109SYuval Mintz }; 149f3e72109SYuval Mintz 150f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { 151f3e72109SYuval Mintz "Coupled-Function", 152f3e72109SYuval Mintz }; 153f3e72109SYuval Mintz 1543044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests { 15516f46bf0SSudarsana Reddy Kalluru QEDE_ETHTOOL_INT_LOOPBACK, 1563044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_INTERRUPT_TEST, 1573044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_MEMORY_TEST, 1583044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_REGISTER_TEST, 1593044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_CLOCK_TEST, 1603044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 1613044a02eSSudarsana Reddy Kalluru }; 1623044a02eSSudarsana Reddy Kalluru 1633044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 16416f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 1653044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 1663044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 1673044a02eSSudarsana Reddy Kalluru "Register (online)\t", 1683044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 1693044a02eSSudarsana Reddy Kalluru }; 1703044a02eSSudarsana Reddy Kalluru 171133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 172133fac0eSSudarsana Kalluru { 173133fac0eSSudarsana Kalluru int i, j, k; 174133fac0eSSudarsana Kalluru 1759a4d7e86SSudarsana Reddy Kalluru for (i = 0, k = 0; i < QEDE_QUEUE_CNT(edev); i++) { 17668db9ec2SSudarsana Reddy Kalluru int tc; 17768db9ec2SSudarsana Reddy Kalluru 17868db9ec2SSudarsana Reddy Kalluru for (j = 0; j < QEDE_NUM_RQSTATS; j++) 17968db9ec2SSudarsana Reddy Kalluru sprintf(buf + (k + j) * ETH_GSTRING_LEN, 18068db9ec2SSudarsana Reddy Kalluru "%d: %s", i, qede_rqstats_arr[j].string); 18168db9ec2SSudarsana Reddy Kalluru k += QEDE_NUM_RQSTATS; 18268db9ec2SSudarsana Reddy Kalluru for (tc = 0; tc < edev->num_tc; tc++) { 18368db9ec2SSudarsana Reddy Kalluru for (j = 0; j < QEDE_NUM_TQSTATS; j++) 18468db9ec2SSudarsana Reddy Kalluru sprintf(buf + (k + j) * ETH_GSTRING_LEN, 18568db9ec2SSudarsana Reddy Kalluru "%d.%d: %s", i, tc, 18668db9ec2SSudarsana Reddy Kalluru qede_tqstats_arr[j].string); 18768db9ec2SSudarsana Reddy Kalluru k += QEDE_NUM_TQSTATS; 18868db9ec2SSudarsana Reddy Kalluru } 18968db9ec2SSudarsana Reddy Kalluru } 19068db9ec2SSudarsana Reddy Kalluru 191133fac0eSSudarsana Kalluru for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) { 192fefb0202SYuval Mintz if (IS_VF(edev) && qede_stats_arr[i].pf_only) 193fefb0202SYuval Mintz continue; 19468db9ec2SSudarsana Reddy Kalluru strcpy(buf + (k + j) * ETH_GSTRING_LEN, 195133fac0eSSudarsana Kalluru qede_stats_arr[i].string); 196133fac0eSSudarsana Kalluru j++; 197133fac0eSSudarsana Kalluru } 198133fac0eSSudarsana Kalluru } 199133fac0eSSudarsana Kalluru 200133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 201133fac0eSSudarsana Kalluru { 202133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 203133fac0eSSudarsana Kalluru 204133fac0eSSudarsana Kalluru switch (stringset) { 205133fac0eSSudarsana Kalluru case ETH_SS_STATS: 206133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 207133fac0eSSudarsana Kalluru break; 208f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 209f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 210f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 211f3e72109SYuval Mintz break; 2123044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2133044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 2143044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 2153044a02eSSudarsana Reddy Kalluru break; 216133fac0eSSudarsana Kalluru default: 217133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 218133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 219133fac0eSSudarsana Kalluru } 220133fac0eSSudarsana Kalluru } 221133fac0eSSudarsana Kalluru 222133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 223133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 224133fac0eSSudarsana Kalluru { 225133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 226133fac0eSSudarsana Kalluru int sidx, cnt = 0; 227133fac0eSSudarsana Kalluru int qid; 228133fac0eSSudarsana Kalluru 229133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 230133fac0eSSudarsana Kalluru 231133fac0eSSudarsana Kalluru mutex_lock(&edev->qede_lock); 232133fac0eSSudarsana Kalluru 2339a4d7e86SSudarsana Reddy Kalluru for (qid = 0; qid < QEDE_QUEUE_CNT(edev); qid++) { 23468db9ec2SSudarsana Reddy Kalluru int tc; 23568db9ec2SSudarsana Reddy Kalluru 2369a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[qid].type & QEDE_FASTPATH_RX) { 23768db9ec2SSudarsana Reddy Kalluru for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++) 23868db9ec2SSudarsana Reddy Kalluru buf[cnt++] = QEDE_RQSTATS_DATA(edev, sidx, qid); 2399a4d7e86SSudarsana Reddy Kalluru } 2409a4d7e86SSudarsana Reddy Kalluru 2419a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[qid].type & QEDE_FASTPATH_TX) { 24268db9ec2SSudarsana Reddy Kalluru for (tc = 0; tc < edev->num_tc; tc++) { 24368db9ec2SSudarsana Reddy Kalluru for (sidx = 0; sidx < QEDE_NUM_TQSTATS; sidx++) 2449a4d7e86SSudarsana Reddy Kalluru buf[cnt++] = QEDE_TQSTATS_DATA(edev, 2459a4d7e86SSudarsana Reddy Kalluru sidx, 2469a4d7e86SSudarsana Reddy Kalluru qid, tc); 2479a4d7e86SSudarsana Reddy Kalluru } 24868db9ec2SSudarsana Reddy Kalluru } 24968db9ec2SSudarsana Reddy Kalluru } 25068db9ec2SSudarsana Reddy Kalluru 251fefb0202SYuval Mintz for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++) { 252fefb0202SYuval Mintz if (IS_VF(edev) && qede_stats_arr[sidx].pf_only) 253fefb0202SYuval Mintz continue; 254133fac0eSSudarsana Kalluru buf[cnt++] = QEDE_STATS_DATA(edev, sidx); 255fefb0202SYuval Mintz } 256133fac0eSSudarsana Kalluru 257133fac0eSSudarsana Kalluru mutex_unlock(&edev->qede_lock); 258133fac0eSSudarsana Kalluru } 259133fac0eSSudarsana Kalluru 260133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 261133fac0eSSudarsana Kalluru { 262133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 263133fac0eSSudarsana Kalluru int num_stats = QEDE_NUM_STATS; 264133fac0eSSudarsana Kalluru 265133fac0eSSudarsana Kalluru switch (stringset) { 266133fac0eSSudarsana Kalluru case ETH_SS_STATS: 267fefb0202SYuval Mintz if (IS_VF(edev)) { 268fefb0202SYuval Mintz int i; 269fefb0202SYuval Mintz 270fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 271fefb0202SYuval Mintz if (qede_stats_arr[i].pf_only) 272fefb0202SYuval Mintz num_stats--; 273fefb0202SYuval Mintz } 2749a4d7e86SSudarsana Reddy Kalluru return num_stats + QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS + 2759a4d7e86SSudarsana Reddy Kalluru QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * edev->num_tc; 276f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 277f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 2783044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2796ecb0a0cSYuval Mintz if (!IS_VF(edev)) 2803044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 2816ecb0a0cSYuval Mintz else 2826ecb0a0cSYuval Mintz return 0; 283133fac0eSSudarsana Kalluru default: 284133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 285133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 286133fac0eSSudarsana Kalluru return -EINVAL; 287133fac0eSSudarsana Kalluru } 288133fac0eSSudarsana Kalluru } 289133fac0eSSudarsana Kalluru 290f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 291f3e72109SYuval Mintz { 292f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 293f3e72109SYuval Mintz 294f3e72109SYuval Mintz return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; 295f3e72109SYuval Mintz } 296f3e72109SYuval Mintz 297054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 298054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 299054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 300054c67d1SSudarsana Reddy Kalluru }; 301054c67d1SSudarsana Reddy Kalluru 302054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 303054c67d1SSudarsana Reddy Kalluru {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, 304054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 305054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 306054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 307054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT}, 308054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 309054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 310054c67d1SSudarsana Reddy Kalluru {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 311054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 312054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 313054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 314054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 315054c67d1SSudarsana Reddy Kalluru }; 316054c67d1SSudarsana Reddy Kalluru 317054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 318054c67d1SSudarsana Reddy Kalluru { \ 319054c67d1SSudarsana Reddy Kalluru int i; \ 320054c67d1SSudarsana Reddy Kalluru \ 321054c67d1SSudarsana Reddy Kalluru for (i = 0; i < QED_LM_COUNT; i++) { \ 322054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 323054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 324054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 325054c67d1SSudarsana Reddy Kalluru } \ 326054c67d1SSudarsana Reddy Kalluru } 327054c67d1SSudarsana Reddy Kalluru 328054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 329054c67d1SSudarsana Reddy Kalluru { \ 330054c67d1SSudarsana Reddy Kalluru int i; \ 331054c67d1SSudarsana Reddy Kalluru \ 332054c67d1SSudarsana Reddy Kalluru for (i = 0; i < QED_LM_COUNT; i++) { \ 333054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 334054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 335054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 336054c67d1SSudarsana Reddy Kalluru } \ 337054c67d1SSudarsana Reddy Kalluru } 338054c67d1SSudarsana Reddy Kalluru 339054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 340054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 341133fac0eSSudarsana Kalluru { 342054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 343133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 344133fac0eSSudarsana Kalluru struct qed_link_output current_link; 345133fac0eSSudarsana Kalluru 346133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 347133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 348133fac0eSSudarsana Kalluru 349054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 350054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 351054c67d1SSudarsana Reddy Kalluru 352054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 353054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 354054c67d1SSudarsana Reddy Kalluru 355054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 356054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 357054c67d1SSudarsana Reddy Kalluru 358133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 359054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 360054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 361133fac0eSSudarsana Kalluru } else { 362054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 363054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 364133fac0eSSudarsana Kalluru } 365054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 366054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 367133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 368133fac0eSSudarsana Kalluru 369133fac0eSSudarsana Kalluru return 0; 370133fac0eSSudarsana Kalluru } 371133fac0eSSudarsana Kalluru 372054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 373054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 374133fac0eSSudarsana Kalluru { 375054c67d1SSudarsana Reddy Kalluru const 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 struct qed_link_params params; 379133fac0eSSudarsana Kalluru 380fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 381054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 382133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 383133fac0eSSudarsana Kalluru } 384133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 385133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 386133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 387133fac0eSSudarsana Kalluru 388133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 389133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 390054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 391133fac0eSSudarsana Kalluru params.autoneg = true; 392133fac0eSSudarsana Kalluru params.forced_speed = 0; 393054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 394133fac0eSSudarsana Kalluru } else { /* forced speed */ 395133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 396133fac0eSSudarsana Kalluru params.autoneg = false; 397054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 398054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 399133fac0eSSudarsana Kalluru case SPEED_10000: 400133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 401054c67d1SSudarsana Reddy Kalluru QED_LM_10000baseKR_Full_BIT)) { 402133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 403133fac0eSSudarsana Kalluru return -EINVAL; 404133fac0eSSudarsana Kalluru } 405054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_10000baseKR_Full_BIT; 406054c67d1SSudarsana Reddy Kalluru break; 407054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 408054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 409054c67d1SSudarsana Reddy Kalluru QED_LM_25000baseKR_Full_BIT)) { 410054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 411054c67d1SSudarsana Reddy Kalluru return -EINVAL; 412054c67d1SSudarsana Reddy Kalluru } 413054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_25000baseKR_Full_BIT; 414133fac0eSSudarsana Kalluru break; 415133fac0eSSudarsana Kalluru case SPEED_40000: 416133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 417054c67d1SSudarsana Reddy Kalluru QED_LM_40000baseLR4_Full_BIT)) { 418133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 419133fac0eSSudarsana Kalluru return -EINVAL; 420133fac0eSSudarsana Kalluru } 421054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_40000baseLR4_Full_BIT; 422054c67d1SSudarsana Reddy Kalluru break; 42316d5946aSYuval Mintz case SPEED_50000: 424054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 425054c67d1SSudarsana Reddy Kalluru QED_LM_50000baseKR2_Full_BIT)) { 426054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 427054c67d1SSudarsana Reddy Kalluru return -EINVAL; 428054c67d1SSudarsana Reddy Kalluru } 429054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_50000baseKR2_Full_BIT; 430054c67d1SSudarsana Reddy Kalluru break; 43116d5946aSYuval Mintz case SPEED_100000: 432054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 433054c67d1SSudarsana Reddy Kalluru QED_LM_100000baseKR4_Full_BIT)) { 434054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 435054c67d1SSudarsana Reddy Kalluru return -EINVAL; 436054c67d1SSudarsana Reddy Kalluru } 437054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_100000baseKR4_Full_BIT; 438133fac0eSSudarsana Kalluru break; 439133fac0eSSudarsana Kalluru default: 440054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 441133fac0eSSudarsana Kalluru return -EINVAL; 442133fac0eSSudarsana Kalluru } 443133fac0eSSudarsana Kalluru } 444133fac0eSSudarsana Kalluru 445133fac0eSSudarsana Kalluru params.link_up = true; 446133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 447133fac0eSSudarsana Kalluru 448133fac0eSSudarsana Kalluru return 0; 449133fac0eSSudarsana Kalluru } 450133fac0eSSudarsana Kalluru 451133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 452133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 453133fac0eSSudarsana Kalluru { 454133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 455133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 456133fac0eSSudarsana Kalluru 457133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 458133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 459133fac0eSSudarsana Kalluru 460133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 461133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 462133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 463133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 464133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 465133fac0eSSudarsana Kalluru 466133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 467133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 468133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 469133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 470133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 471133fac0eSSudarsana Kalluru 472133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 473133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 474133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 475133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 476133fac0eSSudarsana Kalluru } else { 477133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 478133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 479133fac0eSSudarsana Kalluru } 480133fac0eSSudarsana Kalluru 481133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 482133fac0eSSudarsana Kalluru } 483133fac0eSSudarsana Kalluru 484133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 485133fac0eSSudarsana Kalluru { 486133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 487133fac0eSSudarsana Kalluru 4881a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 489133fac0eSSudarsana Kalluru } 490133fac0eSSudarsana Kalluru 491133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 492133fac0eSSudarsana Kalluru { 493133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 494133fac0eSSudarsana Kalluru u32 dp_module = 0; 495133fac0eSSudarsana Kalluru u8 dp_level = 0; 496133fac0eSSudarsana Kalluru 497133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 498133fac0eSSudarsana Kalluru 499133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 500133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 501133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 502133fac0eSSudarsana Kalluru dp_module, dp_level); 503133fac0eSSudarsana Kalluru } 504133fac0eSSudarsana Kalluru 50532a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 50632a7a570SSudarsana Kalluru { 50732a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 50832a7a570SSudarsana Kalluru struct qed_link_output current_link; 50932a7a570SSudarsana Kalluru struct qed_link_params link_params; 51032a7a570SSudarsana Kalluru 511fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 5121a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 513fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 514fe7cd2bfSYuval Mintz } 515fe7cd2bfSYuval Mintz 51632a7a570SSudarsana Kalluru if (!netif_running(dev)) 51732a7a570SSudarsana Kalluru return 0; 51832a7a570SSudarsana Kalluru 51932a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 52032a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 52132a7a570SSudarsana Kalluru if (!current_link.link_up) 52232a7a570SSudarsana Kalluru return 0; 52332a7a570SSudarsana Kalluru 52432a7a570SSudarsana Kalluru /* Toggle the link */ 52532a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 52632a7a570SSudarsana Kalluru link_params.link_up = false; 52732a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 52832a7a570SSudarsana Kalluru link_params.link_up = true; 52932a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 53032a7a570SSudarsana Kalluru 53132a7a570SSudarsana Kalluru return 0; 53232a7a570SSudarsana Kalluru } 53332a7a570SSudarsana Kalluru 534133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 535133fac0eSSudarsana Kalluru { 536133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 537133fac0eSSudarsana Kalluru struct qed_link_output current_link; 538133fac0eSSudarsana Kalluru 539133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 540133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 541133fac0eSSudarsana Kalluru 542133fac0eSSudarsana Kalluru return current_link.link_up; 543133fac0eSSudarsana Kalluru } 544133fac0eSSudarsana Kalluru 545d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 546d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 547d552fa84SSudarsana Reddy Kalluru { 548d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 549d2890deaSSudarsana Reddy Kalluru u16 rxc, txc; 550d552fa84SSudarsana Reddy Kalluru 551d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 552d2890deaSSudarsana Reddy Kalluru edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc); 553d2890deaSSudarsana Reddy Kalluru 554d2890deaSSudarsana Reddy Kalluru coal->rx_coalesce_usecs = rxc; 555d2890deaSSudarsana Reddy Kalluru coal->tx_coalesce_usecs = txc; 556d552fa84SSudarsana Reddy Kalluru 557d552fa84SSudarsana Reddy Kalluru return 0; 558d552fa84SSudarsana Reddy Kalluru } 559d552fa84SSudarsana Reddy Kalluru 560d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 561d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 562d552fa84SSudarsana Reddy Kalluru { 563d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 564d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 565d552fa84SSudarsana Reddy Kalluru u16 rxc, txc; 566d552fa84SSudarsana Reddy Kalluru u8 sb_id; 567d552fa84SSudarsana Reddy Kalluru 568d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 569d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 570d552fa84SSudarsana Reddy Kalluru return -EINVAL; 571d552fa84SSudarsana Reddy Kalluru } 572d552fa84SSudarsana Reddy Kalluru 573d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 574d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 575d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 576d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 577d552fa84SSudarsana Reddy Kalluru coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" 578d552fa84SSudarsana Reddy Kalluru : "tx", 579d552fa84SSudarsana Reddy Kalluru QED_COALESCE_MAX); 580d552fa84SSudarsana Reddy Kalluru return -EINVAL; 581d552fa84SSudarsana Reddy Kalluru } 582d552fa84SSudarsana Reddy Kalluru 583d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 584d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 5859a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 586d552fa84SSudarsana Reddy Kalluru sb_id = edev->fp_array[i].sb_info->igu_sb_id; 587d552fa84SSudarsana Reddy Kalluru rc = edev->ops->common->set_coalesce(edev->cdev, rxc, txc, 588d552fa84SSudarsana Reddy Kalluru (u8)i, sb_id); 589d552fa84SSudarsana Reddy Kalluru if (rc) { 590d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Set coalesce error, rc = %d\n", rc); 591d552fa84SSudarsana Reddy Kalluru return rc; 592d552fa84SSudarsana Reddy Kalluru } 593d552fa84SSudarsana Reddy Kalluru } 594d552fa84SSudarsana Reddy Kalluru 595d552fa84SSudarsana Reddy Kalluru return rc; 596d552fa84SSudarsana Reddy Kalluru } 597d552fa84SSudarsana Reddy Kalluru 59801ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 59901ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 60001ef7e05SSudarsana Kalluru { 60101ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 60201ef7e05SSudarsana Kalluru 60301ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 60401ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 60501ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 60601ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 60701ef7e05SSudarsana Kalluru } 60801ef7e05SSudarsana Kalluru 60901ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 61001ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 61101ef7e05SSudarsana Kalluru { 61201ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 61301ef7e05SSudarsana Kalluru 61401ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 61501ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 61601ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 61701ef7e05SSudarsana Kalluru 61801ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 61901ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 62001ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 62101ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 62201ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 62301ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 62401ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 62501ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 62601ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 62701ef7e05SSudarsana Kalluru return -EINVAL; 62801ef7e05SSudarsana Kalluru } 62901ef7e05SSudarsana Kalluru 63001ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 63101ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 63201ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 63301ef7e05SSudarsana Kalluru 63401ef7e05SSudarsana Kalluru if (netif_running(edev->ndev)) 63501ef7e05SSudarsana Kalluru qede_reload(edev, NULL, NULL); 63601ef7e05SSudarsana Kalluru 63701ef7e05SSudarsana Kalluru return 0; 63801ef7e05SSudarsana Kalluru } 63901ef7e05SSudarsana Kalluru 6400f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 6410f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 6420f7db144SSudarsana Kalluru { 6430f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 6440f7db144SSudarsana Kalluru struct qed_link_output current_link; 6450f7db144SSudarsana Kalluru 6460f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 6470f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 6480f7db144SSudarsana Kalluru 6490f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 6500f7db144SSudarsana Kalluru epause->autoneg = true; 6510f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 6520f7db144SSudarsana Kalluru epause->rx_pause = true; 6530f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 6540f7db144SSudarsana Kalluru epause->tx_pause = true; 6550f7db144SSudarsana Kalluru 6560f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 6570f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 6580f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 6590f7db144SSudarsana Kalluru epause->tx_pause); 6600f7db144SSudarsana Kalluru } 6610f7db144SSudarsana Kalluru 6620f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 6630f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 6640f7db144SSudarsana Kalluru { 6650f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 6660f7db144SSudarsana Kalluru struct qed_link_params params; 6670f7db144SSudarsana Kalluru struct qed_link_output current_link; 6680f7db144SSudarsana Kalluru 669fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 6700f7db144SSudarsana Kalluru DP_INFO(edev, 671fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 6720f7db144SSudarsana Kalluru return -EOPNOTSUPP; 6730f7db144SSudarsana Kalluru } 6740f7db144SSudarsana Kalluru 6750f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 6760f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 6770f7db144SSudarsana Kalluru 6780f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 6790f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 6800f7db144SSudarsana Kalluru if (epause->autoneg) { 681d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 6820f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 6830f7db144SSudarsana Kalluru return -EINVAL; 6840f7db144SSudarsana Kalluru } 6850f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 6860f7db144SSudarsana Kalluru } 6870f7db144SSudarsana Kalluru if (epause->rx_pause) 6880f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 6890f7db144SSudarsana Kalluru if (epause->tx_pause) 6900f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 6910f7db144SSudarsana Kalluru 6920f7db144SSudarsana Kalluru params.link_up = true; 6930f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 6940f7db144SSudarsana Kalluru 6950f7db144SSudarsana Kalluru return 0; 6960f7db144SSudarsana Kalluru } 6970f7db144SSudarsana Kalluru 698e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 699e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 700e0971c83STomer Tayar { 701e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 702e0971c83STomer Tayar 703e0971c83STomer Tayar regs->version = 0; 704e0971c83STomer Tayar memset(buffer, 0, regs->len); 705e0971c83STomer Tayar 706e0971c83STomer Tayar if (edev->ops && edev->ops->common) 707e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 708e0971c83STomer Tayar } 709e0971c83STomer Tayar 710e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 711e0971c83STomer Tayar { 712e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 713e0971c83STomer Tayar 714e0971c83STomer Tayar if (edev->ops && edev->ops->common) 715e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 716e0971c83STomer Tayar else 717e0971c83STomer Tayar return -EINVAL; 718e0971c83STomer Tayar } 719e0971c83STomer Tayar 720133fac0eSSudarsana Kalluru static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args) 721133fac0eSSudarsana Kalluru { 722133fac0eSSudarsana Kalluru edev->ndev->mtu = args->mtu; 723133fac0eSSudarsana Kalluru } 724133fac0eSSudarsana Kalluru 725133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 726133fac0eSSudarsana Kalluru #define ETH_MAX_JUMBO_PACKET_SIZE 9600 727133fac0eSSudarsana Kalluru #define ETH_MIN_PACKET_SIZE 60 728133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 729133fac0eSSudarsana Kalluru { 730133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 731133fac0eSSudarsana Kalluru union qede_reload_args args; 732133fac0eSSudarsana Kalluru 733133fac0eSSudarsana Kalluru if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || 734133fac0eSSudarsana Kalluru ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) { 735133fac0eSSudarsana Kalluru DP_ERR(edev, "Can't support requested MTU size\n"); 736133fac0eSSudarsana Kalluru return -EINVAL; 737133fac0eSSudarsana Kalluru } 738133fac0eSSudarsana Kalluru 739133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 740133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 741133fac0eSSudarsana Kalluru 742133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed*/ 743133fac0eSSudarsana Kalluru args.mtu = new_mtu; 744133fac0eSSudarsana Kalluru 745133fac0eSSudarsana Kalluru if (netif_running(edev->ndev)) 746133fac0eSSudarsana Kalluru qede_reload(edev, &qede_update_mtu, &args); 747133fac0eSSudarsana Kalluru 748133fac0eSSudarsana Kalluru qede_update_mtu(edev, &args); 749133fac0eSSudarsana Kalluru 750133fac0eSSudarsana Kalluru return 0; 751133fac0eSSudarsana Kalluru } 752133fac0eSSudarsana Kalluru 7538edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 7548edf049dSSudarsana Kalluru struct ethtool_channels *channels) 7558edf049dSSudarsana Kalluru { 7568edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7578edf049dSSudarsana Kalluru 7588edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 759bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 760bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 7619a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 7629a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 7639a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 7649a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 7658edf049dSSudarsana Kalluru } 7668edf049dSSudarsana Kalluru 7678edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 7688edf049dSSudarsana Kalluru struct ethtool_channels *channels) 7698edf049dSSudarsana Kalluru { 7708edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7719a4d7e86SSudarsana Reddy Kalluru u32 count; 7728edf049dSSudarsana Kalluru 7738edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 7748edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 7758edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 7768edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 7778edf049dSSudarsana Kalluru 7789a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 7799a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 7809a4d7e86SSudarsana Reddy Kalluru 7819a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 7829a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 7838edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 7848edf049dSSudarsana Kalluru "command parameters not supported\n"); 7858edf049dSSudarsana Kalluru return -EINVAL; 7868edf049dSSudarsana Kalluru } 7878edf049dSSudarsana Kalluru 7889a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 7899a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 7909a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 7919a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 7929a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 7939a4d7e86SSudarsana Reddy Kalluru } 7949a4d7e86SSudarsana Reddy Kalluru 7959a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 7969a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 7979a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 7989a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 7999a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 8009a4d7e86SSudarsana Reddy Kalluru } 8019a4d7e86SSudarsana Reddy Kalluru 8028edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 8039a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 8049a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 8059a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 8068edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8078edf049dSSudarsana Kalluru "No change in active parameters\n"); 8088edf049dSSudarsana Kalluru return 0; 8098edf049dSSudarsana Kalluru } 8108edf049dSSudarsana Kalluru 8118edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 8129a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 8139a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 8149a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 8158edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8169a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 8178edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 8188edf049dSSudarsana Kalluru return -EINVAL; 8198edf049dSSudarsana Kalluru } 8208edf049dSSudarsana Kalluru 8218edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 8229a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 8239a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 8249a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 8258edf049dSSudarsana Kalluru if (netif_running(dev)) 8268edf049dSSudarsana Kalluru qede_reload(edev, NULL, NULL); 8278edf049dSSudarsana Kalluru 8288edf049dSSudarsana Kalluru return 0; 8298edf049dSSudarsana Kalluru } 8308edf049dSSudarsana Kalluru 8313d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 8323d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 8333d971cbdSSudarsana Kalluru { 8343d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8353d971cbdSSudarsana Kalluru u8 led_state = 0; 8363d971cbdSSudarsana Kalluru 8373d971cbdSSudarsana Kalluru switch (state) { 8383d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 8393d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 8403d971cbdSSudarsana Kalluru 8413d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 8423d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 8433d971cbdSSudarsana Kalluru break; 8443d971cbdSSudarsana Kalluru 8453d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 8463d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 8473d971cbdSSudarsana Kalluru break; 8483d971cbdSSudarsana Kalluru 8493d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 8503d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 8513d971cbdSSudarsana Kalluru break; 8523d971cbdSSudarsana Kalluru } 8533d971cbdSSudarsana Kalluru 8543d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 8553d971cbdSSudarsana Kalluru 8563d971cbdSSudarsana Kalluru return 0; 8573d971cbdSSudarsana Kalluru } 8583d971cbdSSudarsana Kalluru 859961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 860961acdeaSSudarsana Reddy Kalluru { 861961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 862961acdeaSSudarsana Reddy Kalluru 863961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 864961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 865961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 866961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 867961acdeaSSudarsana Reddy Kalluru break; 868961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 869961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP) 870961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 871961acdeaSSudarsana Reddy Kalluru break; 872961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 873961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP) 874961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 875961acdeaSSudarsana Reddy Kalluru break; 876961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 877961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 878961acdeaSSudarsana Reddy Kalluru break; 879961acdeaSSudarsana Reddy Kalluru default: 880961acdeaSSudarsana Reddy Kalluru info->data = 0; 881961acdeaSSudarsana Reddy Kalluru break; 882961acdeaSSudarsana Reddy Kalluru } 883961acdeaSSudarsana Reddy Kalluru 884961acdeaSSudarsana Reddy Kalluru return 0; 885961acdeaSSudarsana Reddy Kalluru } 886961acdeaSSudarsana Reddy Kalluru 887961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 888961acdeaSSudarsana Reddy Kalluru u32 *rules __always_unused) 889961acdeaSSudarsana Reddy Kalluru { 890961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 891961acdeaSSudarsana Reddy Kalluru 892961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 893961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 8949a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 895961acdeaSSudarsana Reddy Kalluru return 0; 896961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 897961acdeaSSudarsana Reddy Kalluru return qede_get_rss_flags(edev, info); 898961acdeaSSudarsana Reddy Kalluru default: 899961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 900961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 901961acdeaSSudarsana Reddy Kalluru } 902961acdeaSSudarsana Reddy Kalluru } 903961acdeaSSudarsana Reddy Kalluru 904961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 905961acdeaSSudarsana Reddy Kalluru { 906961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 907961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 908961acdeaSSudarsana Reddy Kalluru 909961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 910961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 911961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 912961acdeaSSudarsana Reddy Kalluru 913961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 914961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 915961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 916961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 917961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 918961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 919961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 920961acdeaSSudarsana Reddy Kalluru return -EINVAL; 921961acdeaSSudarsana Reddy Kalluru } 922961acdeaSSudarsana Reddy Kalluru return 0; 923961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 924961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 925961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 926961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 927961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 928961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 929961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 930961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 931961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 932961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 933961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 934961acdeaSSudarsana Reddy Kalluru } else { 935961acdeaSSudarsana Reddy Kalluru return -EINVAL; 936961acdeaSSudarsana Reddy Kalluru } 937961acdeaSSudarsana Reddy Kalluru break; 938961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 939961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 940961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 941961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 942961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 943961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 944961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 945961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 946961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 947961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 948961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 949961acdeaSSudarsana Reddy Kalluru } else { 950961acdeaSSudarsana Reddy Kalluru return -EINVAL; 951961acdeaSSudarsana Reddy Kalluru } 952961acdeaSSudarsana Reddy Kalluru break; 953961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 954961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 955961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 956961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 957961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 958961acdeaSSudarsana Reddy Kalluru return -EINVAL; 959961acdeaSSudarsana Reddy Kalluru } 960961acdeaSSudarsana Reddy Kalluru return 0; 961961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 962961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 963961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 964961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 965961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 966961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 967961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 968961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 969961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 970961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 971961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 972961acdeaSSudarsana Reddy Kalluru if (info->data) { 973961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 974961acdeaSSudarsana Reddy Kalluru return -EINVAL; 975961acdeaSSudarsana Reddy Kalluru } 976961acdeaSSudarsana Reddy Kalluru return 0; 977961acdeaSSudarsana Reddy Kalluru default: 978961acdeaSSudarsana Reddy Kalluru return -EINVAL; 979961acdeaSSudarsana Reddy Kalluru } 980961acdeaSSudarsana Reddy Kalluru 981961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 982961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps & 983961acdeaSSudarsana Reddy Kalluru ~clr_caps) | set_caps)) 984961acdeaSSudarsana Reddy Kalluru return 0; 985961acdeaSSudarsana Reddy Kalluru 986961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 987961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) | 988961acdeaSSudarsana Reddy Kalluru set_caps; 989961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 990961acdeaSSudarsana Reddy Kalluru 991961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 992961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 993961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 994961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 995961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 996961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 997961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 998961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 999961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1000961acdeaSSudarsana Reddy Kalluru } 1001961acdeaSSudarsana Reddy Kalluru 1002961acdeaSSudarsana Reddy Kalluru return 0; 1003961acdeaSSudarsana Reddy Kalluru } 1004961acdeaSSudarsana Reddy Kalluru 1005961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1006961acdeaSSudarsana Reddy Kalluru { 1007961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1008961acdeaSSudarsana Reddy Kalluru 1009961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1010961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 1011961acdeaSSudarsana Reddy Kalluru return qede_set_rss_flags(edev, info); 1012961acdeaSSudarsana Reddy Kalluru default: 1013961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1014961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1015961acdeaSSudarsana Reddy Kalluru } 1016961acdeaSSudarsana Reddy Kalluru } 1017961acdeaSSudarsana Reddy Kalluru 1018961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1019961acdeaSSudarsana Reddy Kalluru { 1020961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1021961acdeaSSudarsana Reddy Kalluru } 1022961acdeaSSudarsana Reddy Kalluru 1023961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1024961acdeaSSudarsana Reddy Kalluru { 1025961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1026961acdeaSSudarsana Reddy Kalluru 1027961acdeaSSudarsana Reddy Kalluru return sizeof(edev->rss_params.rss_key); 1028961acdeaSSudarsana Reddy Kalluru } 1029961acdeaSSudarsana Reddy Kalluru 1030961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1031961acdeaSSudarsana Reddy Kalluru { 1032961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1033961acdeaSSudarsana Reddy Kalluru int i; 1034961acdeaSSudarsana Reddy Kalluru 1035961acdeaSSudarsana Reddy Kalluru if (hfunc) 1036961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1037961acdeaSSudarsana Reddy Kalluru 1038961acdeaSSudarsana Reddy Kalluru if (!indir) 1039961acdeaSSudarsana Reddy Kalluru return 0; 1040961acdeaSSudarsana Reddy Kalluru 1041961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1042961acdeaSSudarsana Reddy Kalluru indir[i] = edev->rss_params.rss_ind_table[i]; 1043961acdeaSSudarsana Reddy Kalluru 1044961acdeaSSudarsana Reddy Kalluru if (key) 1045961acdeaSSudarsana Reddy Kalluru memcpy(key, edev->rss_params.rss_key, 1046961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1047961acdeaSSudarsana Reddy Kalluru 1048961acdeaSSudarsana Reddy Kalluru return 0; 1049961acdeaSSudarsana Reddy Kalluru } 1050961acdeaSSudarsana Reddy Kalluru 1051961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1052961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1053961acdeaSSudarsana Reddy Kalluru { 1054961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 1055961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1056961acdeaSSudarsana Reddy Kalluru int i; 1057961acdeaSSudarsana Reddy Kalluru 1058ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1059ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1060ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1061ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1062ba300ce3SSudarsana Reddy Kalluru } 1063ba300ce3SSudarsana Reddy Kalluru 1064961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1065961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1066961acdeaSSudarsana Reddy Kalluru 1067961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1068961acdeaSSudarsana Reddy Kalluru return 0; 1069961acdeaSSudarsana Reddy Kalluru 1070961acdeaSSudarsana Reddy Kalluru if (indir) { 1071961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1072961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_ind_table[i] = indir[i]; 1073961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1074961acdeaSSudarsana Reddy Kalluru } 1075961acdeaSSudarsana Reddy Kalluru 1076961acdeaSSudarsana Reddy Kalluru if (key) { 1077961acdeaSSudarsana Reddy Kalluru memcpy(&edev->rss_params.rss_key, key, 1078961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1079961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1080961acdeaSSudarsana Reddy Kalluru } 1081961acdeaSSudarsana Reddy Kalluru 1082961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1083961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1084961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1085961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1086961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1087961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1088961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1089961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1090961acdeaSSudarsana Reddy Kalluru } 1091961acdeaSSudarsana Reddy Kalluru 1092961acdeaSSudarsana Reddy Kalluru return 0; 1093961acdeaSSudarsana Reddy Kalluru } 1094961acdeaSSudarsana Reddy Kalluru 109516f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 109616f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 109716f46bf0SSudarsana Reddy Kalluru { 109816f46bf0SSudarsana Reddy Kalluru int i; 109916f46bf0SSudarsana Reddy Kalluru 110016f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 110116f46bf0SSudarsana Reddy Kalluru return; 110216f46bf0SSudarsana Reddy Kalluru 11039a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 110416f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 110516f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 110616f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 110716f46bf0SSudarsana Reddy Kalluru } 110816f46bf0SSudarsana Reddy Kalluru } 110916f46bf0SSudarsana Reddy Kalluru 111016f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 111116f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 111216f46bf0SSudarsana Reddy Kalluru { 111316f46bf0SSudarsana Reddy Kalluru int i; 111416f46bf0SSudarsana Reddy Kalluru 11159a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 111616f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 111716f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 111816f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 111916f46bf0SSudarsana Reddy Kalluru } 112016f46bf0SSudarsana Reddy Kalluru } 112116f46bf0SSudarsana Reddy Kalluru 112216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 112316f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 112416f46bf0SSudarsana Reddy Kalluru { 11259a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 112616f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 112716f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 112816f46bf0SSudarsana Reddy Kalluru int i, idx, val; 112916f46bf0SSudarsana Reddy Kalluru 11309a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 11319a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 11329a4d7e86SSudarsana Reddy Kalluru txq = edev->fp_array[i].txqs; 11339a4d7e86SSudarsana Reddy Kalluru break; 11349a4d7e86SSudarsana Reddy Kalluru } 11359a4d7e86SSudarsana Reddy Kalluru } 11369a4d7e86SSudarsana Reddy Kalluru 11379a4d7e86SSudarsana Reddy Kalluru if (!txq) { 11389a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 11399a4d7e86SSudarsana Reddy Kalluru return -1; 11409a4d7e86SSudarsana Reddy Kalluru } 11419a4d7e86SSudarsana Reddy Kalluru 114216f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 114316f46bf0SSudarsana Reddy Kalluru idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; 114416f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = skb; 114516f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 114616f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 114716f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 114816f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1149351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 1150351a4dedSYuval Mintz first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); 115116f46bf0SSudarsana Reddy Kalluru 115216f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 115316f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 115416f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 115516f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 115616f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 115716f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 115816f46bf0SSudarsana Reddy Kalluru } 115916f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 116016f46bf0SSudarsana Reddy Kalluru 116116f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 116216f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 116316f46bf0SSudarsana Reddy Kalluru txq->sw_tx_prod++; 116416f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 116516f46bf0SSudarsana Reddy Kalluru val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl)); 116616f46bf0SSudarsana Reddy Kalluru txq->tx_db.data.bd_prod = val; 116716f46bf0SSudarsana Reddy Kalluru 116816f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 116916f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 117016f46bf0SSudarsana Reddy Kalluru */ 117116f46bf0SSudarsana Reddy Kalluru wmb(); 117216f46bf0SSudarsana Reddy Kalluru barrier(); 117316f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 117416f46bf0SSudarsana Reddy Kalluru 117516f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 117616f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 117716f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 117816f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 117916f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 118016f46bf0SSudarsana Reddy Kalluru */ 118116f46bf0SSudarsana Reddy Kalluru mmiowb(); 118216f46bf0SSudarsana Reddy Kalluru 118316f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 118416f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 118516f46bf0SSudarsana Reddy Kalluru break; 118616f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 118716f46bf0SSudarsana Reddy Kalluru } 118816f46bf0SSudarsana Reddy Kalluru 118916f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 119016f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 119116f46bf0SSudarsana Reddy Kalluru return -1; 119216f46bf0SSudarsana Reddy Kalluru } 119316f46bf0SSudarsana Reddy Kalluru 119416f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 119516f46bf0SSudarsana Reddy Kalluru dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 119616f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 119716f46bf0SSudarsana Reddy Kalluru txq->sw_tx_cons++; 119816f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = NULL; 119916f46bf0SSudarsana Reddy Kalluru 120016f46bf0SSudarsana Reddy Kalluru return 0; 120116f46bf0SSudarsana Reddy Kalluru } 120216f46bf0SSudarsana Reddy Kalluru 120316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 120416f46bf0SSudarsana Reddy Kalluru { 120516f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 120616f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 12079a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 120816f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 120916f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 121016f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 121116f46bf0SSudarsana Reddy Kalluru int i; 121216f46bf0SSudarsana Reddy Kalluru 12139a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 12149a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 12159a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 12169a4d7e86SSudarsana Reddy Kalluru break; 12179a4d7e86SSudarsana Reddy Kalluru } 12189a4d7e86SSudarsana Reddy Kalluru } 12199a4d7e86SSudarsana Reddy Kalluru 12209a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 12219a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 12229a4d7e86SSudarsana Reddy Kalluru return -1; 12239a4d7e86SSudarsana Reddy Kalluru } 12249a4d7e86SSudarsana Reddy Kalluru 122516f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 122616f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 122716f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 122816f46bf0SSudarsana Reddy Kalluru */ 122916f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 123016f46bf0SSudarsana Reddy Kalluru if (qede_has_rx_work(rxq)) 123116f46bf0SSudarsana Reddy Kalluru break; 123216f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 123316f46bf0SSudarsana Reddy Kalluru } 123416f46bf0SSudarsana Reddy Kalluru 123516f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 123616f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 123716f46bf0SSudarsana Reddy Kalluru return -1; 123816f46bf0SSudarsana Reddy Kalluru } 123916f46bf0SSudarsana Reddy Kalluru 124016f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 124116f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 124216f46bf0SSudarsana Reddy Kalluru 124316f46bf0SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative reads of CQE 124416f46bf0SSudarsana Reddy Kalluru * / BD before reading hw_comp_cons. If the CQE is read before it is 124516f46bf0SSudarsana Reddy Kalluru * written by FW, then FW writes CQE and SB, and then the CPU reads the 124616f46bf0SSudarsana Reddy Kalluru * hw_comp_cons, it will use an old CQE. 124716f46bf0SSudarsana Reddy Kalluru */ 124816f46bf0SSudarsana Reddy Kalluru rmb(); 124916f46bf0SSudarsana Reddy Kalluru 125016f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 125116f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 125216f46bf0SSudarsana Reddy Kalluru 125316f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 125416f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 125516f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 125616f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 125716f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 125816f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 125916f46bf0SSudarsana Reddy Kalluru fp_cqe->placement_offset + sw_rx_data->page_offset); 126016f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 126116f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 126216f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Loopback test failed\n"); 126316f46bf0SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 126416f46bf0SSudarsana Reddy Kalluru return -1; 126516f46bf0SSudarsana Reddy Kalluru } 126616f46bf0SSudarsana Reddy Kalluru 126716f46bf0SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 126816f46bf0SSudarsana Reddy Kalluru 126916f46bf0SSudarsana Reddy Kalluru return 0; 127016f46bf0SSudarsana Reddy Kalluru } 127116f46bf0SSudarsana Reddy Kalluru 127216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 127316f46bf0SSudarsana Reddy Kalluru { 127416f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 127516f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 127616f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 127716f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 127816f46bf0SSudarsana Reddy Kalluru u8 *packet; 127916f46bf0SSudarsana Reddy Kalluru 128016f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 128116f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 128216f46bf0SSudarsana Reddy Kalluru return -EINVAL; 128316f46bf0SSudarsana Reddy Kalluru } 128416f46bf0SSudarsana Reddy Kalluru 128516f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 128616f46bf0SSudarsana Reddy Kalluru 128716f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 128816f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 128916f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 129016f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 129116f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 129216f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 129316f46bf0SSudarsana Reddy Kalluru 129416f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 129516f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 129616f46bf0SSudarsana Reddy Kalluru 129716f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 129816f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 129916f46bf0SSudarsana Reddy Kalluru 130016f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 130116f46bf0SSudarsana Reddy Kalluru if (!skb) { 130216f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 130316f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 130416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 130516f46bf0SSudarsana Reddy Kalluru } 130616f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 130716f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 130816f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 130916f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 131016f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 131116f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 131216f46bf0SSudarsana Reddy Kalluru 131316f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 131416f46bf0SSudarsana Reddy Kalluru if (rc) 131516f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 131616f46bf0SSudarsana Reddy Kalluru 131716f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 131816f46bf0SSudarsana Reddy Kalluru if (rc) 131916f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 132016f46bf0SSudarsana Reddy Kalluru 132116f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 132216f46bf0SSudarsana Reddy Kalluru 132316f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 132416f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 132516f46bf0SSudarsana Reddy Kalluru 132616f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 132716f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 132816f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 132916f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 133016f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 133116f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 133216f46bf0SSudarsana Reddy Kalluru 133316f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 133416f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 133516f46bf0SSudarsana Reddy Kalluru 133616f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 133716f46bf0SSudarsana Reddy Kalluru 133816f46bf0SSudarsana Reddy Kalluru return rc; 133916f46bf0SSudarsana Reddy Kalluru } 134016f46bf0SSudarsana Reddy Kalluru 13413044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 13423044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 13433044a02eSSudarsana Reddy Kalluru { 13443044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 13453044a02eSSudarsana Reddy Kalluru 13463044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 13473044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 13483044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 13493044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 13503044a02eSSudarsana Reddy Kalluru 13513044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 13523044a02eSSudarsana Reddy Kalluru 135316f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 135416f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 135516f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 135616f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 135716f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 135816f46bf0SSudarsana Reddy Kalluru } 135916f46bf0SSudarsana Reddy Kalluru } 136016f46bf0SSudarsana Reddy Kalluru 13613044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 13623044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 13633044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13643044a02eSSudarsana Reddy Kalluru } 13653044a02eSSudarsana Reddy Kalluru 13663044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 13673044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 13683044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13693044a02eSSudarsana Reddy Kalluru } 13703044a02eSSudarsana Reddy Kalluru 13713044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 13723044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 13733044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13743044a02eSSudarsana Reddy Kalluru } 13753044a02eSSudarsana Reddy Kalluru 13763044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 13773044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 13783044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13793044a02eSSudarsana Reddy Kalluru } 13803044a02eSSudarsana Reddy Kalluru } 13813044a02eSSudarsana Reddy Kalluru 13823d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 13833d789994SManish Chopra const struct ethtool_tunable *tuna, 13843d789994SManish Chopra const void *data) 13853d789994SManish Chopra { 13863d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 13873d789994SManish Chopra u32 val; 13883d789994SManish Chopra 13893d789994SManish Chopra switch (tuna->id) { 13903d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 13913d789994SManish Chopra val = *(u32 *)data; 13923d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 13933d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 13943d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 13953d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 13963d789994SManish Chopra return -EINVAL; 13973d789994SManish Chopra } 13983d789994SManish Chopra 13993d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 14003d789994SManish Chopra break; 14013d789994SManish Chopra default: 14023d789994SManish Chopra return -EOPNOTSUPP; 14033d789994SManish Chopra } 14043d789994SManish Chopra 14053d789994SManish Chopra return 0; 14063d789994SManish Chopra } 14073d789994SManish Chopra 14083d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 14093d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 14103d789994SManish Chopra { 14113d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14123d789994SManish Chopra 14133d789994SManish Chopra switch (tuna->id) { 14143d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14153d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 14163d789994SManish Chopra break; 14173d789994SManish Chopra default: 14183d789994SManish Chopra return -EOPNOTSUPP; 14193d789994SManish Chopra } 14203d789994SManish Chopra 14213d789994SManish Chopra return 0; 14223d789994SManish Chopra } 14233d789994SManish Chopra 1424133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1425054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1426054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1427133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1428e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1429e0971c83STomer Tayar .get_regs = qede_get_regs, 1430133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1431133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 143232a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1433133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1434d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1435d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 143601ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 143701ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 14380f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 14390f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1440133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 14413d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1442133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1443f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1444133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1445961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1446961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1447961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1448961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1449961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1450961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 14518edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 14528edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 14533044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 14543d789994SManish Chopra .get_tunable = qede_get_tunable, 14553d789994SManish Chopra .set_tunable = qede_set_tunable, 1456133fac0eSSudarsana Kalluru }; 1457133fac0eSSudarsana Kalluru 1458fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1459054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1460fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1461fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1462fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1463fefb0202SYuval Mintz .get_link = qede_get_link, 1464fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1465fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1466fefb0202SYuval Mintz .get_strings = qede_get_strings, 1467fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1468fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1469fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1470fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1471fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1472fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1473fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1474fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1475fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1476fefb0202SYuval Mintz .get_channels = qede_get_channels, 1477fefb0202SYuval Mintz .set_channels = qede_set_channels, 14783d789994SManish Chopra .get_tunable = qede_get_tunable, 14793d789994SManish Chopra .set_tunable = qede_set_tunable, 1480fefb0202SYuval Mintz }; 1481fefb0202SYuval Mintz 1482133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1483133fac0eSSudarsana Kalluru { 1484fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1485fefb0202SYuval Mintz 1486fefb0202SYuval Mintz if (IS_VF(edev)) 1487fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1488fefb0202SYuval Mintz else 1489133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1490133fac0eSSudarsana Kalluru } 1491