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 6280439a17SMintz, Yuval #define QEDE_TQSTATS_DATA(dev, sindex, tssid) \ 6380439a17SMintz, Yuval (*((u64 *)(((void *)((dev)->fp_array[tssid].txq)) + \ 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, 1607a4b21b7SMintz, Yuval QEDE_ETHTOOL_NVRAM_TEST, 1613044a02eSSudarsana Reddy Kalluru QEDE_ETHTOOL_TEST_MAX 1623044a02eSSudarsana Reddy Kalluru }; 1633044a02eSSudarsana Reddy Kalluru 1643044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = { 16516f46bf0SSudarsana Reddy Kalluru "Internal loopback (offline)", 1663044a02eSSudarsana Reddy Kalluru "Interrupt (online)\t", 1673044a02eSSudarsana Reddy Kalluru "Memory (online)\t\t", 1683044a02eSSudarsana Reddy Kalluru "Register (online)\t", 1693044a02eSSudarsana Reddy Kalluru "Clock (online)\t\t", 1707a4b21b7SMintz, Yuval "Nvram (online)\t\t", 1713044a02eSSudarsana Reddy Kalluru }; 1723044a02eSSudarsana Reddy Kalluru 173133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) 174133fac0eSSudarsana Kalluru { 175133fac0eSSudarsana Kalluru int i, j, k; 176133fac0eSSudarsana Kalluru 1779a4d7e86SSudarsana Reddy Kalluru for (i = 0, k = 0; i < QEDE_QUEUE_CNT(edev); i++) { 17868db9ec2SSudarsana Reddy Kalluru 179cbbf049aSMintz, Yuval if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 18068db9ec2SSudarsana Reddy Kalluru for (j = 0; j < QEDE_NUM_RQSTATS; j++) 18168db9ec2SSudarsana Reddy Kalluru sprintf(buf + (k + j) * ETH_GSTRING_LEN, 182cbbf049aSMintz, Yuval "%d: %s", i, 183cbbf049aSMintz, Yuval qede_rqstats_arr[j].string); 18468db9ec2SSudarsana Reddy Kalluru k += QEDE_NUM_RQSTATS; 185cbbf049aSMintz, Yuval } 186cbbf049aSMintz, Yuval 187cbbf049aSMintz, Yuval if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 18868db9ec2SSudarsana Reddy Kalluru for (j = 0; j < QEDE_NUM_TQSTATS; j++) 189cbbf049aSMintz, Yuval sprintf(buf + (k + j) * 190cbbf049aSMintz, Yuval ETH_GSTRING_LEN, 19180439a17SMintz, Yuval "%d: %s", i, 19268db9ec2SSudarsana Reddy Kalluru qede_tqstats_arr[j].string); 19368db9ec2SSudarsana Reddy Kalluru k += QEDE_NUM_TQSTATS; 19468db9ec2SSudarsana Reddy Kalluru } 19568db9ec2SSudarsana Reddy Kalluru } 19668db9ec2SSudarsana Reddy Kalluru 197133fac0eSSudarsana Kalluru for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) { 198fefb0202SYuval Mintz if (IS_VF(edev) && qede_stats_arr[i].pf_only) 199fefb0202SYuval Mintz continue; 20068db9ec2SSudarsana Reddy Kalluru strcpy(buf + (k + j) * ETH_GSTRING_LEN, 201133fac0eSSudarsana Kalluru qede_stats_arr[i].string); 202133fac0eSSudarsana Kalluru j++; 203133fac0eSSudarsana Kalluru } 204133fac0eSSudarsana Kalluru } 205133fac0eSSudarsana Kalluru 206133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 207133fac0eSSudarsana Kalluru { 208133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 209133fac0eSSudarsana Kalluru 210133fac0eSSudarsana Kalluru switch (stringset) { 211133fac0eSSudarsana Kalluru case ETH_SS_STATS: 212133fac0eSSudarsana Kalluru qede_get_strings_stats(edev, buf); 213133fac0eSSudarsana Kalluru break; 214f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 215f3e72109SYuval Mintz memcpy(buf, qede_private_arr, 216f3e72109SYuval Mintz ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN); 217f3e72109SYuval Mintz break; 2183044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2193044a02eSSudarsana Reddy Kalluru memcpy(buf, qede_tests_str_arr, 2203044a02eSSudarsana Reddy Kalluru ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX); 2213044a02eSSudarsana Reddy Kalluru break; 222133fac0eSSudarsana Kalluru default: 223133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 224133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 225133fac0eSSudarsana Kalluru } 226133fac0eSSudarsana Kalluru } 227133fac0eSSudarsana Kalluru 228133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev, 229133fac0eSSudarsana Kalluru struct ethtool_stats *stats, u64 *buf) 230133fac0eSSudarsana Kalluru { 231133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 232133fac0eSSudarsana Kalluru int sidx, cnt = 0; 233133fac0eSSudarsana Kalluru int qid; 234133fac0eSSudarsana Kalluru 235133fac0eSSudarsana Kalluru qede_fill_by_demand_stats(edev); 236133fac0eSSudarsana Kalluru 237133fac0eSSudarsana Kalluru mutex_lock(&edev->qede_lock); 238133fac0eSSudarsana Kalluru 2399a4d7e86SSudarsana Reddy Kalluru for (qid = 0; qid < QEDE_QUEUE_CNT(edev); qid++) { 24068db9ec2SSudarsana Reddy Kalluru 24180439a17SMintz, Yuval if (edev->fp_array[qid].type & QEDE_FASTPATH_RX) 24268db9ec2SSudarsana Reddy Kalluru for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++) 24368db9ec2SSudarsana Reddy Kalluru buf[cnt++] = QEDE_RQSTATS_DATA(edev, sidx, qid); 2449a4d7e86SSudarsana Reddy Kalluru 24580439a17SMintz, Yuval if (edev->fp_array[qid].type & QEDE_FASTPATH_TX) 24668db9ec2SSudarsana Reddy Kalluru for (sidx = 0; sidx < QEDE_NUM_TQSTATS; sidx++) 2479a4d7e86SSudarsana Reddy Kalluru buf[cnt++] = QEDE_TQSTATS_DATA(edev, 2489a4d7e86SSudarsana Reddy Kalluru sidx, 24980439a17SMintz, Yuval qid); 25068db9ec2SSudarsana Reddy Kalluru } 25168db9ec2SSudarsana Reddy Kalluru 252fefb0202SYuval Mintz for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++) { 253fefb0202SYuval Mintz if (IS_VF(edev) && qede_stats_arr[sidx].pf_only) 254fefb0202SYuval Mintz continue; 255133fac0eSSudarsana Kalluru buf[cnt++] = QEDE_STATS_DATA(edev, sidx); 256fefb0202SYuval Mintz } 257133fac0eSSudarsana Kalluru 258133fac0eSSudarsana Kalluru mutex_unlock(&edev->qede_lock); 259133fac0eSSudarsana Kalluru } 260133fac0eSSudarsana Kalluru 261133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset) 262133fac0eSSudarsana Kalluru { 263133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 264133fac0eSSudarsana Kalluru int num_stats = QEDE_NUM_STATS; 265133fac0eSSudarsana Kalluru 266133fac0eSSudarsana Kalluru switch (stringset) { 267133fac0eSSudarsana Kalluru case ETH_SS_STATS: 268fefb0202SYuval Mintz if (IS_VF(edev)) { 269fefb0202SYuval Mintz int i; 270fefb0202SYuval Mintz 271fefb0202SYuval Mintz for (i = 0; i < QEDE_NUM_STATS; i++) 272fefb0202SYuval Mintz if (qede_stats_arr[i].pf_only) 273fefb0202SYuval Mintz num_stats--; 274fefb0202SYuval Mintz } 2759a4d7e86SSudarsana Reddy Kalluru return num_stats + QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS + 27680439a17SMintz, Yuval QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS; 277f3e72109SYuval Mintz case ETH_SS_PRIV_FLAGS: 278f3e72109SYuval Mintz return QEDE_PRI_FLAG_LEN; 2793044a02eSSudarsana Reddy Kalluru case ETH_SS_TEST: 2806ecb0a0cSYuval Mintz if (!IS_VF(edev)) 2813044a02eSSudarsana Reddy Kalluru return QEDE_ETHTOOL_TEST_MAX; 2826ecb0a0cSYuval Mintz else 2836ecb0a0cSYuval Mintz return 0; 284133fac0eSSudarsana Kalluru default: 285133fac0eSSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 286133fac0eSSudarsana Kalluru "Unsupported stringset 0x%08x\n", stringset); 287133fac0eSSudarsana Kalluru return -EINVAL; 288133fac0eSSudarsana Kalluru } 289133fac0eSSudarsana Kalluru } 290133fac0eSSudarsana Kalluru 291f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev) 292f3e72109SYuval Mintz { 293f3e72109SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 294f3e72109SYuval Mintz 295f3e72109SYuval Mintz return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; 296f3e72109SYuval Mintz } 297f3e72109SYuval Mintz 298054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping { 299054c67d1SSudarsana Reddy Kalluru u32 qed_link_mode; 300054c67d1SSudarsana Reddy Kalluru u32 ethtool_link_mode; 301054c67d1SSudarsana Reddy Kalluru }; 302054c67d1SSudarsana Reddy Kalluru 303054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = { 304054c67d1SSudarsana Reddy Kalluru {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT}, 305054c67d1SSudarsana Reddy Kalluru {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT}, 306054c67d1SSudarsana Reddy Kalluru {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT}, 307054c67d1SSudarsana Reddy Kalluru {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT}, 308054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT}, 309054c67d1SSudarsana Reddy Kalluru {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, 310054c67d1SSudarsana Reddy Kalluru {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, 311054c67d1SSudarsana Reddy Kalluru {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, 312054c67d1SSudarsana Reddy Kalluru {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, 313054c67d1SSudarsana Reddy Kalluru {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, 314054c67d1SSudarsana Reddy Kalluru {QED_LM_100000baseKR4_Full_BIT, 315054c67d1SSudarsana Reddy Kalluru ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, 316054c67d1SSudarsana Reddy Kalluru }; 317054c67d1SSudarsana Reddy Kalluru 318054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name) \ 319054c67d1SSudarsana Reddy Kalluru { \ 320054c67d1SSudarsana Reddy Kalluru int i; \ 321054c67d1SSudarsana Reddy Kalluru \ 322d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 323054c67d1SSudarsana Reddy Kalluru if ((caps) & (qed_lm_map[i].qed_link_mode)) \ 324054c67d1SSudarsana Reddy Kalluru __set_bit(qed_lm_map[i].ethtool_link_mode,\ 325054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name); \ 326054c67d1SSudarsana Reddy Kalluru } \ 327054c67d1SSudarsana Reddy Kalluru } 328054c67d1SSudarsana Reddy Kalluru 329054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name) \ 330054c67d1SSudarsana Reddy Kalluru { \ 331054c67d1SSudarsana Reddy Kalluru int i; \ 332054c67d1SSudarsana Reddy Kalluru \ 333d7455f6eSMintz, Yuval for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) { \ 334054c67d1SSudarsana Reddy Kalluru if (test_bit(qed_lm_map[i].ethtool_link_mode, \ 335054c67d1SSudarsana Reddy Kalluru lk_ksettings->link_modes.name)) \ 336054c67d1SSudarsana Reddy Kalluru caps |= qed_lm_map[i].qed_link_mode; \ 337054c67d1SSudarsana Reddy Kalluru } \ 338054c67d1SSudarsana Reddy Kalluru } 339054c67d1SSudarsana Reddy Kalluru 340054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev, 341054c67d1SSudarsana Reddy Kalluru struct ethtool_link_ksettings *cmd) 342133fac0eSSudarsana Kalluru { 343054c67d1SSudarsana Reddy Kalluru struct ethtool_link_settings *base = &cmd->base; 344133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 345133fac0eSSudarsana Kalluru struct qed_link_output current_link; 346133fac0eSSudarsana Kalluru 347133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 348133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 349133fac0eSSudarsana Kalluru 350054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, supported); 351054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported) 352054c67d1SSudarsana Reddy Kalluru 353054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, advertising); 354054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising) 355054c67d1SSudarsana Reddy Kalluru 356054c67d1SSudarsana Reddy Kalluru ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); 357054c67d1SSudarsana Reddy Kalluru QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising) 358054c67d1SSudarsana Reddy Kalluru 359133fac0eSSudarsana Kalluru if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { 360054c67d1SSudarsana Reddy Kalluru base->speed = current_link.speed; 361054c67d1SSudarsana Reddy Kalluru base->duplex = current_link.duplex; 362133fac0eSSudarsana Kalluru } else { 363054c67d1SSudarsana Reddy Kalluru base->speed = SPEED_UNKNOWN; 364054c67d1SSudarsana Reddy Kalluru base->duplex = DUPLEX_UNKNOWN; 365133fac0eSSudarsana Kalluru } 366054c67d1SSudarsana Reddy Kalluru base->port = current_link.port; 367054c67d1SSudarsana Reddy Kalluru base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : 368133fac0eSSudarsana Kalluru AUTONEG_DISABLE; 369133fac0eSSudarsana Kalluru 370133fac0eSSudarsana Kalluru return 0; 371133fac0eSSudarsana Kalluru } 372133fac0eSSudarsana Kalluru 373054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev, 374054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_ksettings *cmd) 375133fac0eSSudarsana Kalluru { 376054c67d1SSudarsana Reddy Kalluru const struct ethtool_link_settings *base = &cmd->base; 377133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 378133fac0eSSudarsana Kalluru struct qed_link_output current_link; 379133fac0eSSudarsana Kalluru struct qed_link_params params; 380133fac0eSSudarsana Kalluru 381fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 382054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Link settings are not allowed to be changed\n"); 383133fac0eSSudarsana Kalluru return -EOPNOTSUPP; 384133fac0eSSudarsana Kalluru } 385133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 386133fac0eSSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 387133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 388133fac0eSSudarsana Kalluru 389133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; 390133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; 391054c67d1SSudarsana Reddy Kalluru if (base->autoneg == AUTONEG_ENABLE) { 392133fac0eSSudarsana Kalluru params.autoneg = true; 393133fac0eSSudarsana Kalluru params.forced_speed = 0; 394054c67d1SSudarsana Reddy Kalluru QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising) 395133fac0eSSudarsana Kalluru } else { /* forced speed */ 396133fac0eSSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; 397133fac0eSSudarsana Kalluru params.autoneg = false; 398054c67d1SSudarsana Reddy Kalluru params.forced_speed = base->speed; 399054c67d1SSudarsana Reddy Kalluru switch (base->speed) { 400133fac0eSSudarsana Kalluru case SPEED_10000: 401133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 402054c67d1SSudarsana Reddy Kalluru QED_LM_10000baseKR_Full_BIT)) { 403133fac0eSSudarsana Kalluru DP_INFO(edev, "10G speed not supported\n"); 404133fac0eSSudarsana Kalluru return -EINVAL; 405133fac0eSSudarsana Kalluru } 406054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_10000baseKR_Full_BIT; 407054c67d1SSudarsana Reddy Kalluru break; 408054c67d1SSudarsana Reddy Kalluru case SPEED_25000: 409054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 410054c67d1SSudarsana Reddy Kalluru QED_LM_25000baseKR_Full_BIT)) { 411054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "25G speed not supported\n"); 412054c67d1SSudarsana Reddy Kalluru return -EINVAL; 413054c67d1SSudarsana Reddy Kalluru } 414054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_25000baseKR_Full_BIT; 415133fac0eSSudarsana Kalluru break; 416133fac0eSSudarsana Kalluru case SPEED_40000: 417133fac0eSSudarsana Kalluru if (!(current_link.supported_caps & 418054c67d1SSudarsana Reddy Kalluru QED_LM_40000baseLR4_Full_BIT)) { 419133fac0eSSudarsana Kalluru DP_INFO(edev, "40G speed not supported\n"); 420133fac0eSSudarsana Kalluru return -EINVAL; 421133fac0eSSudarsana Kalluru } 422054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_40000baseLR4_Full_BIT; 423054c67d1SSudarsana Reddy Kalluru break; 42416d5946aSYuval Mintz case SPEED_50000: 425054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 426054c67d1SSudarsana Reddy Kalluru QED_LM_50000baseKR2_Full_BIT)) { 427054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "50G speed not supported\n"); 428054c67d1SSudarsana Reddy Kalluru return -EINVAL; 429054c67d1SSudarsana Reddy Kalluru } 430054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_50000baseKR2_Full_BIT; 431054c67d1SSudarsana Reddy Kalluru break; 43216d5946aSYuval Mintz case SPEED_100000: 433054c67d1SSudarsana Reddy Kalluru if (!(current_link.supported_caps & 434054c67d1SSudarsana Reddy Kalluru QED_LM_100000baseKR4_Full_BIT)) { 435054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "100G speed not supported\n"); 436054c67d1SSudarsana Reddy Kalluru return -EINVAL; 437054c67d1SSudarsana Reddy Kalluru } 438054c67d1SSudarsana Reddy Kalluru params.adv_speeds = QED_LM_100000baseKR4_Full_BIT; 439133fac0eSSudarsana Kalluru break; 440133fac0eSSudarsana Kalluru default: 441054c67d1SSudarsana Reddy Kalluru DP_INFO(edev, "Unsupported speed %u\n", base->speed); 442133fac0eSSudarsana Kalluru return -EINVAL; 443133fac0eSSudarsana Kalluru } 444133fac0eSSudarsana Kalluru } 445133fac0eSSudarsana Kalluru 446133fac0eSSudarsana Kalluru params.link_up = true; 447133fac0eSSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 448133fac0eSSudarsana Kalluru 449133fac0eSSudarsana Kalluru return 0; 450133fac0eSSudarsana Kalluru } 451133fac0eSSudarsana Kalluru 452133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev, 453133fac0eSSudarsana Kalluru struct ethtool_drvinfo *info) 454133fac0eSSudarsana Kalluru { 455133fac0eSSudarsana Kalluru char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; 456133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 457133fac0eSSudarsana Kalluru 458133fac0eSSudarsana Kalluru strlcpy(info->driver, "qede", sizeof(info->driver)); 459133fac0eSSudarsana Kalluru strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 460133fac0eSSudarsana Kalluru 461133fac0eSSudarsana Kalluru snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 462133fac0eSSudarsana Kalluru edev->dev_info.common.fw_major, 463133fac0eSSudarsana Kalluru edev->dev_info.common.fw_minor, 464133fac0eSSudarsana Kalluru edev->dev_info.common.fw_rev, 465133fac0eSSudarsana Kalluru edev->dev_info.common.fw_eng); 466133fac0eSSudarsana Kalluru 467133fac0eSSudarsana Kalluru snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", 468133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 24) & 0xFF, 469133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 16) & 0xFF, 470133fac0eSSudarsana Kalluru (edev->dev_info.common.mfw_rev >> 8) & 0xFF, 471133fac0eSSudarsana Kalluru edev->dev_info.common.mfw_rev & 0xFF); 472133fac0eSSudarsana Kalluru 473133fac0eSSudarsana Kalluru if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < 474133fac0eSSudarsana Kalluru sizeof(info->fw_version)) { 475133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 476133fac0eSSudarsana Kalluru "mfw %s storm %s", mfw, storm); 477133fac0eSSudarsana Kalluru } else { 478133fac0eSSudarsana Kalluru snprintf(info->fw_version, sizeof(info->fw_version), 479133fac0eSSudarsana Kalluru "%s %s", mfw, storm); 480133fac0eSSudarsana Kalluru } 481133fac0eSSudarsana Kalluru 482133fac0eSSudarsana Kalluru strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); 483133fac0eSSudarsana Kalluru } 484133fac0eSSudarsana Kalluru 48514d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 48614d39648SMintz, Yuval { 48714d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 48814d39648SMintz, Yuval 48914d39648SMintz, Yuval if (edev->dev_info.common.wol_support) { 49014d39648SMintz, Yuval wol->supported = WAKE_MAGIC; 49114d39648SMintz, Yuval wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0; 49214d39648SMintz, Yuval } 49314d39648SMintz, Yuval } 49414d39648SMintz, Yuval 49514d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 49614d39648SMintz, Yuval { 49714d39648SMintz, Yuval struct qede_dev *edev = netdev_priv(ndev); 49814d39648SMintz, Yuval bool wol_requested; 49914d39648SMintz, Yuval int rc; 50014d39648SMintz, Yuval 50114d39648SMintz, Yuval if (wol->wolopts & ~WAKE_MAGIC) { 50214d39648SMintz, Yuval DP_INFO(edev, 50314d39648SMintz, Yuval "Can't support WoL options other than magic-packet\n"); 50414d39648SMintz, Yuval return -EINVAL; 50514d39648SMintz, Yuval } 50614d39648SMintz, Yuval 50714d39648SMintz, Yuval wol_requested = !!(wol->wolopts & WAKE_MAGIC); 50814d39648SMintz, Yuval if (wol_requested == edev->wol_enabled) 50914d39648SMintz, Yuval return 0; 51014d39648SMintz, Yuval 51114d39648SMintz, Yuval /* Need to actually change configuration */ 51214d39648SMintz, Yuval if (!edev->dev_info.common.wol_support) { 51314d39648SMintz, Yuval DP_INFO(edev, "Device doesn't support WoL\n"); 51414d39648SMintz, Yuval return -EINVAL; 51514d39648SMintz, Yuval } 51614d39648SMintz, Yuval 51714d39648SMintz, Yuval rc = edev->ops->common->update_wol(edev->cdev, wol_requested); 51814d39648SMintz, Yuval if (!rc) 51914d39648SMintz, Yuval edev->wol_enabled = wol_requested; 52014d39648SMintz, Yuval 52114d39648SMintz, Yuval return rc; 52214d39648SMintz, Yuval } 52314d39648SMintz, Yuval 524133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev) 525133fac0eSSudarsana Kalluru { 526133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 527133fac0eSSudarsana Kalluru 5281a635e48SYuval Mintz return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module; 529133fac0eSSudarsana Kalluru } 530133fac0eSSudarsana Kalluru 531133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level) 532133fac0eSSudarsana Kalluru { 533133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 534133fac0eSSudarsana Kalluru u32 dp_module = 0; 535133fac0eSSudarsana Kalluru u8 dp_level = 0; 536133fac0eSSudarsana Kalluru 537133fac0eSSudarsana Kalluru qede_config_debug(level, &dp_module, &dp_level); 538133fac0eSSudarsana Kalluru 539133fac0eSSudarsana Kalluru edev->dp_level = dp_level; 540133fac0eSSudarsana Kalluru edev->dp_module = dp_module; 541133fac0eSSudarsana Kalluru edev->ops->common->update_msglvl(edev->cdev, 542133fac0eSSudarsana Kalluru dp_module, dp_level); 543133fac0eSSudarsana Kalluru } 544133fac0eSSudarsana Kalluru 54532a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev) 54632a7a570SSudarsana Kalluru { 54732a7a570SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 54832a7a570SSudarsana Kalluru struct qed_link_output current_link; 54932a7a570SSudarsana Kalluru struct qed_link_params link_params; 55032a7a570SSudarsana Kalluru 551fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 5521a635e48SYuval Mintz DP_INFO(edev, "Link settings are not allowed to be changed\n"); 553fe7cd2bfSYuval Mintz return -EOPNOTSUPP; 554fe7cd2bfSYuval Mintz } 555fe7cd2bfSYuval Mintz 55632a7a570SSudarsana Kalluru if (!netif_running(dev)) 55732a7a570SSudarsana Kalluru return 0; 55832a7a570SSudarsana Kalluru 55932a7a570SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 56032a7a570SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 56132a7a570SSudarsana Kalluru if (!current_link.link_up) 56232a7a570SSudarsana Kalluru return 0; 56332a7a570SSudarsana Kalluru 56432a7a570SSudarsana Kalluru /* Toggle the link */ 56532a7a570SSudarsana Kalluru memset(&link_params, 0, sizeof(link_params)); 56632a7a570SSudarsana Kalluru link_params.link_up = false; 56732a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 56832a7a570SSudarsana Kalluru link_params.link_up = true; 56932a7a570SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 57032a7a570SSudarsana Kalluru 57132a7a570SSudarsana Kalluru return 0; 57232a7a570SSudarsana Kalluru } 57332a7a570SSudarsana Kalluru 574133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev) 575133fac0eSSudarsana Kalluru { 576133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 577133fac0eSSudarsana Kalluru struct qed_link_output current_link; 578133fac0eSSudarsana Kalluru 579133fac0eSSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 580133fac0eSSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 581133fac0eSSudarsana Kalluru 582133fac0eSSudarsana Kalluru return current_link.link_up; 583133fac0eSSudarsana Kalluru } 584133fac0eSSudarsana Kalluru 585d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev, 586d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 587d552fa84SSudarsana Reddy Kalluru { 588d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 589d2890deaSSudarsana Reddy Kalluru u16 rxc, txc; 590d552fa84SSudarsana Reddy Kalluru 591d552fa84SSudarsana Reddy Kalluru memset(coal, 0, sizeof(struct ethtool_coalesce)); 592d2890deaSSudarsana Reddy Kalluru edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc); 593d2890deaSSudarsana Reddy Kalluru 594d2890deaSSudarsana Reddy Kalluru coal->rx_coalesce_usecs = rxc; 595d2890deaSSudarsana Reddy Kalluru coal->tx_coalesce_usecs = txc; 596d552fa84SSudarsana Reddy Kalluru 597d552fa84SSudarsana Reddy Kalluru return 0; 598d552fa84SSudarsana Reddy Kalluru } 599d552fa84SSudarsana Reddy Kalluru 600d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev, 601d552fa84SSudarsana Reddy Kalluru struct ethtool_coalesce *coal) 602d552fa84SSudarsana Reddy Kalluru { 603d552fa84SSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 604d552fa84SSudarsana Reddy Kalluru int i, rc = 0; 605d552fa84SSudarsana Reddy Kalluru u16 rxc, txc; 606d552fa84SSudarsana Reddy Kalluru u8 sb_id; 607d552fa84SSudarsana Reddy Kalluru 608d552fa84SSudarsana Reddy Kalluru if (!netif_running(dev)) { 609d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Interface is down\n"); 610d552fa84SSudarsana Reddy Kalluru return -EINVAL; 611d552fa84SSudarsana Reddy Kalluru } 612d552fa84SSudarsana Reddy Kalluru 613d552fa84SSudarsana Reddy Kalluru if (coal->rx_coalesce_usecs > QED_COALESCE_MAX || 614d552fa84SSudarsana Reddy Kalluru coal->tx_coalesce_usecs > QED_COALESCE_MAX) { 615d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, 616d552fa84SSudarsana Reddy Kalluru "Can't support requested %s coalesce value [max supported value %d]\n", 617d552fa84SSudarsana Reddy Kalluru coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" 618d552fa84SSudarsana Reddy Kalluru : "tx", 619d552fa84SSudarsana Reddy Kalluru QED_COALESCE_MAX); 620d552fa84SSudarsana Reddy Kalluru return -EINVAL; 621d552fa84SSudarsana Reddy Kalluru } 622d552fa84SSudarsana Reddy Kalluru 623d552fa84SSudarsana Reddy Kalluru rxc = (u16)coal->rx_coalesce_usecs; 624d552fa84SSudarsana Reddy Kalluru txc = (u16)coal->tx_coalesce_usecs; 6259a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 626d552fa84SSudarsana Reddy Kalluru sb_id = edev->fp_array[i].sb_info->igu_sb_id; 627d552fa84SSudarsana Reddy Kalluru rc = edev->ops->common->set_coalesce(edev->cdev, rxc, txc, 628d552fa84SSudarsana Reddy Kalluru (u8)i, sb_id); 629d552fa84SSudarsana Reddy Kalluru if (rc) { 630d552fa84SSudarsana Reddy Kalluru DP_INFO(edev, "Set coalesce error, rc = %d\n", rc); 631d552fa84SSudarsana Reddy Kalluru return rc; 632d552fa84SSudarsana Reddy Kalluru } 633d552fa84SSudarsana Reddy Kalluru } 634d552fa84SSudarsana Reddy Kalluru 635d552fa84SSudarsana Reddy Kalluru return rc; 636d552fa84SSudarsana Reddy Kalluru } 637d552fa84SSudarsana Reddy Kalluru 63801ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev, 63901ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 64001ef7e05SSudarsana Kalluru { 64101ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 64201ef7e05SSudarsana Kalluru 64301ef7e05SSudarsana Kalluru ering->rx_max_pending = NUM_RX_BDS_MAX; 64401ef7e05SSudarsana Kalluru ering->rx_pending = edev->q_num_rx_buffers; 64501ef7e05SSudarsana Kalluru ering->tx_max_pending = NUM_TX_BDS_MAX; 64601ef7e05SSudarsana Kalluru ering->tx_pending = edev->q_num_tx_buffers; 64701ef7e05SSudarsana Kalluru } 64801ef7e05SSudarsana Kalluru 64901ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev, 65001ef7e05SSudarsana Kalluru struct ethtool_ringparam *ering) 65101ef7e05SSudarsana Kalluru { 65201ef7e05SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 65301ef7e05SSudarsana Kalluru 65401ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 65501ef7e05SSudarsana Kalluru "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n", 65601ef7e05SSudarsana Kalluru ering->rx_pending, ering->tx_pending); 65701ef7e05SSudarsana Kalluru 65801ef7e05SSudarsana Kalluru /* Validate legality of configuration */ 65901ef7e05SSudarsana Kalluru if (ering->rx_pending > NUM_RX_BDS_MAX || 66001ef7e05SSudarsana Kalluru ering->rx_pending < NUM_RX_BDS_MIN || 66101ef7e05SSudarsana Kalluru ering->tx_pending > NUM_TX_BDS_MAX || 66201ef7e05SSudarsana Kalluru ering->tx_pending < NUM_TX_BDS_MIN) { 66301ef7e05SSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 66401ef7e05SSudarsana Kalluru "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n", 66501ef7e05SSudarsana Kalluru NUM_RX_BDS_MIN, NUM_RX_BDS_MAX, 66601ef7e05SSudarsana Kalluru NUM_TX_BDS_MIN, NUM_TX_BDS_MAX); 66701ef7e05SSudarsana Kalluru return -EINVAL; 66801ef7e05SSudarsana Kalluru } 66901ef7e05SSudarsana Kalluru 67001ef7e05SSudarsana Kalluru /* Change ring size and re-load */ 67101ef7e05SSudarsana Kalluru edev->q_num_rx_buffers = ering->rx_pending; 67201ef7e05SSudarsana Kalluru edev->q_num_tx_buffers = ering->tx_pending; 67301ef7e05SSudarsana Kalluru 67401ef7e05SSudarsana Kalluru if (netif_running(edev->ndev)) 67501ef7e05SSudarsana Kalluru qede_reload(edev, NULL, NULL); 67601ef7e05SSudarsana Kalluru 67701ef7e05SSudarsana Kalluru return 0; 67801ef7e05SSudarsana Kalluru } 67901ef7e05SSudarsana Kalluru 6800f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev, 6810f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 6820f7db144SSudarsana Kalluru { 6830f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 6840f7db144SSudarsana Kalluru struct qed_link_output current_link; 6850f7db144SSudarsana Kalluru 6860f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 6870f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 6880f7db144SSudarsana Kalluru 6890f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE) 6900f7db144SSudarsana Kalluru epause->autoneg = true; 6910f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE) 6920f7db144SSudarsana Kalluru epause->rx_pause = true; 6930f7db144SSudarsana Kalluru if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE) 6940f7db144SSudarsana Kalluru epause->tx_pause = true; 6950f7db144SSudarsana Kalluru 6960f7db144SSudarsana Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 6970f7db144SSudarsana Kalluru "ethtool_pauseparam: cmd %d autoneg %d rx_pause %d tx_pause %d\n", 6980f7db144SSudarsana Kalluru epause->cmd, epause->autoneg, epause->rx_pause, 6990f7db144SSudarsana Kalluru epause->tx_pause); 7000f7db144SSudarsana Kalluru } 7010f7db144SSudarsana Kalluru 7020f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev, 7030f7db144SSudarsana Kalluru struct ethtool_pauseparam *epause) 7040f7db144SSudarsana Kalluru { 7050f7db144SSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7060f7db144SSudarsana Kalluru struct qed_link_params params; 7070f7db144SSudarsana Kalluru struct qed_link_output current_link; 7080f7db144SSudarsana Kalluru 709fe7cd2bfSYuval Mintz if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) { 7100f7db144SSudarsana Kalluru DP_INFO(edev, 711fe7cd2bfSYuval Mintz "Pause settings are not allowed to be changed\n"); 7120f7db144SSudarsana Kalluru return -EOPNOTSUPP; 7130f7db144SSudarsana Kalluru } 7140f7db144SSudarsana Kalluru 7150f7db144SSudarsana Kalluru memset(¤t_link, 0, sizeof(current_link)); 7160f7db144SSudarsana Kalluru edev->ops->common->get_link(edev->cdev, ¤t_link); 7170f7db144SSudarsana Kalluru 7180f7db144SSudarsana Kalluru memset(¶ms, 0, sizeof(params)); 7190f7db144SSudarsana Kalluru params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG; 7200f7db144SSudarsana Kalluru if (epause->autoneg) { 721d194fd26SYuval Mintz if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) { 7220f7db144SSudarsana Kalluru DP_INFO(edev, "autoneg not supported\n"); 7230f7db144SSudarsana Kalluru return -EINVAL; 7240f7db144SSudarsana Kalluru } 7250f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; 7260f7db144SSudarsana Kalluru } 7270f7db144SSudarsana Kalluru if (epause->rx_pause) 7280f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_RX_ENABLE; 7290f7db144SSudarsana Kalluru if (epause->tx_pause) 7300f7db144SSudarsana Kalluru params.pause_config |= QED_LINK_PAUSE_TX_ENABLE; 7310f7db144SSudarsana Kalluru 7320f7db144SSudarsana Kalluru params.link_up = true; 7330f7db144SSudarsana Kalluru edev->ops->common->set_link(edev->cdev, ¶ms); 7340f7db144SSudarsana Kalluru 7350f7db144SSudarsana Kalluru return 0; 7360f7db144SSudarsana Kalluru } 7370f7db144SSudarsana Kalluru 738e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev, 739e0971c83STomer Tayar struct ethtool_regs *regs, void *buffer) 740e0971c83STomer Tayar { 741e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 742e0971c83STomer Tayar 743e0971c83STomer Tayar regs->version = 0; 744e0971c83STomer Tayar memset(buffer, 0, regs->len); 745e0971c83STomer Tayar 746e0971c83STomer Tayar if (edev->ops && edev->ops->common) 747e0971c83STomer Tayar edev->ops->common->dbg_all_data(edev->cdev, buffer); 748e0971c83STomer Tayar } 749e0971c83STomer Tayar 750e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev) 751e0971c83STomer Tayar { 752e0971c83STomer Tayar struct qede_dev *edev = netdev_priv(ndev); 753e0971c83STomer Tayar 754e0971c83STomer Tayar if (edev->ops && edev->ops->common) 755e0971c83STomer Tayar return edev->ops->common->dbg_all_data_size(edev->cdev); 756e0971c83STomer Tayar else 757e0971c83STomer Tayar return -EINVAL; 758e0971c83STomer Tayar } 759e0971c83STomer Tayar 760133fac0eSSudarsana Kalluru static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args) 761133fac0eSSudarsana Kalluru { 762133fac0eSSudarsana Kalluru edev->ndev->mtu = args->mtu; 763133fac0eSSudarsana Kalluru } 764133fac0eSSudarsana Kalluru 765133fac0eSSudarsana Kalluru /* Netdevice NDOs */ 766133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu) 767133fac0eSSudarsana Kalluru { 768133fac0eSSudarsana Kalluru struct qede_dev *edev = netdev_priv(ndev); 769133fac0eSSudarsana Kalluru union qede_reload_args args; 770133fac0eSSudarsana Kalluru 771133fac0eSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 772133fac0eSSudarsana Kalluru "Configuring MTU size of %d\n", new_mtu); 773133fac0eSSudarsana Kalluru 774133fac0eSSudarsana Kalluru /* Set the mtu field and re-start the interface if needed*/ 775133fac0eSSudarsana Kalluru args.mtu = new_mtu; 776133fac0eSSudarsana Kalluru 777133fac0eSSudarsana Kalluru if (netif_running(edev->ndev)) 778133fac0eSSudarsana Kalluru qede_reload(edev, &qede_update_mtu, &args); 779133fac0eSSudarsana Kalluru 780133fac0eSSudarsana Kalluru qede_update_mtu(edev, &args); 781133fac0eSSudarsana Kalluru 7820fefbfbaSSudarsana Kalluru edev->ops->common->update_mtu(edev->cdev, args.mtu); 7830fefbfbaSSudarsana Kalluru 784133fac0eSSudarsana Kalluru return 0; 785133fac0eSSudarsana Kalluru } 786133fac0eSSudarsana Kalluru 7878edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev, 7888edf049dSSudarsana Kalluru struct ethtool_channels *channels) 7898edf049dSSudarsana Kalluru { 7908edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 7918edf049dSSudarsana Kalluru 7928edf049dSSudarsana Kalluru channels->max_combined = QEDE_MAX_RSS_CNT(edev); 793bdc8cbd3SSudarsana Reddy Kalluru channels->max_rx = QEDE_MAX_RSS_CNT(edev); 794bdc8cbd3SSudarsana Reddy Kalluru channels->max_tx = QEDE_MAX_RSS_CNT(edev); 7959a4d7e86SSudarsana Reddy Kalluru channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - 7969a4d7e86SSudarsana Reddy Kalluru edev->fp_num_rx; 7979a4d7e86SSudarsana Reddy Kalluru channels->tx_count = edev->fp_num_tx; 7989a4d7e86SSudarsana Reddy Kalluru channels->rx_count = edev->fp_num_rx; 7998edf049dSSudarsana Kalluru } 8008edf049dSSudarsana Kalluru 8018edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev, 8028edf049dSSudarsana Kalluru struct ethtool_channels *channels) 8038edf049dSSudarsana Kalluru { 8048edf049dSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8059a4d7e86SSudarsana Reddy Kalluru u32 count; 8068edf049dSSudarsana Kalluru 8078edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8088edf049dSSudarsana Kalluru "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", 8098edf049dSSudarsana Kalluru channels->rx_count, channels->tx_count, 8108edf049dSSudarsana Kalluru channels->other_count, channels->combined_count); 8118edf049dSSudarsana Kalluru 8129a4d7e86SSudarsana Reddy Kalluru count = channels->rx_count + channels->tx_count + 8139a4d7e86SSudarsana Reddy Kalluru channels->combined_count; 8149a4d7e86SSudarsana Reddy Kalluru 8159a4d7e86SSudarsana Reddy Kalluru /* We don't support `other' channels */ 8169a4d7e86SSudarsana Reddy Kalluru if (channels->other_count) { 8178edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8188edf049dSSudarsana Kalluru "command parameters not supported\n"); 8198edf049dSSudarsana Kalluru return -EINVAL; 8208edf049dSSudarsana Kalluru } 8218edf049dSSudarsana Kalluru 8229a4d7e86SSudarsana Reddy Kalluru if (!(channels->combined_count || (channels->rx_count && 8239a4d7e86SSudarsana Reddy Kalluru channels->tx_count))) { 8249a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8259a4d7e86SSudarsana Reddy Kalluru "need to request at least one transmit and one receive channel\n"); 8269a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 8279a4d7e86SSudarsana Reddy Kalluru } 8289a4d7e86SSudarsana Reddy Kalluru 8299a4d7e86SSudarsana Reddy Kalluru if (count > QEDE_MAX_RSS_CNT(edev)) { 8309a4d7e86SSudarsana Reddy Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8319a4d7e86SSudarsana Reddy Kalluru "requested channels = %d max supported channels = %d\n", 8329a4d7e86SSudarsana Reddy Kalluru count, QEDE_MAX_RSS_CNT(edev)); 8339a4d7e86SSudarsana Reddy Kalluru return -EINVAL; 8349a4d7e86SSudarsana Reddy Kalluru } 8359a4d7e86SSudarsana Reddy Kalluru 8368edf049dSSudarsana Kalluru /* Check if there was a change in the active parameters */ 8379a4d7e86SSudarsana Reddy Kalluru if ((count == QEDE_QUEUE_CNT(edev)) && 8389a4d7e86SSudarsana Reddy Kalluru (channels->tx_count == edev->fp_num_tx) && 8399a4d7e86SSudarsana Reddy Kalluru (channels->rx_count == edev->fp_num_rx)) { 8408edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8418edf049dSSudarsana Kalluru "No change in active parameters\n"); 8428edf049dSSudarsana Kalluru return 0; 8438edf049dSSudarsana Kalluru } 8448edf049dSSudarsana Kalluru 8458edf049dSSudarsana Kalluru /* We need the number of queues to be divisible between the hwfns */ 8469a4d7e86SSudarsana Reddy Kalluru if ((count % edev->dev_info.common.num_hwfns) || 8479a4d7e86SSudarsana Reddy Kalluru (channels->tx_count % edev->dev_info.common.num_hwfns) || 8489a4d7e86SSudarsana Reddy Kalluru (channels->rx_count % edev->dev_info.common.num_hwfns)) { 8498edf049dSSudarsana Kalluru DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), 8509a4d7e86SSudarsana Reddy Kalluru "Number of channels must be divisible by %04x\n", 8518edf049dSSudarsana Kalluru edev->dev_info.common.num_hwfns); 8528edf049dSSudarsana Kalluru return -EINVAL; 8538edf049dSSudarsana Kalluru } 8548edf049dSSudarsana Kalluru 8558edf049dSSudarsana Kalluru /* Set number of queues and reload if necessary */ 8569a4d7e86SSudarsana Reddy Kalluru edev->req_queues = count; 8579a4d7e86SSudarsana Reddy Kalluru edev->req_num_tx = channels->tx_count; 8589a4d7e86SSudarsana Reddy Kalluru edev->req_num_rx = channels->rx_count; 859ed0dd915SSudarsana Reddy Kalluru /* Reset the indirection table if rx queue count is updated */ 860ed0dd915SSudarsana Reddy Kalluru if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { 861ed0dd915SSudarsana Reddy Kalluru edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; 862ed0dd915SSudarsana Reddy Kalluru memset(&edev->rss_params.rss_ind_table, 0, 863ed0dd915SSudarsana Reddy Kalluru sizeof(edev->rss_params.rss_ind_table)); 864ed0dd915SSudarsana Reddy Kalluru } 865ed0dd915SSudarsana Reddy Kalluru 8668edf049dSSudarsana Kalluru if (netif_running(dev)) 8678edf049dSSudarsana Kalluru qede_reload(edev, NULL, NULL); 8688edf049dSSudarsana Kalluru 8698edf049dSSudarsana Kalluru return 0; 8708edf049dSSudarsana Kalluru } 8718edf049dSSudarsana Kalluru 8723d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev, 8733d971cbdSSudarsana Kalluru enum ethtool_phys_id_state state) 8743d971cbdSSudarsana Kalluru { 8753d971cbdSSudarsana Kalluru struct qede_dev *edev = netdev_priv(dev); 8763d971cbdSSudarsana Kalluru u8 led_state = 0; 8773d971cbdSSudarsana Kalluru 8783d971cbdSSudarsana Kalluru switch (state) { 8793d971cbdSSudarsana Kalluru case ETHTOOL_ID_ACTIVE: 8803d971cbdSSudarsana Kalluru return 1; /* cycle on/off once per second */ 8813d971cbdSSudarsana Kalluru 8823d971cbdSSudarsana Kalluru case ETHTOOL_ID_ON: 8833d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_ON; 8843d971cbdSSudarsana Kalluru break; 8853d971cbdSSudarsana Kalluru 8863d971cbdSSudarsana Kalluru case ETHTOOL_ID_OFF: 8873d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_OFF; 8883d971cbdSSudarsana Kalluru break; 8893d971cbdSSudarsana Kalluru 8903d971cbdSSudarsana Kalluru case ETHTOOL_ID_INACTIVE: 8913d971cbdSSudarsana Kalluru led_state = QED_LED_MODE_RESTORE; 8923d971cbdSSudarsana Kalluru break; 8933d971cbdSSudarsana Kalluru } 8943d971cbdSSudarsana Kalluru 8953d971cbdSSudarsana Kalluru edev->ops->common->set_led(edev->cdev, led_state); 8963d971cbdSSudarsana Kalluru 8973d971cbdSSudarsana Kalluru return 0; 8983d971cbdSSudarsana Kalluru } 8993d971cbdSSudarsana Kalluru 900961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 901961acdeaSSudarsana Reddy Kalluru { 902961acdeaSSudarsana Reddy Kalluru info->data = RXH_IP_SRC | RXH_IP_DST; 903961acdeaSSudarsana Reddy Kalluru 904961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 905961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 906961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 907961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 908961acdeaSSudarsana Reddy Kalluru break; 909961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 910961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP) 911961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 912961acdeaSSudarsana Reddy Kalluru break; 913961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 914961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP) 915961acdeaSSudarsana Reddy Kalluru info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 916961acdeaSSudarsana Reddy Kalluru break; 917961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 918961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 919961acdeaSSudarsana Reddy Kalluru break; 920961acdeaSSudarsana Reddy Kalluru default: 921961acdeaSSudarsana Reddy Kalluru info->data = 0; 922961acdeaSSudarsana Reddy Kalluru break; 923961acdeaSSudarsana Reddy Kalluru } 924961acdeaSSudarsana Reddy Kalluru 925961acdeaSSudarsana Reddy Kalluru return 0; 926961acdeaSSudarsana Reddy Kalluru } 927961acdeaSSudarsana Reddy Kalluru 928961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 929961acdeaSSudarsana Reddy Kalluru u32 *rules __always_unused) 930961acdeaSSudarsana Reddy Kalluru { 931961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 932961acdeaSSudarsana Reddy Kalluru 933961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 934961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXRINGS: 9359a4d7e86SSudarsana Reddy Kalluru info->data = QEDE_RSS_COUNT(edev); 936961acdeaSSudarsana Reddy Kalluru return 0; 937961acdeaSSudarsana Reddy Kalluru case ETHTOOL_GRXFH: 938961acdeaSSudarsana Reddy Kalluru return qede_get_rss_flags(edev, info); 939961acdeaSSudarsana Reddy Kalluru default: 940961acdeaSSudarsana Reddy Kalluru DP_ERR(edev, "Command parameters not supported\n"); 941961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 942961acdeaSSudarsana Reddy Kalluru } 943961acdeaSSudarsana Reddy Kalluru } 944961acdeaSSudarsana Reddy Kalluru 945961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info) 946961acdeaSSudarsana Reddy Kalluru { 947961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 948961acdeaSSudarsana Reddy Kalluru u8 set_caps = 0, clr_caps = 0; 949961acdeaSSudarsana Reddy Kalluru 950961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 951961acdeaSSudarsana Reddy Kalluru "Set rss flags command parameters: flow type = %d, data = %llu\n", 952961acdeaSSudarsana Reddy Kalluru info->flow_type, info->data); 953961acdeaSSudarsana Reddy Kalluru 954961acdeaSSudarsana Reddy Kalluru switch (info->flow_type) { 955961acdeaSSudarsana Reddy Kalluru case TCP_V4_FLOW: 956961acdeaSSudarsana Reddy Kalluru case TCP_V6_FLOW: 957961acdeaSSudarsana Reddy Kalluru /* For TCP only 4-tuple hash is supported */ 958961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST | 959961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 960961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 961961acdeaSSudarsana Reddy Kalluru return -EINVAL; 962961acdeaSSudarsana Reddy Kalluru } 963961acdeaSSudarsana Reddy Kalluru return 0; 964961acdeaSSudarsana Reddy Kalluru case UDP_V4_FLOW: 965961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 966961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 967961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 968961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV4_UDP; 969961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 970961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 971961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 972961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV4_UDP; 973961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 974961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 975961acdeaSSudarsana Reddy Kalluru } else { 976961acdeaSSudarsana Reddy Kalluru return -EINVAL; 977961acdeaSSudarsana Reddy Kalluru } 978961acdeaSSudarsana Reddy Kalluru break; 979961acdeaSSudarsana Reddy Kalluru case UDP_V6_FLOW: 980961acdeaSSudarsana Reddy Kalluru /* For UDP either 2-tuple hash or 4-tuple hash is supported */ 981961acdeaSSudarsana Reddy Kalluru if (info->data == (RXH_IP_SRC | RXH_IP_DST | 982961acdeaSSudarsana Reddy Kalluru RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 983961acdeaSSudarsana Reddy Kalluru set_caps = QED_RSS_IPV6_UDP; 984961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 985961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple enabled\n"); 986961acdeaSSudarsana Reddy Kalluru } else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) { 987961acdeaSSudarsana Reddy Kalluru clr_caps = QED_RSS_IPV6_UDP; 988961acdeaSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 989961acdeaSSudarsana Reddy Kalluru "UDP 4-tuple disabled\n"); 990961acdeaSSudarsana Reddy Kalluru } else { 991961acdeaSSudarsana Reddy Kalluru return -EINVAL; 992961acdeaSSudarsana Reddy Kalluru } 993961acdeaSSudarsana Reddy Kalluru break; 994961acdeaSSudarsana Reddy Kalluru case IPV4_FLOW: 995961acdeaSSudarsana Reddy Kalluru case IPV6_FLOW: 996961acdeaSSudarsana Reddy Kalluru /* For IP only 2-tuple hash is supported */ 997961acdeaSSudarsana Reddy Kalluru if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) { 998961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 999961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1000961acdeaSSudarsana Reddy Kalluru } 1001961acdeaSSudarsana Reddy Kalluru return 0; 1002961acdeaSSudarsana Reddy Kalluru case SCTP_V4_FLOW: 1003961acdeaSSudarsana Reddy Kalluru case AH_ESP_V4_FLOW: 1004961acdeaSSudarsana Reddy Kalluru case AH_V4_FLOW: 1005961acdeaSSudarsana Reddy Kalluru case ESP_V4_FLOW: 1006961acdeaSSudarsana Reddy Kalluru case SCTP_V6_FLOW: 1007961acdeaSSudarsana Reddy Kalluru case AH_ESP_V6_FLOW: 1008961acdeaSSudarsana Reddy Kalluru case AH_V6_FLOW: 1009961acdeaSSudarsana Reddy Kalluru case ESP_V6_FLOW: 1010961acdeaSSudarsana Reddy Kalluru case IP_USER_FLOW: 1011961acdeaSSudarsana Reddy Kalluru case ETHER_FLOW: 1012961acdeaSSudarsana Reddy Kalluru /* RSS is not supported for these protocols */ 1013961acdeaSSudarsana Reddy Kalluru if (info->data) { 1014961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1015961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1016961acdeaSSudarsana Reddy Kalluru } 1017961acdeaSSudarsana Reddy Kalluru return 0; 1018961acdeaSSudarsana Reddy Kalluru default: 1019961acdeaSSudarsana Reddy Kalluru return -EINVAL; 1020961acdeaSSudarsana Reddy Kalluru } 1021961acdeaSSudarsana Reddy Kalluru 1022961acdeaSSudarsana Reddy Kalluru /* No action is needed if there is no change in the rss capability */ 1023961acdeaSSudarsana Reddy Kalluru if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps & 1024961acdeaSSudarsana Reddy Kalluru ~clr_caps) | set_caps)) 1025961acdeaSSudarsana Reddy Kalluru return 0; 1026961acdeaSSudarsana Reddy Kalluru 1027961acdeaSSudarsana Reddy Kalluru /* Update internal configuration */ 1028961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) | 1029961acdeaSSudarsana Reddy Kalluru set_caps; 1030961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_CAPS_INITED; 1031961acdeaSSudarsana Reddy Kalluru 1032961acdeaSSudarsana Reddy Kalluru /* Re-configure if possible */ 1033961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1034961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1035961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1036961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1037961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1038961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1039961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1040961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1041961acdeaSSudarsana Reddy Kalluru } 1042961acdeaSSudarsana Reddy Kalluru 1043961acdeaSSudarsana Reddy Kalluru return 0; 1044961acdeaSSudarsana Reddy Kalluru } 1045961acdeaSSudarsana Reddy Kalluru 1046961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 1047961acdeaSSudarsana Reddy Kalluru { 1048961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1049961acdeaSSudarsana Reddy Kalluru 1050961acdeaSSudarsana Reddy Kalluru switch (info->cmd) { 1051961acdeaSSudarsana Reddy Kalluru case ETHTOOL_SRXFH: 1052961acdeaSSudarsana Reddy Kalluru return qede_set_rss_flags(edev, info); 1053961acdeaSSudarsana Reddy Kalluru default: 1054961acdeaSSudarsana Reddy Kalluru DP_INFO(edev, "Command parameters not supported\n"); 1055961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1056961acdeaSSudarsana Reddy Kalluru } 1057961acdeaSSudarsana Reddy Kalluru } 1058961acdeaSSudarsana Reddy Kalluru 1059961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev) 1060961acdeaSSudarsana Reddy Kalluru { 1061961acdeaSSudarsana Reddy Kalluru return QED_RSS_IND_TABLE_SIZE; 1062961acdeaSSudarsana Reddy Kalluru } 1063961acdeaSSudarsana Reddy Kalluru 1064961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev) 1065961acdeaSSudarsana Reddy Kalluru { 1066961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1067961acdeaSSudarsana Reddy Kalluru 1068961acdeaSSudarsana Reddy Kalluru return sizeof(edev->rss_params.rss_key); 1069961acdeaSSudarsana Reddy Kalluru } 1070961acdeaSSudarsana Reddy Kalluru 1071961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) 1072961acdeaSSudarsana Reddy Kalluru { 1073961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1074961acdeaSSudarsana Reddy Kalluru int i; 1075961acdeaSSudarsana Reddy Kalluru 1076961acdeaSSudarsana Reddy Kalluru if (hfunc) 1077961acdeaSSudarsana Reddy Kalluru *hfunc = ETH_RSS_HASH_TOP; 1078961acdeaSSudarsana Reddy Kalluru 1079961acdeaSSudarsana Reddy Kalluru if (!indir) 1080961acdeaSSudarsana Reddy Kalluru return 0; 1081961acdeaSSudarsana Reddy Kalluru 1082961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1083961acdeaSSudarsana Reddy Kalluru indir[i] = edev->rss_params.rss_ind_table[i]; 1084961acdeaSSudarsana Reddy Kalluru 1085961acdeaSSudarsana Reddy Kalluru if (key) 1086961acdeaSSudarsana Reddy Kalluru memcpy(key, edev->rss_params.rss_key, 1087961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1088961acdeaSSudarsana Reddy Kalluru 1089961acdeaSSudarsana Reddy Kalluru return 0; 1090961acdeaSSudarsana Reddy Kalluru } 1091961acdeaSSudarsana Reddy Kalluru 1092961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir, 1093961acdeaSSudarsana Reddy Kalluru const u8 *key, const u8 hfunc) 1094961acdeaSSudarsana Reddy Kalluru { 1095961acdeaSSudarsana Reddy Kalluru struct qed_update_vport_params vport_update_params; 1096961acdeaSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 1097961acdeaSSudarsana Reddy Kalluru int i; 1098961acdeaSSudarsana Reddy Kalluru 1099ba300ce3SSudarsana Reddy Kalluru if (edev->dev_info.common.num_hwfns > 1) { 1100ba300ce3SSudarsana Reddy Kalluru DP_INFO(edev, 1101ba300ce3SSudarsana Reddy Kalluru "RSS configuration is not supported for 100G devices\n"); 1102ba300ce3SSudarsana Reddy Kalluru return -EOPNOTSUPP; 1103ba300ce3SSudarsana Reddy Kalluru } 1104ba300ce3SSudarsana Reddy Kalluru 1105961acdeaSSudarsana Reddy Kalluru if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 1106961acdeaSSudarsana Reddy Kalluru return -EOPNOTSUPP; 1107961acdeaSSudarsana Reddy Kalluru 1108961acdeaSSudarsana Reddy Kalluru if (!indir && !key) 1109961acdeaSSudarsana Reddy Kalluru return 0; 1110961acdeaSSudarsana Reddy Kalluru 1111961acdeaSSudarsana Reddy Kalluru if (indir) { 1112961acdeaSSudarsana Reddy Kalluru for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) 1113961acdeaSSudarsana Reddy Kalluru edev->rss_params.rss_ind_table[i] = indir[i]; 1114961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_INDIR_INITED; 1115961acdeaSSudarsana Reddy Kalluru } 1116961acdeaSSudarsana Reddy Kalluru 1117961acdeaSSudarsana Reddy Kalluru if (key) { 1118961acdeaSSudarsana Reddy Kalluru memcpy(&edev->rss_params.rss_key, key, 1119961acdeaSSudarsana Reddy Kalluru qede_get_rxfh_key_size(dev)); 1120961acdeaSSudarsana Reddy Kalluru edev->rss_params_inited |= QEDE_RSS_KEY_INITED; 1121961acdeaSSudarsana Reddy Kalluru } 1122961acdeaSSudarsana Reddy Kalluru 1123961acdeaSSudarsana Reddy Kalluru if (netif_running(edev->ndev)) { 1124961acdeaSSudarsana Reddy Kalluru memset(&vport_update_params, 0, sizeof(vport_update_params)); 1125961acdeaSSudarsana Reddy Kalluru vport_update_params.update_rss_flg = 1; 1126961acdeaSSudarsana Reddy Kalluru vport_update_params.vport_id = 0; 1127961acdeaSSudarsana Reddy Kalluru memcpy(&vport_update_params.rss_params, &edev->rss_params, 1128961acdeaSSudarsana Reddy Kalluru sizeof(vport_update_params.rss_params)); 1129961acdeaSSudarsana Reddy Kalluru return edev->ops->vport_update(edev->cdev, 1130961acdeaSSudarsana Reddy Kalluru &vport_update_params); 1131961acdeaSSudarsana Reddy Kalluru } 1132961acdeaSSudarsana Reddy Kalluru 1133961acdeaSSudarsana Reddy Kalluru return 0; 1134961acdeaSSudarsana Reddy Kalluru } 1135961acdeaSSudarsana Reddy Kalluru 113616f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */ 113716f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev) 113816f46bf0SSudarsana Reddy Kalluru { 113916f46bf0SSudarsana Reddy Kalluru int i; 114016f46bf0SSudarsana Reddy Kalluru 114116f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) 114216f46bf0SSudarsana Reddy Kalluru return; 114316f46bf0SSudarsana Reddy Kalluru 11449a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 114516f46bf0SSudarsana Reddy Kalluru /* Update and reenable interrupts */ 114616f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1); 114716f46bf0SSudarsana Reddy Kalluru napi_enable(&edev->fp_array[i].napi); 114816f46bf0SSudarsana Reddy Kalluru } 114916f46bf0SSudarsana Reddy Kalluru } 115016f46bf0SSudarsana Reddy Kalluru 115116f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */ 115216f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev) 115316f46bf0SSudarsana Reddy Kalluru { 115416f46bf0SSudarsana Reddy Kalluru int i; 115516f46bf0SSudarsana Reddy Kalluru 11569a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 115716f46bf0SSudarsana Reddy Kalluru napi_disable(&edev->fp_array[i].napi); 115816f46bf0SSudarsana Reddy Kalluru /* Disable interrupts */ 115916f46bf0SSudarsana Reddy Kalluru qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0); 116016f46bf0SSudarsana Reddy Kalluru } 116116f46bf0SSudarsana Reddy Kalluru } 116216f46bf0SSudarsana Reddy Kalluru 116316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev, 116416f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb) 116516f46bf0SSudarsana Reddy Kalluru { 11669a4d7e86SSudarsana Reddy Kalluru struct qede_tx_queue *txq = NULL; 116716f46bf0SSudarsana Reddy Kalluru struct eth_tx_1st_bd *first_bd; 116816f46bf0SSudarsana Reddy Kalluru dma_addr_t mapping; 116916f46bf0SSudarsana Reddy Kalluru int i, idx, val; 117016f46bf0SSudarsana Reddy Kalluru 11719a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 11729a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { 117380439a17SMintz, Yuval txq = edev->fp_array[i].txq; 11749a4d7e86SSudarsana Reddy Kalluru break; 11759a4d7e86SSudarsana Reddy Kalluru } 11769a4d7e86SSudarsana Reddy Kalluru } 11779a4d7e86SSudarsana Reddy Kalluru 11789a4d7e86SSudarsana Reddy Kalluru if (!txq) { 11799a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx path is not available\n"); 11809a4d7e86SSudarsana Reddy Kalluru return -1; 11819a4d7e86SSudarsana Reddy Kalluru } 11829a4d7e86SSudarsana Reddy Kalluru 118316f46bf0SSudarsana Reddy Kalluru /* Fill the entry in the SW ring and the BDs in the FW ring */ 118416f46bf0SSudarsana Reddy Kalluru idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; 118516f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = skb; 118616f46bf0SSudarsana Reddy Kalluru first_bd = qed_chain_produce(&txq->tx_pbl); 118716f46bf0SSudarsana Reddy Kalluru memset(first_bd, 0, sizeof(*first_bd)); 118816f46bf0SSudarsana Reddy Kalluru val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; 118916f46bf0SSudarsana Reddy Kalluru first_bd->data.bd_flags.bitfields = val; 1190351a4dedSYuval Mintz val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK; 1191351a4dedSYuval Mintz first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); 119216f46bf0SSudarsana Reddy Kalluru 119316f46bf0SSudarsana Reddy Kalluru /* Map skb linear data for DMA and set in the first BD */ 119416f46bf0SSudarsana Reddy Kalluru mapping = dma_map_single(&edev->pdev->dev, skb->data, 119516f46bf0SSudarsana Reddy Kalluru skb_headlen(skb), DMA_TO_DEVICE); 119616f46bf0SSudarsana Reddy Kalluru if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { 119716f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "SKB mapping failed\n"); 119816f46bf0SSudarsana Reddy Kalluru return -ENOMEM; 119916f46bf0SSudarsana Reddy Kalluru } 120016f46bf0SSudarsana Reddy Kalluru BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); 120116f46bf0SSudarsana Reddy Kalluru 120216f46bf0SSudarsana Reddy Kalluru /* update the first BD with the actual num BDs */ 120316f46bf0SSudarsana Reddy Kalluru first_bd->data.nbds = 1; 120416f46bf0SSudarsana Reddy Kalluru txq->sw_tx_prod++; 120516f46bf0SSudarsana Reddy Kalluru /* 'next page' entries are counted in the producer value */ 120616f46bf0SSudarsana Reddy Kalluru val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl)); 120716f46bf0SSudarsana Reddy Kalluru txq->tx_db.data.bd_prod = val; 120816f46bf0SSudarsana Reddy Kalluru 120916f46bf0SSudarsana Reddy Kalluru /* wmb makes sure that the BDs data is updated before updating the 121016f46bf0SSudarsana Reddy Kalluru * producer, otherwise FW may read old data from the BDs. 121116f46bf0SSudarsana Reddy Kalluru */ 121216f46bf0SSudarsana Reddy Kalluru wmb(); 121316f46bf0SSudarsana Reddy Kalluru barrier(); 121416f46bf0SSudarsana Reddy Kalluru writel(txq->tx_db.raw, txq->doorbell_addr); 121516f46bf0SSudarsana Reddy Kalluru 121616f46bf0SSudarsana Reddy Kalluru /* mmiowb is needed to synchronize doorbell writes from more than one 121716f46bf0SSudarsana Reddy Kalluru * processor. It guarantees that the write arrives to the device before 121816f46bf0SSudarsana Reddy Kalluru * the queue lock is released and another start_xmit is called (possibly 121916f46bf0SSudarsana Reddy Kalluru * on another CPU). Without this barrier, the next doorbell can bypass 122016f46bf0SSudarsana Reddy Kalluru * this doorbell. This is applicable to IA64/Altix systems. 122116f46bf0SSudarsana Reddy Kalluru */ 122216f46bf0SSudarsana Reddy Kalluru mmiowb(); 122316f46bf0SSudarsana Reddy Kalluru 122416f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 122516f46bf0SSudarsana Reddy Kalluru if (qede_txq_has_work(txq)) 122616f46bf0SSudarsana Reddy Kalluru break; 122716f46bf0SSudarsana Reddy Kalluru usleep_range(100, 200); 122816f46bf0SSudarsana Reddy Kalluru } 122916f46bf0SSudarsana Reddy Kalluru 123016f46bf0SSudarsana Reddy Kalluru if (!qede_txq_has_work(txq)) { 123116f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Tx completion didn't happen\n"); 123216f46bf0SSudarsana Reddy Kalluru return -1; 123316f46bf0SSudarsana Reddy Kalluru } 123416f46bf0SSudarsana Reddy Kalluru 123516f46bf0SSudarsana Reddy Kalluru first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); 1236fabd545cSManish Chopra dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), 123716f46bf0SSudarsana Reddy Kalluru BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); 123816f46bf0SSudarsana Reddy Kalluru txq->sw_tx_cons++; 123916f46bf0SSudarsana Reddy Kalluru txq->sw_tx_ring[idx].skb = NULL; 124016f46bf0SSudarsana Reddy Kalluru 124116f46bf0SSudarsana Reddy Kalluru return 0; 124216f46bf0SSudarsana Reddy Kalluru } 124316f46bf0SSudarsana Reddy Kalluru 124416f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev) 124516f46bf0SSudarsana Reddy Kalluru { 124616f46bf0SSudarsana Reddy Kalluru u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len; 124716f46bf0SSudarsana Reddy Kalluru struct eth_fast_path_rx_reg_cqe *fp_cqe; 12489a4d7e86SSudarsana Reddy Kalluru struct qede_rx_queue *rxq = NULL; 124916f46bf0SSudarsana Reddy Kalluru struct sw_rx_data *sw_rx_data; 125016f46bf0SSudarsana Reddy Kalluru union eth_rx_cqe *cqe; 1251837d4eb6SSudarsana Reddy Kalluru int i, rc = 0; 125216f46bf0SSudarsana Reddy Kalluru u8 *data_ptr; 125316f46bf0SSudarsana Reddy Kalluru 12549a4d7e86SSudarsana Reddy Kalluru for_each_queue(i) { 12559a4d7e86SSudarsana Reddy Kalluru if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { 12569a4d7e86SSudarsana Reddy Kalluru rxq = edev->fp_array[i].rxq; 12579a4d7e86SSudarsana Reddy Kalluru break; 12589a4d7e86SSudarsana Reddy Kalluru } 12599a4d7e86SSudarsana Reddy Kalluru } 12609a4d7e86SSudarsana Reddy Kalluru 12619a4d7e86SSudarsana Reddy Kalluru if (!rxq) { 12629a4d7e86SSudarsana Reddy Kalluru DP_NOTICE(edev, "Rx path is not available\n"); 12639a4d7e86SSudarsana Reddy Kalluru return -1; 12649a4d7e86SSudarsana Reddy Kalluru } 12659a4d7e86SSudarsana Reddy Kalluru 126616f46bf0SSudarsana Reddy Kalluru /* The packet is expected to receive on rx-queue 0 even though RSS is 126716f46bf0SSudarsana Reddy Kalluru * enabled. This is because the queue 0 is configured as the default 126816f46bf0SSudarsana Reddy Kalluru * queue and that the loopback traffic is not IP. 126916f46bf0SSudarsana Reddy Kalluru */ 127016f46bf0SSudarsana Reddy Kalluru for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { 127116f46bf0SSudarsana Reddy Kalluru if (!qede_has_rx_work(rxq)) { 1272837d4eb6SSudarsana Reddy Kalluru usleep_range(100, 200); 1273837d4eb6SSudarsana Reddy Kalluru continue; 127416f46bf0SSudarsana Reddy Kalluru } 127516f46bf0SSudarsana Reddy Kalluru 127616f46bf0SSudarsana Reddy Kalluru hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); 127716f46bf0SSudarsana Reddy Kalluru sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); 127816f46bf0SSudarsana Reddy Kalluru 1279837d4eb6SSudarsana Reddy Kalluru /* Memory barrier to prevent the CPU from doing speculative 1280837d4eb6SSudarsana Reddy Kalluru * reads of CQE/BD before reading hw_comp_cons. If the CQE is 1281837d4eb6SSudarsana Reddy Kalluru * read before it is written by FW, then FW writes CQE and SB, 1282837d4eb6SSudarsana Reddy Kalluru * and then the CPU reads the hw_comp_cons, it will use an old 1283837d4eb6SSudarsana Reddy Kalluru * CQE. 128416f46bf0SSudarsana Reddy Kalluru */ 128516f46bf0SSudarsana Reddy Kalluru rmb(); 128616f46bf0SSudarsana Reddy Kalluru 128716f46bf0SSudarsana Reddy Kalluru /* Get the CQE from the completion ring */ 128816f46bf0SSudarsana Reddy Kalluru cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); 128916f46bf0SSudarsana Reddy Kalluru 129016f46bf0SSudarsana Reddy Kalluru /* Get the data from the SW ring */ 129116f46bf0SSudarsana Reddy Kalluru sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; 129216f46bf0SSudarsana Reddy Kalluru sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; 129316f46bf0SSudarsana Reddy Kalluru fp_cqe = &cqe->fast_path_regular; 129416f46bf0SSudarsana Reddy Kalluru len = le16_to_cpu(fp_cqe->len_on_first_bd); 129516f46bf0SSudarsana Reddy Kalluru data_ptr = (u8 *)(page_address(sw_rx_data->data) + 1296837d4eb6SSudarsana Reddy Kalluru fp_cqe->placement_offset + 1297837d4eb6SSudarsana Reddy Kalluru sw_rx_data->page_offset); 1298837d4eb6SSudarsana Reddy Kalluru if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && 1299837d4eb6SSudarsana Reddy Kalluru ether_addr_equal(data_ptr + ETH_ALEN, 1300837d4eb6SSudarsana Reddy Kalluru edev->ndev->dev_addr)) { 130116f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < len; i++) 130216f46bf0SSudarsana Reddy Kalluru if (data_ptr[i] != (unsigned char)(i & 0xff)) { 1303837d4eb6SSudarsana Reddy Kalluru rc = -1; 1304837d4eb6SSudarsana Reddy Kalluru break; 130516f46bf0SSudarsana Reddy Kalluru } 130616f46bf0SSudarsana Reddy Kalluru 130716f46bf0SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 1308837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1309837d4eb6SSudarsana Reddy Kalluru break; 1310837d4eb6SSudarsana Reddy Kalluru } 131116f46bf0SSudarsana Reddy Kalluru 1312837d4eb6SSudarsana Reddy Kalluru DP_INFO(edev, "Not the transmitted packet\n"); 1313837d4eb6SSudarsana Reddy Kalluru qede_recycle_rx_bd_ring(rxq, edev, 1); 1314837d4eb6SSudarsana Reddy Kalluru qed_chain_recycle_consumed(&rxq->rx_comp_ring); 1315837d4eb6SSudarsana Reddy Kalluru } 1316837d4eb6SSudarsana Reddy Kalluru 1317837d4eb6SSudarsana Reddy Kalluru if (i == QEDE_SELFTEST_POLL_COUNT) { 1318837d4eb6SSudarsana Reddy Kalluru DP_NOTICE(edev, "Failed to receive the traffic\n"); 1319837d4eb6SSudarsana Reddy Kalluru return -1; 1320837d4eb6SSudarsana Reddy Kalluru } 1321837d4eb6SSudarsana Reddy Kalluru 1322837d4eb6SSudarsana Reddy Kalluru qede_update_rx_prod(edev, rxq); 1323837d4eb6SSudarsana Reddy Kalluru 1324837d4eb6SSudarsana Reddy Kalluru return rc; 132516f46bf0SSudarsana Reddy Kalluru } 132616f46bf0SSudarsana Reddy Kalluru 132716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) 132816f46bf0SSudarsana Reddy Kalluru { 132916f46bf0SSudarsana Reddy Kalluru struct qed_link_params link_params; 133016f46bf0SSudarsana Reddy Kalluru struct sk_buff *skb = NULL; 133116f46bf0SSudarsana Reddy Kalluru int rc = 0, i; 133216f46bf0SSudarsana Reddy Kalluru u32 pkt_size; 133316f46bf0SSudarsana Reddy Kalluru u8 *packet; 133416f46bf0SSudarsana Reddy Kalluru 133516f46bf0SSudarsana Reddy Kalluru if (!netif_running(edev->ndev)) { 133616f46bf0SSudarsana Reddy Kalluru DP_NOTICE(edev, "Interface is down\n"); 133716f46bf0SSudarsana Reddy Kalluru return -EINVAL; 133816f46bf0SSudarsana Reddy Kalluru } 133916f46bf0SSudarsana Reddy Kalluru 134016f46bf0SSudarsana Reddy Kalluru qede_netif_stop(edev); 134116f46bf0SSudarsana Reddy Kalluru 134216f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Loopback mode */ 134316f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 134416f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 134516f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 134616f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = loopback_mode; 134716f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 134816f46bf0SSudarsana Reddy Kalluru 134916f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 135016f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 135116f46bf0SSudarsana Reddy Kalluru 135216f46bf0SSudarsana Reddy Kalluru /* prepare the loopback packet */ 135316f46bf0SSudarsana Reddy Kalluru pkt_size = edev->ndev->mtu + ETH_HLEN; 135416f46bf0SSudarsana Reddy Kalluru 135516f46bf0SSudarsana Reddy Kalluru skb = netdev_alloc_skb(edev->ndev, pkt_size); 135616f46bf0SSudarsana Reddy Kalluru if (!skb) { 135716f46bf0SSudarsana Reddy Kalluru DP_INFO(edev, "Can't allocate skb\n"); 135816f46bf0SSudarsana Reddy Kalluru rc = -ENOMEM; 135916f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 136016f46bf0SSudarsana Reddy Kalluru } 136116f46bf0SSudarsana Reddy Kalluru packet = skb_put(skb, pkt_size); 136216f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet, edev->ndev->dev_addr); 136316f46bf0SSudarsana Reddy Kalluru ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr); 136416f46bf0SSudarsana Reddy Kalluru memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN))); 136516f46bf0SSudarsana Reddy Kalluru for (i = ETH_HLEN; i < pkt_size; i++) 136616f46bf0SSudarsana Reddy Kalluru packet[i] = (unsigned char)(i & 0xff); 136716f46bf0SSudarsana Reddy Kalluru 136816f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_transmit_traffic(edev, skb); 136916f46bf0SSudarsana Reddy Kalluru if (rc) 137016f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 137116f46bf0SSudarsana Reddy Kalluru 137216f46bf0SSudarsana Reddy Kalluru rc = qede_selftest_receive_traffic(edev); 137316f46bf0SSudarsana Reddy Kalluru if (rc) 137416f46bf0SSudarsana Reddy Kalluru goto test_loopback_exit; 137516f46bf0SSudarsana Reddy Kalluru 137616f46bf0SSudarsana Reddy Kalluru DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n"); 137716f46bf0SSudarsana Reddy Kalluru 137816f46bf0SSudarsana Reddy Kalluru test_loopback_exit: 137916f46bf0SSudarsana Reddy Kalluru dev_kfree_skb(skb); 138016f46bf0SSudarsana Reddy Kalluru 138116f46bf0SSudarsana Reddy Kalluru /* Bring up the link in Normal mode */ 138216f46bf0SSudarsana Reddy Kalluru memset(&link_params, 0, sizeof(link_params)); 138316f46bf0SSudarsana Reddy Kalluru link_params.link_up = true; 138416f46bf0SSudarsana Reddy Kalluru link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE; 138516f46bf0SSudarsana Reddy Kalluru link_params.loopback_mode = QED_LINK_LOOPBACK_NONE; 138616f46bf0SSudarsana Reddy Kalluru edev->ops->common->set_link(edev->cdev, &link_params); 138716f46bf0SSudarsana Reddy Kalluru 138816f46bf0SSudarsana Reddy Kalluru /* Wait for loopback configuration to apply */ 138916f46bf0SSudarsana Reddy Kalluru msleep_interruptible(500); 139016f46bf0SSudarsana Reddy Kalluru 139116f46bf0SSudarsana Reddy Kalluru qede_netif_start(edev); 139216f46bf0SSudarsana Reddy Kalluru 139316f46bf0SSudarsana Reddy Kalluru return rc; 139416f46bf0SSudarsana Reddy Kalluru } 139516f46bf0SSudarsana Reddy Kalluru 13963044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev, 13973044a02eSSudarsana Reddy Kalluru struct ethtool_test *etest, u64 *buf) 13983044a02eSSudarsana Reddy Kalluru { 13993044a02eSSudarsana Reddy Kalluru struct qede_dev *edev = netdev_priv(dev); 14003044a02eSSudarsana Reddy Kalluru 14013044a02eSSudarsana Reddy Kalluru DP_VERBOSE(edev, QED_MSG_DEBUG, 14023044a02eSSudarsana Reddy Kalluru "Self-test command parameters: offline = %d, external_lb = %d\n", 14033044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_OFFLINE), 14043044a02eSSudarsana Reddy Kalluru (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2); 14053044a02eSSudarsana Reddy Kalluru 14063044a02eSSudarsana Reddy Kalluru memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX); 14073044a02eSSudarsana Reddy Kalluru 140816f46bf0SSudarsana Reddy Kalluru if (etest->flags & ETH_TEST_FL_OFFLINE) { 140916f46bf0SSudarsana Reddy Kalluru if (qede_selftest_run_loopback(edev, 141016f46bf0SSudarsana Reddy Kalluru QED_LINK_LOOPBACK_INT_PHY)) { 141116f46bf0SSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1; 141216f46bf0SSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 141316f46bf0SSudarsana Reddy Kalluru } 141416f46bf0SSudarsana Reddy Kalluru } 141516f46bf0SSudarsana Reddy Kalluru 14163044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) { 14173044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1; 14183044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14193044a02eSSudarsana Reddy Kalluru } 14203044a02eSSudarsana Reddy Kalluru 14213044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_memory(edev->cdev)) { 14223044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_MEMORY_TEST] = 1; 14233044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14243044a02eSSudarsana Reddy Kalluru } 14253044a02eSSudarsana Reddy Kalluru 14263044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_register(edev->cdev)) { 14273044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_REGISTER_TEST] = 1; 14283044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14293044a02eSSudarsana Reddy Kalluru } 14303044a02eSSudarsana Reddy Kalluru 14313044a02eSSudarsana Reddy Kalluru if (edev->ops->common->selftest->selftest_clock(edev->cdev)) { 14323044a02eSSudarsana Reddy Kalluru buf[QEDE_ETHTOOL_CLOCK_TEST] = 1; 14333044a02eSSudarsana Reddy Kalluru etest->flags |= ETH_TEST_FL_FAILED; 14343044a02eSSudarsana Reddy Kalluru } 14357a4b21b7SMintz, Yuval 14367a4b21b7SMintz, Yuval if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) { 14377a4b21b7SMintz, Yuval buf[QEDE_ETHTOOL_NVRAM_TEST] = 1; 14387a4b21b7SMintz, Yuval etest->flags |= ETH_TEST_FL_FAILED; 14397a4b21b7SMintz, Yuval } 14403044a02eSSudarsana Reddy Kalluru } 14413044a02eSSudarsana Reddy Kalluru 14423d789994SManish Chopra static int qede_set_tunable(struct net_device *dev, 14433d789994SManish Chopra const struct ethtool_tunable *tuna, 14443d789994SManish Chopra const void *data) 14453d789994SManish Chopra { 14463d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14473d789994SManish Chopra u32 val; 14483d789994SManish Chopra 14493d789994SManish Chopra switch (tuna->id) { 14503d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14513d789994SManish Chopra val = *(u32 *)data; 14523d789994SManish Chopra if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) { 14533d789994SManish Chopra DP_VERBOSE(edev, QED_MSG_DEBUG, 14543d789994SManish Chopra "Invalid rx copy break value, range is [%u, %u]", 14553d789994SManish Chopra QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE); 14563d789994SManish Chopra return -EINVAL; 14573d789994SManish Chopra } 14583d789994SManish Chopra 14593d789994SManish Chopra edev->rx_copybreak = *(u32 *)data; 14603d789994SManish Chopra break; 14613d789994SManish Chopra default: 14623d789994SManish Chopra return -EOPNOTSUPP; 14633d789994SManish Chopra } 14643d789994SManish Chopra 14653d789994SManish Chopra return 0; 14663d789994SManish Chopra } 14673d789994SManish Chopra 14683d789994SManish Chopra static int qede_get_tunable(struct net_device *dev, 14693d789994SManish Chopra const struct ethtool_tunable *tuna, void *data) 14703d789994SManish Chopra { 14713d789994SManish Chopra struct qede_dev *edev = netdev_priv(dev); 14723d789994SManish Chopra 14733d789994SManish Chopra switch (tuna->id) { 14743d789994SManish Chopra case ETHTOOL_RX_COPYBREAK: 14753d789994SManish Chopra *(u32 *)data = edev->rx_copybreak; 14763d789994SManish Chopra break; 14773d789994SManish Chopra default: 14783d789994SManish Chopra return -EOPNOTSUPP; 14793d789994SManish Chopra } 14803d789994SManish Chopra 14813d789994SManish Chopra return 0; 14823d789994SManish Chopra } 14833d789994SManish Chopra 1484133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = { 1485054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1486054c67d1SSudarsana Reddy Kalluru .set_link_ksettings = qede_set_link_ksettings, 1487133fac0eSSudarsana Kalluru .get_drvinfo = qede_get_drvinfo, 1488e0971c83STomer Tayar .get_regs_len = qede_get_regs_len, 1489e0971c83STomer Tayar .get_regs = qede_get_regs, 149014d39648SMintz, Yuval .get_wol = qede_get_wol, 149114d39648SMintz, Yuval .set_wol = qede_set_wol, 1492133fac0eSSudarsana Kalluru .get_msglevel = qede_get_msglevel, 1493133fac0eSSudarsana Kalluru .set_msglevel = qede_set_msglevel, 149432a7a570SSudarsana Kalluru .nway_reset = qede_nway_reset, 1495133fac0eSSudarsana Kalluru .get_link = qede_get_link, 1496d552fa84SSudarsana Reddy Kalluru .get_coalesce = qede_get_coalesce, 1497d552fa84SSudarsana Reddy Kalluru .set_coalesce = qede_set_coalesce, 149801ef7e05SSudarsana Kalluru .get_ringparam = qede_get_ringparam, 149901ef7e05SSudarsana Kalluru .set_ringparam = qede_set_ringparam, 15000f7db144SSudarsana Kalluru .get_pauseparam = qede_get_pauseparam, 15010f7db144SSudarsana Kalluru .set_pauseparam = qede_set_pauseparam, 1502133fac0eSSudarsana Kalluru .get_strings = qede_get_strings, 15033d971cbdSSudarsana Kalluru .set_phys_id = qede_set_phys_id, 1504133fac0eSSudarsana Kalluru .get_ethtool_stats = qede_get_ethtool_stats, 1505f3e72109SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1506133fac0eSSudarsana Kalluru .get_sset_count = qede_get_sset_count, 1507961acdeaSSudarsana Reddy Kalluru .get_rxnfc = qede_get_rxnfc, 1508961acdeaSSudarsana Reddy Kalluru .set_rxnfc = qede_set_rxnfc, 1509961acdeaSSudarsana Reddy Kalluru .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1510961acdeaSSudarsana Reddy Kalluru .get_rxfh_key_size = qede_get_rxfh_key_size, 1511961acdeaSSudarsana Reddy Kalluru .get_rxfh = qede_get_rxfh, 1512961acdeaSSudarsana Reddy Kalluru .set_rxfh = qede_set_rxfh, 15138edf049dSSudarsana Kalluru .get_channels = qede_get_channels, 15148edf049dSSudarsana Kalluru .set_channels = qede_set_channels, 15153044a02eSSudarsana Reddy Kalluru .self_test = qede_self_test, 15163d789994SManish Chopra .get_tunable = qede_get_tunable, 15173d789994SManish Chopra .set_tunable = qede_set_tunable, 1518133fac0eSSudarsana Kalluru }; 1519133fac0eSSudarsana Kalluru 1520fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = { 1521054c67d1SSudarsana Reddy Kalluru .get_link_ksettings = qede_get_link_ksettings, 1522fefb0202SYuval Mintz .get_drvinfo = qede_get_drvinfo, 1523fefb0202SYuval Mintz .get_msglevel = qede_get_msglevel, 1524fefb0202SYuval Mintz .set_msglevel = qede_set_msglevel, 1525fefb0202SYuval Mintz .get_link = qede_get_link, 1526fefb0202SYuval Mintz .get_ringparam = qede_get_ringparam, 1527fefb0202SYuval Mintz .set_ringparam = qede_set_ringparam, 1528fefb0202SYuval Mintz .get_strings = qede_get_strings, 1529fefb0202SYuval Mintz .get_ethtool_stats = qede_get_ethtool_stats, 1530fefb0202SYuval Mintz .get_priv_flags = qede_get_priv_flags, 1531fefb0202SYuval Mintz .get_sset_count = qede_get_sset_count, 1532fefb0202SYuval Mintz .get_rxnfc = qede_get_rxnfc, 1533fefb0202SYuval Mintz .set_rxnfc = qede_set_rxnfc, 1534fefb0202SYuval Mintz .get_rxfh_indir_size = qede_get_rxfh_indir_size, 1535fefb0202SYuval Mintz .get_rxfh_key_size = qede_get_rxfh_key_size, 1536fefb0202SYuval Mintz .get_rxfh = qede_get_rxfh, 1537fefb0202SYuval Mintz .set_rxfh = qede_set_rxfh, 1538fefb0202SYuval Mintz .get_channels = qede_get_channels, 1539fefb0202SYuval Mintz .set_channels = qede_set_channels, 15403d789994SManish Chopra .get_tunable = qede_get_tunable, 15413d789994SManish Chopra .set_tunable = qede_set_tunable, 1542fefb0202SYuval Mintz }; 1543fefb0202SYuval Mintz 1544133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev) 1545133fac0eSSudarsana Kalluru { 1546fefb0202SYuval Mintz struct qede_dev *edev = netdev_priv(dev); 1547fefb0202SYuval Mintz 1548fefb0202SYuval Mintz if (IS_VF(edev)) 1549fefb0202SYuval Mintz dev->ethtool_ops = &qede_vf_ethtool_ops; 1550fefb0202SYuval Mintz else 1551133fac0eSSudarsana Kalluru dev->ethtool_ops = &qede_ethtool_ops; 1552133fac0eSSudarsana Kalluru } 1553