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; 825ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 826ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 827ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 828ed0dd915SSudarsana Reddy Kalluru memset(&edev->rss_params.rss_ind_table, 0, 829ed0dd915SSudarsana Reddy Kalluru sizeof(edev->rss_params.rss_ind_table)); 830ed0dd915SSudarsana Reddy Kalluru } 831ed0dd915SSudarsana Reddy Kalluru 8328edf049dSSudarsana Kalluru if (netif_running(dev)) 8338edf049dSSudarsana Kalluru qede_reload(edev, NULL, NULL); 8348edf049dSSudarsana Kalluru 8358edf049dSSudarsana Kalluru return 0; 8368edf049dSSudarsana Kalluru } 8378edf049dSSudarsana Kalluru 8383d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 8393d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 8403d971cbdSSudarsana Kalluru { 8413d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8423d971cbdSSudarsana Kalluru u8 led_state = 0; 8433d971cbdSSudarsana Kalluru 8443d971cbdSSudarsana Kalluru switch (state) { 8453d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 8463d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 8473d971cbdSSudarsana Kalluru 8483d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 8493d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 8503d971cbdSSudarsana Kalluru break; 8513d971cbdSSudarsana Kalluru 8523d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 8533d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 8543d971cbdSSudarsana Kalluru break; 8553d971cbdSSudarsana Kalluru 8563d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 8573d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 8583d971cbdSSudarsana Kalluru break; 8593d971cbdSSudarsana Kalluru } 8603d971cbdSSudarsana Kalluru 8613d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 8623d971cbdSSudarsana Kalluru 8633d971cbdSSudarsana Kalluru return 0; 8643d971cbdSSudarsana Kalluru } 8653d971cbdSSudarsana Kalluru 866961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 867961acdeaSSudarsana Reddy Kalluru { 868961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 869961acdeaSSudarsana Reddy Kalluru 870961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 871961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 872961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 873961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 874961acdeaSSudarsana Reddy Kalluru break; 875961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 876961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP) 877961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 878961acdeaSSudarsana Reddy Kalluru break; 879961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 880961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP) 881961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 882961acdeaSSudarsana Reddy Kalluru break; 883961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 884961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 885961acdeaSSudarsana Reddy Kalluru break; 886961acdeaSSudarsana Reddy Kalluru default: 887961acdeaSSudarsana Reddy Kalluru info->data = 0; 888961acdeaSSudarsana Reddy Kalluru break; 889961acdeaSSudarsana Reddy Kalluru } 890961acdeaSSudarsana Reddy Kalluru 891961acdeaSSudarsana Reddy Kalluru return 0; 892961acdeaSSudarsana Reddy Kalluru } 893961acdeaSSudarsana Reddy Kalluru 894961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 895961acdeaSSudarsana Reddy Kalluru u32 *rules __always_unused) 896961acdeaSSudarsana Reddy Kalluru { 897961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 898961acdeaSSudarsana Reddy Kalluru 899961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 900961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 9019a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 902961acdeaSSudarsana Reddy Kalluru return 0; 903961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 904961acdeaSSudarsana Reddy Kalluru return qede_get_rss_flags(edev, info); 905961acdeaSSudarsana Reddy Kalluru default: 906961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 907961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 908961acdeaSSudarsana Reddy Kalluru } 909961acdeaSSudarsana Reddy Kalluru } 910961acdeaSSudarsana Reddy Kalluru 911961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 912961acdeaSSudarsana Reddy Kalluru { 913961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 914961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 915961acdeaSSudarsana Reddy Kalluru 916961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 917961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 918961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 919961acdeaSSudarsana Reddy Kalluru 920961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 921961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 922961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 923961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 924961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 925961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 926961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 927961acdeaSSudarsana Reddy Kalluru return -EINVAL; 928961acdeaSSudarsana Reddy Kalluru } 929961acdeaSSudarsana Reddy Kalluru return 0; 930961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 931961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 932961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 933961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 934961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 935961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 936961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 937961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 938961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 939961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 940961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 941961acdeaSSudarsana Reddy Kalluru } else { 942961acdeaSSudarsana Reddy Kalluru return -EINVAL; 943961acdeaSSudarsana Reddy Kalluru } 944961acdeaSSudarsana Reddy Kalluru break; 945961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 946961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 947961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 948961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 949961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 950961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 951961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 952961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 953961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 954961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 955961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 956961acdeaSSudarsana Reddy Kalluru } else { 957961acdeaSSudarsana Reddy Kalluru return -EINVAL; 958961acdeaSSudarsana Reddy Kalluru } 959961acdeaSSudarsana Reddy Kalluru break; 960961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 961961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 962961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 963961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 964961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 965961acdeaSSudarsana Reddy Kalluru return -EINVAL; 966961acdeaSSudarsana Reddy Kalluru } 967961acdeaSSudarsana Reddy Kalluru return 0; 968961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 969961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 970961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 971961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 972961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 973961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 974961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 975961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 976961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 977961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 978961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 979961acdeaSSudarsana Reddy Kalluru if (info->data) { 980961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 981961acdeaSSudarsana Reddy Kalluru return -EINVAL; 982961acdeaSSudarsana Reddy Kalluru } 983961acdeaSSudarsana Reddy Kalluru return 0; 984961acdeaSSudarsana Reddy Kalluru default: 985961acdeaSSudarsana Reddy Kalluru return -EINVAL; 986961acdeaSSudarsana Reddy Kalluru } 987961acdeaSSudarsana Reddy Kalluru 988961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 989961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps & 990961acdeaSSudarsana Reddy Kalluru ~clr_caps) | set_caps)) 991961acdeaSSudarsana Reddy Kalluru return 0; 992961acdeaSSudarsana Reddy Kalluru 993961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 994961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) | 995961acdeaSSudarsana Reddy Kalluru set_caps; 996961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 997961acdeaSSudarsana Reddy Kalluru 998961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 999961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1000961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1001961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1002961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1003961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1004961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1005961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1006961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1007961acdeaSSudarsana Reddy Kalluru } 1008961acdeaSSudarsana Reddy Kalluru 1009961acdeaSSudarsana Reddy Kalluru return 0; 1010961acdeaSSudarsana Reddy Kalluru } 1011961acdeaSSudarsana Reddy Kalluru 1012961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1013961acdeaSSudarsana Reddy Kalluru { 1014961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1015961acdeaSSudarsana Reddy Kalluru 1016961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1017961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 1018961acdeaSSudarsana Reddy Kalluru return qede_set_rss_flags(edev, info); 1019961acdeaSSudarsana Reddy Kalluru default: 1020961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1021961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1022961acdeaSSudarsana Reddy Kalluru } 1023961acdeaSSudarsana Reddy Kalluru } 1024961acdeaSSudarsana Reddy Kalluru 1025961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1026961acdeaSSudarsana Reddy Kalluru { 1027961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1028961acdeaSSudarsana Reddy Kalluru } 1029961acdeaSSudarsana Reddy Kalluru 1030961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1031961acdeaSSudarsana Reddy Kalluru { 1032961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1033961acdeaSSudarsana Reddy Kalluru 1034961acdeaSSudarsana Reddy Kalluru return sizeof(edev->rss_params.rss_key); 1035961acdeaSSudarsana Reddy Kalluru } 1036961acdeaSSudarsana Reddy Kalluru 1037961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1038961acdeaSSudarsana Reddy Kalluru { 1039961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1040961acdeaSSudarsana Reddy Kalluru int i; 1041961acdeaSSudarsana Reddy Kalluru 1042961acdeaSSudarsana Reddy Kalluru if (hfunc) 1043961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1044961acdeaSSudarsana Reddy Kalluru 1045961acdeaSSudarsana Reddy Kalluru if (!indir) 1046961acdeaSSudarsana Reddy Kalluru return 0; 1047961acdeaSSudarsana Reddy Kalluru 1048961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1049961acdeaSSudarsana Reddy Kalluru indir[i] = edev->rss_params.rss_ind_table[i]; 1050961acdeaSSudarsana Reddy Kalluru 1051961acdeaSSudarsana Reddy Kalluru if (key) 1052961acdeaSSudarsana Reddy Kalluru memcpy(key, edev->rss_params.rss_key, 1053961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1054961acdeaSSudarsana Reddy Kalluru 1055961acdeaSSudarsana Reddy Kalluru return 0; 1056961acdeaSSudarsana Reddy Kalluru } 1057961acdeaSSudarsana Reddy Kalluru 1058961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1059961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1060961acdeaSSudarsana Reddy Kalluru { 1061961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 1062961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1063961acdeaSSudarsana Reddy Kalluru int i; 1064961acdeaSSudarsana Reddy Kalluru 1065ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1066ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1067ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1068ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1069ba300ce3SSudarsana Reddy Kalluru } 1070ba300ce3SSudarsana Reddy Kalluru 1071961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1072961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1073961acdeaSSudarsana Reddy Kalluru 1074961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1075961acdeaSSudarsana Reddy Kalluru return 0; 1076961acdeaSSudarsana Reddy Kalluru 1077961acdeaSSudarsana Reddy Kalluru if (indir) { 1078961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1079961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_ind_table[i] = indir[i]; 1080961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1081961acdeaSSudarsana Reddy Kalluru } 1082961acdeaSSudarsana Reddy Kalluru 1083961acdeaSSudarsana Reddy Kalluru if (key) { 1084961acdeaSSudarsana Reddy Kalluru memcpy(&edev->rss_params.rss_key, key, 1085961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1086961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1087961acdeaSSudarsana Reddy Kalluru } 1088961acdeaSSudarsana Reddy Kalluru 1089961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1090961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1091961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1092961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1093961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1094961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1095961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1096961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1097961acdeaSSudarsana Reddy Kalluru } 1098961acdeaSSudarsana Reddy Kalluru 1099961acdeaSSudarsana Reddy Kalluru return 0; 1100961acdeaSSudarsana Reddy Kalluru } 1101961acdeaSSudarsana Reddy Kalluru 110216f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 110316f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 110416f46bf0SSudarsana Reddy Kalluru { 110516f46bf0SSudarsana Reddy Kalluru int i; 110616f46bf0SSudarsana Reddy Kalluru 110716f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 110816f46bf0SSudarsana Reddy Kalluru return; 110916f46bf0SSudarsana Reddy Kalluru 11109a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 111116f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 111216f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 111316f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 111416f46bf0SSudarsana Reddy Kalluru } 111516f46bf0SSudarsana Reddy Kalluru } 111616f46bf0SSudarsana Reddy Kalluru 111716f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 111816f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 111916f46bf0SSudarsana Reddy Kalluru { 112016f46bf0SSudarsana Reddy Kalluru int i; 112116f46bf0SSudarsana Reddy Kalluru 11229a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 112316f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 112416f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 112516f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 112616f46bf0SSudarsana Reddy Kalluru } 112716f46bf0SSudarsana Reddy Kalluru } 112816f46bf0SSudarsana Reddy Kalluru 112916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 113016f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 113116f46bf0SSudarsana Reddy Kalluru { 11329a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 113316f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 113416f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 113516f46bf0SSudarsana Reddy Kalluru int i, idx, val; 113616f46bf0SSudarsana Reddy Kalluru 11379a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 11389a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 11399a4d7e86SSudarsana Reddy Kalluru txq = edev->fp_array[i].txqs; 11409a4d7e86SSudarsana Reddy Kalluru break; 11419a4d7e86SSudarsana Reddy Kalluru } 11429a4d7e86SSudarsana Reddy Kalluru } 11439a4d7e86SSudarsana Reddy Kalluru 11449a4d7e86SSudarsana Reddy Kalluru if (!txq) { 11459a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 11469a4d7e86SSudarsana Reddy Kalluru return -1; 11479a4d7e86SSudarsana Reddy Kalluru } 11489a4d7e86SSudarsana Reddy Kalluru 114916f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 115016f46bf0SSudarsana Reddy Kalluru idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; 115116f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = skb; 115216f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 115316f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 115416f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 115516f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1156351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 1157351a4dedSYuval Mintz first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); 115816f46bf0SSudarsana Reddy Kalluru 115916f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 116016f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 116116f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 116216f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 116316f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 116416f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 116516f46bf0SSudarsana Reddy Kalluru } 116616f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 116716f46bf0SSudarsana Reddy Kalluru 116816f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 116916f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 117016f46bf0SSudarsana Reddy Kalluru txq->sw_tx_prod++; 117116f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 117216f46bf0SSudarsana Reddy Kalluru val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl)); 117316f46bf0SSudarsana Reddy Kalluru txq->tx_db.data.bd_prod = val; 117416f46bf0SSudarsana Reddy Kalluru 117516f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 117616f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 117716f46bf0SSudarsana Reddy Kalluru */ 117816f46bf0SSudarsana Reddy Kalluru wmb(); 117916f46bf0SSudarsana Reddy Kalluru barrier(); 118016f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 118116f46bf0SSudarsana Reddy Kalluru 118216f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 118316f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 118416f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 118516f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 118616f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 118716f46bf0SSudarsana Reddy Kalluru */ 118816f46bf0SSudarsana Reddy Kalluru mmiowb(); 118916f46bf0SSudarsana Reddy Kalluru 119016f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 119116f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 119216f46bf0SSudarsana Reddy Kalluru break; 119316f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 119416f46bf0SSudarsana Reddy Kalluru } 119516f46bf0SSudarsana Reddy Kalluru 119616f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 119716f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 119816f46bf0SSudarsana Reddy Kalluru return -1; 119916f46bf0SSudarsana Reddy Kalluru } 120016f46bf0SSudarsana Reddy Kalluru 120116f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1202fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 120316f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 120416f46bf0SSudarsana Reddy Kalluru txq->sw_tx_cons++; 120516f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = NULL; 120616f46bf0SSudarsana Reddy Kalluru 120716f46bf0SSudarsana Reddy Kalluru return 0; 120816f46bf0SSudarsana Reddy Kalluru } 120916f46bf0SSudarsana Reddy Kalluru 121016f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 121116f46bf0SSudarsana Reddy Kalluru { 121216f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 121316f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 12149a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 121516f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 121616f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1217837d4eb6SSudarsana Reddy Kalluru int i, rc = 0; 121816f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 121916f46bf0SSudarsana Reddy Kalluru 12209a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 12219a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 12229a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 12239a4d7e86SSudarsana Reddy Kalluru break; 12249a4d7e86SSudarsana Reddy Kalluru } 12259a4d7e86SSudarsana Reddy Kalluru } 12269a4d7e86SSudarsana Reddy Kalluru 12279a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 12289a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 12299a4d7e86SSudarsana Reddy Kalluru return -1; 12309a4d7e86SSudarsana Reddy Kalluru } 12319a4d7e86SSudarsana Reddy Kalluru 123216f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 123316f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 123416f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 123516f46bf0SSudarsana Reddy Kalluru */ 123616f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 123716f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1238837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1239837d4eb6SSudarsana Reddy Kalluru continue; 124016f46bf0SSudarsana Reddy Kalluru } 124116f46bf0SSudarsana Reddy Kalluru 124216f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 124316f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 124416f46bf0SSudarsana Reddy Kalluru 1245837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1246837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1247837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1248837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1249837d4eb6SSudarsana Reddy Kalluru * CQE. 125016f46bf0SSudarsana Reddy Kalluru */ 125116f46bf0SSudarsana Reddy Kalluru rmb(); 125216f46bf0SSudarsana Reddy Kalluru 125316f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 125416f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 125516f46bf0SSudarsana Reddy Kalluru 125616f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 125716f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 125816f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 125916f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 126016f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 126116f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1262837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 1263837d4eb6SSudarsana Reddy Kalluru sw_rx_data->page_offset); 1264837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1265837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1266837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 126716f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 126816f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1269837d4eb6SSudarsana Reddy Kalluru rc = -1; 1270837d4eb6SSudarsana Reddy Kalluru break; 127116f46bf0SSudarsana Reddy Kalluru } 127216f46bf0SSudarsana Reddy Kalluru 127316f46bf0SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 1274837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1275837d4eb6SSudarsana Reddy Kalluru break; 1276837d4eb6SSudarsana Reddy Kalluru } 127716f46bf0SSudarsana Reddy Kalluru 1278837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 1279837d4eb6SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 1280837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1281837d4eb6SSudarsana Reddy Kalluru } 1282837d4eb6SSudarsana Reddy Kalluru 1283837d4eb6SSudarsana Reddy Kalluru if (i == QEDE_SELFTEST_POLL_COUNT) { 1284837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1285837d4eb6SSudarsana Reddy Kalluru return -1; 1286837d4eb6SSudarsana Reddy Kalluru } 1287837d4eb6SSudarsana Reddy Kalluru 1288837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1289837d4eb6SSudarsana Reddy Kalluru 1290837d4eb6SSudarsana Reddy Kalluru return rc; 129116f46bf0SSudarsana Reddy Kalluru } 129216f46bf0SSudarsana Reddy Kalluru 129316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 129416f46bf0SSudarsana Reddy Kalluru { 129516f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 129616f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 129716f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 129816f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 129916f46bf0SSudarsana Reddy Kalluru u8 *packet; 130016f46bf0SSudarsana Reddy Kalluru 130116f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 130216f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 130316f46bf0SSudarsana Reddy Kalluru return -EINVAL; 130416f46bf0SSudarsana Reddy Kalluru } 130516f46bf0SSudarsana Reddy Kalluru 130616f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 130716f46bf0SSudarsana Reddy Kalluru 130816f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 130916f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 131016f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 131116f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 131216f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 131316f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 131416f46bf0SSudarsana Reddy Kalluru 131516f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 131616f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 131716f46bf0SSudarsana Reddy Kalluru 131816f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 131916f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 132016f46bf0SSudarsana Reddy Kalluru 132116f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 132216f46bf0SSudarsana Reddy Kalluru if (!skb) { 132316f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 132416f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 132516f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 132616f46bf0SSudarsana Reddy Kalluru } 132716f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 132816f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 132916f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 133016f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 133116f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 133216f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 133316f46bf0SSudarsana Reddy Kalluru 133416f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 133516f46bf0SSudarsana Reddy Kalluru if (rc) 133616f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 133716f46bf0SSudarsana Reddy Kalluru 133816f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 133916f46bf0SSudarsana Reddy Kalluru if (rc) 134016f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 134116f46bf0SSudarsana Reddy Kalluru 134216f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 134316f46bf0SSudarsana Reddy Kalluru 134416f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 134516f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 134616f46bf0SSudarsana Reddy Kalluru 134716f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 134816f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 134916f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 135016f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 135116f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 135216f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 135316f46bf0SSudarsana Reddy Kalluru 135416f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 135516f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 135616f46bf0SSudarsana Reddy Kalluru 135716f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 135816f46bf0SSudarsana Reddy Kalluru 135916f46bf0SSudarsana Reddy Kalluru return rc; 136016f46bf0SSudarsana Reddy Kalluru } 136116f46bf0SSudarsana Reddy Kalluru 13623044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 13633044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 13643044a02eSSudarsana Reddy Kalluru { 13653044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 13663044a02eSSudarsana Reddy Kalluru 13673044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 13683044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 13693044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 13703044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 13713044a02eSSudarsana Reddy Kalluru 13723044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 13733044a02eSSudarsana Reddy Kalluru 137416f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 137516f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 137616f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 137716f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 137816f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 137916f46bf0SSudarsana Reddy Kalluru } 138016f46bf0SSudarsana Reddy Kalluru } 138116f46bf0SSudarsana Reddy Kalluru 13823044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 13833044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 13843044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13853044a02eSSudarsana Reddy Kalluru } 13863044a02eSSudarsana Reddy Kalluru 13873044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 13883044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 13893044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13903044a02eSSudarsana Reddy Kalluru } 13913044a02eSSudarsana Reddy Kalluru 13923044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 13933044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 13943044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 13953044a02eSSudarsana Reddy Kalluru } 13963044a02eSSudarsana Reddy Kalluru 13973044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 13983044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 13993044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14003044a02eSSudarsana Reddy Kalluru } 14013044a02eSSudarsana Reddy Kalluru } 14023044a02eSSudarsana Reddy Kalluru 14033d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 14043d789994SManish Chopra const struct ethtool_tunable *tuna, 14053d789994SManish Chopra const void *data) 14063d789994SManish Chopra { 14073d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14083d789994SManish Chopra u32 val; 14093d789994SManish Chopra 14103d789994SManish Chopra switch (tuna->id) { 14113d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14123d789994SManish Chopra val = *(u32 *)data; 14133d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 14143d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 14153d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 14163d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 14173d789994SManish Chopra return -EINVAL; 14183d789994SManish Chopra } 14193d789994SManish Chopra 14203d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 14213d789994SManish Chopra break; 14223d789994SManish Chopra default: 14233d789994SManish Chopra return -EOPNOTSUPP; 14243d789994SManish Chopra } 14253d789994SManish Chopra 14263d789994SManish Chopra return 0; 14273d789994SManish Chopra } 14283d789994SManish Chopra 14293d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 14303d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 14313d789994SManish Chopra { 14323d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14333d789994SManish Chopra 14343d789994SManish Chopra switch (tuna->id) { 14353d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14363d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 14373d789994SManish Chopra break; 14383d789994SManish Chopra default: 14393d789994SManish Chopra return -EOPNOTSUPP; 14403d789994SManish Chopra } 14413d789994SManish Chopra 14423d789994SManish Chopra return 0; 14433d789994SManish Chopra } 14443d789994SManish Chopra 1445133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1446054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1447054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1448133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1449e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1450e0971c83STomer Tayar .get_regs = qede_get_regs, 1451133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1452133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 145332a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1454133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1455d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1456d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 145701ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 145801ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 14590f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 14600f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1461133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 14623d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1463133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1464f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1465133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1466961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1467961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1468961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1469961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1470961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1471961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 14728edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 14738edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 14743044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 14753d789994SManish Chopra .get_tunable = qede_get_tunable, 14763d789994SManish Chopra .set_tunable = qede_set_tunable, 1477133fac0eSSudarsana Kalluru }; 1478133fac0eSSudarsana Kalluru 1479fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1480054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1481fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1482fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1483fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1484fefb0202SYuval Mintz .get_link = qede_get_link, 1485fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1486fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1487fefb0202SYuval Mintz .get_strings = qede_get_strings, 1488fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1489fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1490fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1491fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1492fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1493fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1494fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1495fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1496fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1497fefb0202SYuval Mintz .get_channels = qede_get_channels, 1498fefb0202SYuval Mintz .set_channels = qede_set_channels, 14993d789994SManish Chopra .get_tunable = qede_get_tunable, 15003d789994SManish Chopra .set_tunable = qede_set_tunable, 1501fefb0202SYuval Mintz }; 1502fefb0202SYuval Mintz 1503133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1504133fac0eSSudarsana Kalluru { 1505fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1506fefb0202SYuval Mintz 1507fefb0202SYuval Mintz if (IS_VF(edev)) 1508fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1509fefb0202SYuval Mintz else 1510133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1511133fac0eSSudarsana Kalluru } 1512