18c5ad0daSSasha Neftin // SPDX-License-Identifier: GPL-2.0
28c5ad0daSSasha Neftin /* Copyright (c) 2018 Intel Corporation */
38c5ad0daSSasha Neftin
48c5ad0daSSasha Neftin /* ethtool support for igc */
56245c848SSasha Neftin #include <linux/if_vlan.h>
68c5ad0daSSasha Neftin #include <linux/pm_runtime.h>
793ec439aSSasha Neftin #include <linux/mdio.h>
88c5ad0daSSasha Neftin
98c5ad0daSSasha Neftin #include "igc.h"
10f026d8caSVitaly Lifshits #include "igc_diag.h"
118c5ad0daSSasha Neftin
1236b9fea6SSasha Neftin /* forward declaration */
1336b9fea6SSasha Neftin struct igc_stats {
1436b9fea6SSasha Neftin char stat_string[ETH_GSTRING_LEN];
1536b9fea6SSasha Neftin int sizeof_stat;
1636b9fea6SSasha Neftin int stat_offset;
1736b9fea6SSasha Neftin };
1836b9fea6SSasha Neftin
1936b9fea6SSasha Neftin #define IGC_STAT(_name, _stat) { \
2036b9fea6SSasha Neftin .stat_string = _name, \
21c593642cSPankaj Bharadiya .sizeof_stat = sizeof_field(struct igc_adapter, _stat), \
2236b9fea6SSasha Neftin .stat_offset = offsetof(struct igc_adapter, _stat) \
2336b9fea6SSasha Neftin }
2436b9fea6SSasha Neftin
2536b9fea6SSasha Neftin static const struct igc_stats igc_gstrings_stats[] = {
2636b9fea6SSasha Neftin IGC_STAT("rx_packets", stats.gprc),
2736b9fea6SSasha Neftin IGC_STAT("tx_packets", stats.gptc),
2836b9fea6SSasha Neftin IGC_STAT("rx_bytes", stats.gorc),
2936b9fea6SSasha Neftin IGC_STAT("tx_bytes", stats.gotc),
3036b9fea6SSasha Neftin IGC_STAT("rx_broadcast", stats.bprc),
3136b9fea6SSasha Neftin IGC_STAT("tx_broadcast", stats.bptc),
3236b9fea6SSasha Neftin IGC_STAT("rx_multicast", stats.mprc),
3336b9fea6SSasha Neftin IGC_STAT("tx_multicast", stats.mptc),
3436b9fea6SSasha Neftin IGC_STAT("multicast", stats.mprc),
3536b9fea6SSasha Neftin IGC_STAT("collisions", stats.colc),
3636b9fea6SSasha Neftin IGC_STAT("rx_crc_errors", stats.crcerrs),
3736b9fea6SSasha Neftin IGC_STAT("rx_no_buffer_count", stats.rnbc),
3836b9fea6SSasha Neftin IGC_STAT("rx_missed_errors", stats.mpc),
3936b9fea6SSasha Neftin IGC_STAT("tx_aborted_errors", stats.ecol),
4036b9fea6SSasha Neftin IGC_STAT("tx_carrier_errors", stats.tncrs),
4136b9fea6SSasha Neftin IGC_STAT("tx_window_errors", stats.latecol),
4236b9fea6SSasha Neftin IGC_STAT("tx_abort_late_coll", stats.latecol),
4336b9fea6SSasha Neftin IGC_STAT("tx_deferred_ok", stats.dc),
4436b9fea6SSasha Neftin IGC_STAT("tx_single_coll_ok", stats.scc),
4536b9fea6SSasha Neftin IGC_STAT("tx_multi_coll_ok", stats.mcc),
4636b9fea6SSasha Neftin IGC_STAT("tx_timeout_count", tx_timeout_count),
4736b9fea6SSasha Neftin IGC_STAT("rx_long_length_errors", stats.roc),
4836b9fea6SSasha Neftin IGC_STAT("rx_short_length_errors", stats.ruc),
4936b9fea6SSasha Neftin IGC_STAT("rx_align_errors", stats.algnerrc),
5036b9fea6SSasha Neftin IGC_STAT("tx_tcp_seg_good", stats.tsctc),
5136b9fea6SSasha Neftin IGC_STAT("tx_tcp_seg_failed", stats.tsctfc),
5236b9fea6SSasha Neftin IGC_STAT("rx_flow_control_xon", stats.xonrxc),
5336b9fea6SSasha Neftin IGC_STAT("rx_flow_control_xoff", stats.xoffrxc),
5436b9fea6SSasha Neftin IGC_STAT("tx_flow_control_xon", stats.xontxc),
5536b9fea6SSasha Neftin IGC_STAT("tx_flow_control_xoff", stats.xofftxc),
5636b9fea6SSasha Neftin IGC_STAT("rx_long_byte_count", stats.gorc),
5736b9fea6SSasha Neftin IGC_STAT("tx_dma_out_of_sync", stats.doosync),
5836b9fea6SSasha Neftin IGC_STAT("tx_smbus", stats.mgptc),
5936b9fea6SSasha Neftin IGC_STAT("rx_smbus", stats.mgprc),
6036b9fea6SSasha Neftin IGC_STAT("dropped_smbus", stats.mgpdc),
6136b9fea6SSasha Neftin IGC_STAT("os2bmc_rx_by_bmc", stats.o2bgptc),
6236b9fea6SSasha Neftin IGC_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
6336b9fea6SSasha Neftin IGC_STAT("os2bmc_tx_by_host", stats.o2bspc),
6436b9fea6SSasha Neftin IGC_STAT("os2bmc_rx_by_host", stats.b2ogprc),
6536b9fea6SSasha Neftin IGC_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
6636b9fea6SSasha Neftin IGC_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
6736b9fea6SSasha Neftin IGC_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
681feaf60fSSasha Neftin IGC_STAT("tx_lpi_counter", stats.tlpic),
691feaf60fSSasha Neftin IGC_STAT("rx_lpi_counter", stats.rlpic),
70ae4fe469SMuhammad Husaini Zulkifli IGC_STAT("qbv_config_change_errors", qbv_config_change_errors),
7136b9fea6SSasha Neftin };
7236b9fea6SSasha Neftin
7336b9fea6SSasha Neftin #define IGC_NETDEV_STAT(_net_stat) { \
7436b9fea6SSasha Neftin .stat_string = __stringify(_net_stat), \
75c593642cSPankaj Bharadiya .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \
7636b9fea6SSasha Neftin .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
7736b9fea6SSasha Neftin }
7836b9fea6SSasha Neftin
7936b9fea6SSasha Neftin static const struct igc_stats igc_gstrings_net_stats[] = {
8036b9fea6SSasha Neftin IGC_NETDEV_STAT(rx_errors),
8136b9fea6SSasha Neftin IGC_NETDEV_STAT(tx_errors),
8236b9fea6SSasha Neftin IGC_NETDEV_STAT(tx_dropped),
8336b9fea6SSasha Neftin IGC_NETDEV_STAT(rx_length_errors),
8436b9fea6SSasha Neftin IGC_NETDEV_STAT(rx_over_errors),
8536b9fea6SSasha Neftin IGC_NETDEV_STAT(rx_frame_errors),
8636b9fea6SSasha Neftin IGC_NETDEV_STAT(rx_fifo_errors),
8736b9fea6SSasha Neftin IGC_NETDEV_STAT(tx_fifo_errors),
8836b9fea6SSasha Neftin IGC_NETDEV_STAT(tx_heartbeat_errors)
8936b9fea6SSasha Neftin };
9036b9fea6SSasha Neftin
9136b9fea6SSasha Neftin enum igc_diagnostics_results {
9236b9fea6SSasha Neftin TEST_REG = 0,
9336b9fea6SSasha Neftin TEST_EEP,
9436b9fea6SSasha Neftin TEST_IRQ,
9536b9fea6SSasha Neftin TEST_LOOP,
9636b9fea6SSasha Neftin TEST_LINK
9736b9fea6SSasha Neftin };
9836b9fea6SSasha Neftin
9936b9fea6SSasha Neftin static const char igc_gstrings_test[][ETH_GSTRING_LEN] = {
10036b9fea6SSasha Neftin [TEST_REG] = "Register test (offline)",
10136b9fea6SSasha Neftin [TEST_EEP] = "Eeprom test (offline)",
10236b9fea6SSasha Neftin [TEST_IRQ] = "Interrupt test (offline)",
10336b9fea6SSasha Neftin [TEST_LOOP] = "Loopback test (offline)",
10436b9fea6SSasha Neftin [TEST_LINK] = "Link test (on/offline)"
10536b9fea6SSasha Neftin };
10636b9fea6SSasha Neftin
10736b9fea6SSasha Neftin #define IGC_TEST_LEN (sizeof(igc_gstrings_test) / ETH_GSTRING_LEN)
10836b9fea6SSasha Neftin
10936b9fea6SSasha Neftin #define IGC_GLOBAL_STATS_LEN \
11036b9fea6SSasha Neftin (sizeof(igc_gstrings_stats) / sizeof(struct igc_stats))
11136b9fea6SSasha Neftin #define IGC_NETDEV_STATS_LEN \
11236b9fea6SSasha Neftin (sizeof(igc_gstrings_net_stats) / sizeof(struct igc_stats))
11336b9fea6SSasha Neftin #define IGC_RX_QUEUE_STATS_LEN \
11436b9fea6SSasha Neftin (sizeof(struct igc_rx_queue_stats) / sizeof(u64))
11536b9fea6SSasha Neftin #define IGC_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */
11636b9fea6SSasha Neftin #define IGC_QUEUE_STATS_LEN \
11736b9fea6SSasha Neftin ((((struct igc_adapter *)netdev_priv(netdev))->num_rx_queues * \
11836b9fea6SSasha Neftin IGC_RX_QUEUE_STATS_LEN) + \
11936b9fea6SSasha Neftin (((struct igc_adapter *)netdev_priv(netdev))->num_tx_queues * \
12036b9fea6SSasha Neftin IGC_TX_QUEUE_STATS_LEN))
12136b9fea6SSasha Neftin #define IGC_STATS_LEN \
12236b9fea6SSasha Neftin (IGC_GLOBAL_STATS_LEN + IGC_NETDEV_STATS_LEN + IGC_QUEUE_STATS_LEN)
12336b9fea6SSasha Neftin
1248c5ad0daSSasha Neftin static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = {
1258c5ad0daSSasha Neftin #define IGC_PRIV_FLAGS_LEGACY_RX BIT(0)
1268c5ad0daSSasha Neftin "legacy-rx",
1278c5ad0daSSasha Neftin };
1288c5ad0daSSasha Neftin
1298c5ad0daSSasha Neftin #define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings)
1308c5ad0daSSasha Neftin
igc_ethtool_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)1317df76bd1SAndre Guedes static void igc_ethtool_get_drvinfo(struct net_device *netdev,
1328c5ad0daSSasha Neftin struct ethtool_drvinfo *drvinfo)
1338c5ad0daSSasha Neftin {
1348c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
13501bb6129SSasha Neftin struct igc_hw *hw = &adapter->hw;
13601bb6129SSasha Neftin u16 nvm_version = 0;
13794f794d1SSasha Neftin u16 gphy_version;
1388c5ad0daSSasha Neftin
13901bb6129SSasha Neftin strscpy(drvinfo->driver, igc_driver_name, sizeof(drvinfo->driver));
1408c5ad0daSSasha Neftin
14101bb6129SSasha Neftin /* NVM image version is reported as firmware version for i225 device */
14201bb6129SSasha Neftin hw->nvm.ops.read(hw, IGC_NVM_DEV_STARTER, 1, &nvm_version);
14301bb6129SSasha Neftin
14494f794d1SSasha Neftin /* gPHY firmware version is reported as PHY FW version */
14594f794d1SSasha Neftin gphy_version = igc_read_phy_fw_version(hw);
14694f794d1SSasha Neftin
14701bb6129SSasha Neftin scnprintf(adapter->fw_version,
14801bb6129SSasha Neftin sizeof(adapter->fw_version),
14994f794d1SSasha Neftin "%x:%x",
15094f794d1SSasha Neftin nvm_version,
15194f794d1SSasha Neftin gphy_version);
15201bb6129SSasha Neftin
15301bb6129SSasha Neftin strscpy(drvinfo->fw_version, adapter->fw_version,
15401bb6129SSasha Neftin sizeof(drvinfo->fw_version));
15501bb6129SSasha Neftin
156ed443cdfSSasha Neftin strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
1578c5ad0daSSasha Neftin sizeof(drvinfo->bus_info));
1588c5ad0daSSasha Neftin
1598c5ad0daSSasha Neftin drvinfo->n_priv_flags = IGC_PRIV_FLAGS_STR_LEN;
1608c5ad0daSSasha Neftin }
1618c5ad0daSSasha Neftin
igc_ethtool_get_regs_len(struct net_device * netdev)1627df76bd1SAndre Guedes static int igc_ethtool_get_regs_len(struct net_device *netdev)
1638c5ad0daSSasha Neftin {
1648c5ad0daSSasha Neftin return IGC_REGS_LEN * sizeof(u32);
1658c5ad0daSSasha Neftin }
1668c5ad0daSSasha Neftin
igc_ethtool_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * p)1677df76bd1SAndre Guedes static void igc_ethtool_get_regs(struct net_device *netdev,
1688c5ad0daSSasha Neftin struct ethtool_regs *regs, void *p)
1698c5ad0daSSasha Neftin {
1708c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
1718c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
1728c5ad0daSSasha Neftin u32 *regs_buff = p;
1738c5ad0daSSasha Neftin u8 i;
1748c5ad0daSSasha Neftin
1758c5ad0daSSasha Neftin memset(p, 0, IGC_REGS_LEN * sizeof(u32));
1768c5ad0daSSasha Neftin
177b8a61ea1SAndre Guedes regs->version = (2u << 24) | (hw->revision_id << 16) | hw->device_id;
1788c5ad0daSSasha Neftin
1798c5ad0daSSasha Neftin /* General Registers */
1808c5ad0daSSasha Neftin regs_buff[0] = rd32(IGC_CTRL);
1818c5ad0daSSasha Neftin regs_buff[1] = rd32(IGC_STATUS);
1828c5ad0daSSasha Neftin regs_buff[2] = rd32(IGC_CTRL_EXT);
1838c5ad0daSSasha Neftin regs_buff[3] = rd32(IGC_MDIC);
1848c5ad0daSSasha Neftin regs_buff[4] = rd32(IGC_CONNSW);
1858c5ad0daSSasha Neftin
1868c5ad0daSSasha Neftin /* NVM Register */
1878c5ad0daSSasha Neftin regs_buff[5] = rd32(IGC_EECD);
1888c5ad0daSSasha Neftin
1898c5ad0daSSasha Neftin /* Interrupt */
1908c5ad0daSSasha Neftin /* Reading EICS for EICR because they read the
1918c5ad0daSSasha Neftin * same but EICS does not clear on read
1928c5ad0daSSasha Neftin */
1938c5ad0daSSasha Neftin regs_buff[6] = rd32(IGC_EICS);
1948c5ad0daSSasha Neftin regs_buff[7] = rd32(IGC_EICS);
1958c5ad0daSSasha Neftin regs_buff[8] = rd32(IGC_EIMS);
1968c5ad0daSSasha Neftin regs_buff[9] = rd32(IGC_EIMC);
1978c5ad0daSSasha Neftin regs_buff[10] = rd32(IGC_EIAC);
1988c5ad0daSSasha Neftin regs_buff[11] = rd32(IGC_EIAM);
1998c5ad0daSSasha Neftin /* Reading ICS for ICR because they read the
2008c5ad0daSSasha Neftin * same but ICS does not clear on read
2018c5ad0daSSasha Neftin */
2028c5ad0daSSasha Neftin regs_buff[12] = rd32(IGC_ICS);
2038c5ad0daSSasha Neftin regs_buff[13] = rd32(IGC_ICS);
2048c5ad0daSSasha Neftin regs_buff[14] = rd32(IGC_IMS);
2058c5ad0daSSasha Neftin regs_buff[15] = rd32(IGC_IMC);
2068c5ad0daSSasha Neftin regs_buff[16] = rd32(IGC_IAC);
2078c5ad0daSSasha Neftin regs_buff[17] = rd32(IGC_IAM);
2088c5ad0daSSasha Neftin
2098c5ad0daSSasha Neftin /* Flow Control */
2108c5ad0daSSasha Neftin regs_buff[18] = rd32(IGC_FCAL);
2118c5ad0daSSasha Neftin regs_buff[19] = rd32(IGC_FCAH);
2128c5ad0daSSasha Neftin regs_buff[20] = rd32(IGC_FCTTV);
2138c5ad0daSSasha Neftin regs_buff[21] = rd32(IGC_FCRTL);
2148c5ad0daSSasha Neftin regs_buff[22] = rd32(IGC_FCRTH);
2158c5ad0daSSasha Neftin regs_buff[23] = rd32(IGC_FCRTV);
2168c5ad0daSSasha Neftin
2178c5ad0daSSasha Neftin /* Receive */
2188c5ad0daSSasha Neftin regs_buff[24] = rd32(IGC_RCTL);
2198c5ad0daSSasha Neftin regs_buff[25] = rd32(IGC_RXCSUM);
2208c5ad0daSSasha Neftin regs_buff[26] = rd32(IGC_RLPML);
2218c5ad0daSSasha Neftin regs_buff[27] = rd32(IGC_RFCTL);
2228c5ad0daSSasha Neftin
2238c5ad0daSSasha Neftin /* Transmit */
2248c5ad0daSSasha Neftin regs_buff[28] = rd32(IGC_TCTL);
2258c5ad0daSSasha Neftin regs_buff[29] = rd32(IGC_TIPG);
2268c5ad0daSSasha Neftin
2278c5ad0daSSasha Neftin /* Wake Up */
2288c5ad0daSSasha Neftin
2298c5ad0daSSasha Neftin /* MAC */
2308c5ad0daSSasha Neftin
2318c5ad0daSSasha Neftin /* Statistics */
2328c5ad0daSSasha Neftin regs_buff[30] = adapter->stats.crcerrs;
2338c5ad0daSSasha Neftin regs_buff[31] = adapter->stats.algnerrc;
2348c5ad0daSSasha Neftin regs_buff[32] = adapter->stats.symerrs;
2358c5ad0daSSasha Neftin regs_buff[33] = adapter->stats.rxerrc;
2368c5ad0daSSasha Neftin regs_buff[34] = adapter->stats.mpc;
2378c5ad0daSSasha Neftin regs_buff[35] = adapter->stats.scc;
2388c5ad0daSSasha Neftin regs_buff[36] = adapter->stats.ecol;
2398c5ad0daSSasha Neftin regs_buff[37] = adapter->stats.mcc;
2408c5ad0daSSasha Neftin regs_buff[38] = adapter->stats.latecol;
2418c5ad0daSSasha Neftin regs_buff[39] = adapter->stats.colc;
2428c5ad0daSSasha Neftin regs_buff[40] = adapter->stats.dc;
2438c5ad0daSSasha Neftin regs_buff[41] = adapter->stats.tncrs;
2448c5ad0daSSasha Neftin regs_buff[42] = adapter->stats.sec;
2458c5ad0daSSasha Neftin regs_buff[43] = adapter->stats.htdpmc;
2468c5ad0daSSasha Neftin regs_buff[44] = adapter->stats.rlec;
2478c5ad0daSSasha Neftin regs_buff[45] = adapter->stats.xonrxc;
2488c5ad0daSSasha Neftin regs_buff[46] = adapter->stats.xontxc;
2498c5ad0daSSasha Neftin regs_buff[47] = adapter->stats.xoffrxc;
2508c5ad0daSSasha Neftin regs_buff[48] = adapter->stats.xofftxc;
2518c5ad0daSSasha Neftin regs_buff[49] = adapter->stats.fcruc;
2528c5ad0daSSasha Neftin regs_buff[50] = adapter->stats.prc64;
2538c5ad0daSSasha Neftin regs_buff[51] = adapter->stats.prc127;
2548c5ad0daSSasha Neftin regs_buff[52] = adapter->stats.prc255;
2558c5ad0daSSasha Neftin regs_buff[53] = adapter->stats.prc511;
2568c5ad0daSSasha Neftin regs_buff[54] = adapter->stats.prc1023;
2578c5ad0daSSasha Neftin regs_buff[55] = adapter->stats.prc1522;
2588c5ad0daSSasha Neftin regs_buff[56] = adapter->stats.gprc;
2598c5ad0daSSasha Neftin regs_buff[57] = adapter->stats.bprc;
2608c5ad0daSSasha Neftin regs_buff[58] = adapter->stats.mprc;
2618c5ad0daSSasha Neftin regs_buff[59] = adapter->stats.gptc;
2628c5ad0daSSasha Neftin regs_buff[60] = adapter->stats.gorc;
2638c5ad0daSSasha Neftin regs_buff[61] = adapter->stats.gotc;
2648c5ad0daSSasha Neftin regs_buff[62] = adapter->stats.rnbc;
2658c5ad0daSSasha Neftin regs_buff[63] = adapter->stats.ruc;
2668c5ad0daSSasha Neftin regs_buff[64] = adapter->stats.rfc;
2678c5ad0daSSasha Neftin regs_buff[65] = adapter->stats.roc;
2688c5ad0daSSasha Neftin regs_buff[66] = adapter->stats.rjc;
2698c5ad0daSSasha Neftin regs_buff[67] = adapter->stats.mgprc;
2708c5ad0daSSasha Neftin regs_buff[68] = adapter->stats.mgpdc;
2718c5ad0daSSasha Neftin regs_buff[69] = adapter->stats.mgptc;
2728c5ad0daSSasha Neftin regs_buff[70] = adapter->stats.tor;
2738c5ad0daSSasha Neftin regs_buff[71] = adapter->stats.tot;
2748c5ad0daSSasha Neftin regs_buff[72] = adapter->stats.tpr;
2758c5ad0daSSasha Neftin regs_buff[73] = adapter->stats.tpt;
2768c5ad0daSSasha Neftin regs_buff[74] = adapter->stats.ptc64;
2778c5ad0daSSasha Neftin regs_buff[75] = adapter->stats.ptc127;
2788c5ad0daSSasha Neftin regs_buff[76] = adapter->stats.ptc255;
2798c5ad0daSSasha Neftin regs_buff[77] = adapter->stats.ptc511;
2808c5ad0daSSasha Neftin regs_buff[78] = adapter->stats.ptc1023;
2818c5ad0daSSasha Neftin regs_buff[79] = adapter->stats.ptc1522;
2828c5ad0daSSasha Neftin regs_buff[80] = adapter->stats.mptc;
2838c5ad0daSSasha Neftin regs_buff[81] = adapter->stats.bptc;
2848c5ad0daSSasha Neftin regs_buff[82] = adapter->stats.tsctc;
2858c5ad0daSSasha Neftin regs_buff[83] = adapter->stats.iac;
2868c5ad0daSSasha Neftin regs_buff[84] = adapter->stats.rpthc;
2878c5ad0daSSasha Neftin regs_buff[85] = adapter->stats.hgptc;
2888c5ad0daSSasha Neftin regs_buff[86] = adapter->stats.hgorc;
2898c5ad0daSSasha Neftin regs_buff[87] = adapter->stats.hgotc;
2908c5ad0daSSasha Neftin regs_buff[88] = adapter->stats.lenerrs;
2918c5ad0daSSasha Neftin regs_buff[89] = adapter->stats.scvpc;
2928c5ad0daSSasha Neftin regs_buff[90] = adapter->stats.hrmpc;
2938c5ad0daSSasha Neftin
2948c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
2958c5ad0daSSasha Neftin regs_buff[91 + i] = rd32(IGC_SRRCTL(i));
2968c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
2978c5ad0daSSasha Neftin regs_buff[95 + i] = rd32(IGC_PSRTYPE(i));
2988c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
2998c5ad0daSSasha Neftin regs_buff[99 + i] = rd32(IGC_RDBAL(i));
3008c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3018c5ad0daSSasha Neftin regs_buff[103 + i] = rd32(IGC_RDBAH(i));
3028c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3038c5ad0daSSasha Neftin regs_buff[107 + i] = rd32(IGC_RDLEN(i));
3048c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3058c5ad0daSSasha Neftin regs_buff[111 + i] = rd32(IGC_RDH(i));
3068c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3078c5ad0daSSasha Neftin regs_buff[115 + i] = rd32(IGC_RDT(i));
3088c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3098c5ad0daSSasha Neftin regs_buff[119 + i] = rd32(IGC_RXDCTL(i));
3108c5ad0daSSasha Neftin
3118c5ad0daSSasha Neftin for (i = 0; i < 10; i++)
3128c5ad0daSSasha Neftin regs_buff[123 + i] = rd32(IGC_EITR(i));
3138c5ad0daSSasha Neftin for (i = 0; i < 16; i++)
3148c5ad0daSSasha Neftin regs_buff[139 + i] = rd32(IGC_RAL(i));
3158c5ad0daSSasha Neftin for (i = 0; i < 16; i++)
3168c5ad0daSSasha Neftin regs_buff[145 + i] = rd32(IGC_RAH(i));
3178c5ad0daSSasha Neftin
3188c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3198c5ad0daSSasha Neftin regs_buff[149 + i] = rd32(IGC_TDBAL(i));
3208c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3218c5ad0daSSasha Neftin regs_buff[152 + i] = rd32(IGC_TDBAH(i));
3228c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3238c5ad0daSSasha Neftin regs_buff[156 + i] = rd32(IGC_TDLEN(i));
3248c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3258c5ad0daSSasha Neftin regs_buff[160 + i] = rd32(IGC_TDH(i));
3268c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3278c5ad0daSSasha Neftin regs_buff[164 + i] = rd32(IGC_TDT(i));
3288c5ad0daSSasha Neftin for (i = 0; i < 4; i++)
3298c5ad0daSSasha Neftin regs_buff[168 + i] = rd32(IGC_TXDCTL(i));
330b8a61ea1SAndre Guedes
331b8a61ea1SAndre Guedes /* XXX: Due to a bug few lines above, RAL and RAH registers are
332b8a61ea1SAndre Guedes * overwritten. To preserve the ABI, we write these registers again in
333b8a61ea1SAndre Guedes * regs_buff.
334b8a61ea1SAndre Guedes */
335b8a61ea1SAndre Guedes for (i = 0; i < 16; i++)
336b8a61ea1SAndre Guedes regs_buff[172 + i] = rd32(IGC_RAL(i));
337b8a61ea1SAndre Guedes for (i = 0; i < 16; i++)
338b8a61ea1SAndre Guedes regs_buff[188 + i] = rd32(IGC_RAH(i));
339fbee4760SAndre Guedes
340fbee4760SAndre Guedes regs_buff[204] = rd32(IGC_VLANPQF);
34181e33061SAndre Guedes
34281e33061SAndre Guedes for (i = 0; i < 8; i++)
34381e33061SAndre Guedes regs_buff[205 + i] = rd32(IGC_ETQF(i));
34440edc734SSasha Neftin
34540edc734SSasha Neftin regs_buff[213] = adapter->stats.tlpic;
34640edc734SSasha Neftin regs_buff[214] = adapter->stats.rlpic;
3478c5ad0daSSasha Neftin }
3488c5ad0daSSasha Neftin
igc_ethtool_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)3497df76bd1SAndre Guedes static void igc_ethtool_get_wol(struct net_device *netdev,
3507df76bd1SAndre Guedes struct ethtool_wolinfo *wol)
351e055600dSSasha Neftin {
352e055600dSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
353e055600dSSasha Neftin
354e055600dSSasha Neftin wol->wolopts = 0;
355e055600dSSasha Neftin
356e055600dSSasha Neftin if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED))
357e055600dSSasha Neftin return;
358e055600dSSasha Neftin
359e055600dSSasha Neftin wol->supported = WAKE_UCAST | WAKE_MCAST |
360e055600dSSasha Neftin WAKE_BCAST | WAKE_MAGIC |
361e055600dSSasha Neftin WAKE_PHY;
362e055600dSSasha Neftin
363e055600dSSasha Neftin /* apply any specific unsupported masks here */
364e055600dSSasha Neftin switch (adapter->hw.device_id) {
365e055600dSSasha Neftin default:
366e055600dSSasha Neftin break;
367e055600dSSasha Neftin }
368e055600dSSasha Neftin
369e055600dSSasha Neftin if (adapter->wol & IGC_WUFC_EX)
370e055600dSSasha Neftin wol->wolopts |= WAKE_UCAST;
371e055600dSSasha Neftin if (adapter->wol & IGC_WUFC_MC)
372e055600dSSasha Neftin wol->wolopts |= WAKE_MCAST;
373e055600dSSasha Neftin if (adapter->wol & IGC_WUFC_BC)
374e055600dSSasha Neftin wol->wolopts |= WAKE_BCAST;
375e055600dSSasha Neftin if (adapter->wol & IGC_WUFC_MAG)
376e055600dSSasha Neftin wol->wolopts |= WAKE_MAGIC;
377e055600dSSasha Neftin if (adapter->wol & IGC_WUFC_LNKC)
378e055600dSSasha Neftin wol->wolopts |= WAKE_PHY;
379e055600dSSasha Neftin }
380e055600dSSasha Neftin
igc_ethtool_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)3817df76bd1SAndre Guedes static int igc_ethtool_set_wol(struct net_device *netdev,
3827df76bd1SAndre Guedes struct ethtool_wolinfo *wol)
383e055600dSSasha Neftin {
384e055600dSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
385e055600dSSasha Neftin
386e055600dSSasha Neftin if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_FILTER))
387e055600dSSasha Neftin return -EOPNOTSUPP;
388e055600dSSasha Neftin
389e055600dSSasha Neftin if (!(adapter->flags & IGC_FLAG_WOL_SUPPORTED))
390e055600dSSasha Neftin return wol->wolopts ? -EOPNOTSUPP : 0;
391e055600dSSasha Neftin
392e055600dSSasha Neftin /* these settings will always override what we currently have */
393e055600dSSasha Neftin adapter->wol = 0;
394e055600dSSasha Neftin
395e055600dSSasha Neftin if (wol->wolopts & WAKE_UCAST)
396e055600dSSasha Neftin adapter->wol |= IGC_WUFC_EX;
397e055600dSSasha Neftin if (wol->wolopts & WAKE_MCAST)
398e055600dSSasha Neftin adapter->wol |= IGC_WUFC_MC;
399e055600dSSasha Neftin if (wol->wolopts & WAKE_BCAST)
400e055600dSSasha Neftin adapter->wol |= IGC_WUFC_BC;
401e055600dSSasha Neftin if (wol->wolopts & WAKE_MAGIC)
402e055600dSSasha Neftin adapter->wol |= IGC_WUFC_MAG;
403e055600dSSasha Neftin if (wol->wolopts & WAKE_PHY)
404e055600dSSasha Neftin adapter->wol |= IGC_WUFC_LNKC;
405e055600dSSasha Neftin device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
406e055600dSSasha Neftin
407e055600dSSasha Neftin return 0;
408e055600dSSasha Neftin }
409e055600dSSasha Neftin
igc_ethtool_get_msglevel(struct net_device * netdev)4107df76bd1SAndre Guedes static u32 igc_ethtool_get_msglevel(struct net_device *netdev)
4118c5ad0daSSasha Neftin {
4128c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4138c5ad0daSSasha Neftin
4148c5ad0daSSasha Neftin return adapter->msg_enable;
4158c5ad0daSSasha Neftin }
4168c5ad0daSSasha Neftin
igc_ethtool_set_msglevel(struct net_device * netdev,u32 data)4177df76bd1SAndre Guedes static void igc_ethtool_set_msglevel(struct net_device *netdev, u32 data)
4188c5ad0daSSasha Neftin {
4198c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4208c5ad0daSSasha Neftin
4218c5ad0daSSasha Neftin adapter->msg_enable = data;
4228c5ad0daSSasha Neftin }
4238c5ad0daSSasha Neftin
igc_ethtool_nway_reset(struct net_device * netdev)4247df76bd1SAndre Guedes static int igc_ethtool_nway_reset(struct net_device *netdev)
4258c5ad0daSSasha Neftin {
4268c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4278c5ad0daSSasha Neftin
4288c5ad0daSSasha Neftin if (netif_running(netdev))
4298c5ad0daSSasha Neftin igc_reinit_locked(adapter);
4308c5ad0daSSasha Neftin return 0;
4318c5ad0daSSasha Neftin }
4328c5ad0daSSasha Neftin
igc_ethtool_get_link(struct net_device * netdev)4337df76bd1SAndre Guedes static u32 igc_ethtool_get_link(struct net_device *netdev)
4348c5ad0daSSasha Neftin {
4358c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4368c5ad0daSSasha Neftin struct igc_mac_info *mac = &adapter->hw.mac;
4378c5ad0daSSasha Neftin
4388c5ad0daSSasha Neftin /* If the link is not reported up to netdev, interrupts are disabled,
4398c5ad0daSSasha Neftin * and so the physical link state may have changed since we last
4408c5ad0daSSasha Neftin * looked. Set get_link_status to make sure that the true link
4418c5ad0daSSasha Neftin * state is interrogated, rather than pulling a cached and possibly
4428c5ad0daSSasha Neftin * stale link state from the driver.
4438c5ad0daSSasha Neftin */
4448c5ad0daSSasha Neftin if (!netif_carrier_ok(netdev))
4458c5ad0daSSasha Neftin mac->get_link_status = 1;
4468c5ad0daSSasha Neftin
4478c5ad0daSSasha Neftin return igc_has_link(adapter);
4488c5ad0daSSasha Neftin }
4498c5ad0daSSasha Neftin
igc_ethtool_get_eeprom_len(struct net_device * netdev)4507df76bd1SAndre Guedes static int igc_ethtool_get_eeprom_len(struct net_device *netdev)
4518c5ad0daSSasha Neftin {
4528c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4538c5ad0daSSasha Neftin
4548c5ad0daSSasha Neftin return adapter->hw.nvm.word_size * 2;
4558c5ad0daSSasha Neftin }
4568c5ad0daSSasha Neftin
igc_ethtool_get_eeprom(struct net_device * netdev,struct ethtool_eeprom * eeprom,u8 * bytes)4577df76bd1SAndre Guedes static int igc_ethtool_get_eeprom(struct net_device *netdev,
4588c5ad0daSSasha Neftin struct ethtool_eeprom *eeprom, u8 *bytes)
4598c5ad0daSSasha Neftin {
4608c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
4618c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
4628c5ad0daSSasha Neftin int first_word, last_word;
4638c5ad0daSSasha Neftin u16 *eeprom_buff;
4648c5ad0daSSasha Neftin int ret_val = 0;
4658c5ad0daSSasha Neftin u16 i;
4668c5ad0daSSasha Neftin
4678c5ad0daSSasha Neftin if (eeprom->len == 0)
4688c5ad0daSSasha Neftin return -EINVAL;
4698c5ad0daSSasha Neftin
4708c5ad0daSSasha Neftin eeprom->magic = hw->vendor_id | (hw->device_id << 16);
4718c5ad0daSSasha Neftin
4728c5ad0daSSasha Neftin first_word = eeprom->offset >> 1;
4738c5ad0daSSasha Neftin last_word = (eeprom->offset + eeprom->len - 1) >> 1;
4748c5ad0daSSasha Neftin
4758c5ad0daSSasha Neftin eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
4768c5ad0daSSasha Neftin GFP_KERNEL);
4778c5ad0daSSasha Neftin if (!eeprom_buff)
4788c5ad0daSSasha Neftin return -ENOMEM;
4798c5ad0daSSasha Neftin
4808c5ad0daSSasha Neftin if (hw->nvm.type == igc_nvm_eeprom_spi) {
4818c5ad0daSSasha Neftin ret_val = hw->nvm.ops.read(hw, first_word,
4828c5ad0daSSasha Neftin last_word - first_word + 1,
4838c5ad0daSSasha Neftin eeprom_buff);
4848c5ad0daSSasha Neftin } else {
4858c5ad0daSSasha Neftin for (i = 0; i < last_word - first_word + 1; i++) {
4868c5ad0daSSasha Neftin ret_val = hw->nvm.ops.read(hw, first_word + i, 1,
4878c5ad0daSSasha Neftin &eeprom_buff[i]);
4888c5ad0daSSasha Neftin if (ret_val)
4898c5ad0daSSasha Neftin break;
4908c5ad0daSSasha Neftin }
4918c5ad0daSSasha Neftin }
4928c5ad0daSSasha Neftin
4938c5ad0daSSasha Neftin /* Device's eeprom is always little-endian, word addressable */
4948c5ad0daSSasha Neftin for (i = 0; i < last_word - first_word + 1; i++)
4958c5ad0daSSasha Neftin le16_to_cpus(&eeprom_buff[i]);
4968c5ad0daSSasha Neftin
4978c5ad0daSSasha Neftin memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
4988c5ad0daSSasha Neftin eeprom->len);
4998c5ad0daSSasha Neftin kfree(eeprom_buff);
5008c5ad0daSSasha Neftin
5018c5ad0daSSasha Neftin return ret_val;
5028c5ad0daSSasha Neftin }
5038c5ad0daSSasha Neftin
igc_ethtool_set_eeprom(struct net_device * netdev,struct ethtool_eeprom * eeprom,u8 * bytes)5047df76bd1SAndre Guedes static int igc_ethtool_set_eeprom(struct net_device *netdev,
5058c5ad0daSSasha Neftin struct ethtool_eeprom *eeprom, u8 *bytes)
5068c5ad0daSSasha Neftin {
5078c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
5088c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
5098c5ad0daSSasha Neftin int max_len, first_word, last_word, ret_val = 0;
5108c5ad0daSSasha Neftin u16 *eeprom_buff;
5118c5ad0daSSasha Neftin void *ptr;
5128c5ad0daSSasha Neftin u16 i;
5138c5ad0daSSasha Neftin
5148c5ad0daSSasha Neftin if (eeprom->len == 0)
5158c5ad0daSSasha Neftin return -EOPNOTSUPP;
5168c5ad0daSSasha Neftin
5178c5ad0daSSasha Neftin if (hw->mac.type >= igc_i225 &&
5188c5ad0daSSasha Neftin !igc_get_flash_presence_i225(hw)) {
5198c5ad0daSSasha Neftin return -EOPNOTSUPP;
5208c5ad0daSSasha Neftin }
5218c5ad0daSSasha Neftin
5228c5ad0daSSasha Neftin if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
5238c5ad0daSSasha Neftin return -EFAULT;
5248c5ad0daSSasha Neftin
5258c5ad0daSSasha Neftin max_len = hw->nvm.word_size * 2;
5268c5ad0daSSasha Neftin
5278c5ad0daSSasha Neftin first_word = eeprom->offset >> 1;
5288c5ad0daSSasha Neftin last_word = (eeprom->offset + eeprom->len - 1) >> 1;
5298c5ad0daSSasha Neftin eeprom_buff = kmalloc(max_len, GFP_KERNEL);
5308c5ad0daSSasha Neftin if (!eeprom_buff)
5318c5ad0daSSasha Neftin return -ENOMEM;
5328c5ad0daSSasha Neftin
5338c5ad0daSSasha Neftin ptr = (void *)eeprom_buff;
5348c5ad0daSSasha Neftin
5358c5ad0daSSasha Neftin if (eeprom->offset & 1) {
5368c5ad0daSSasha Neftin /* need read/modify/write of first changed EEPROM word
5378c5ad0daSSasha Neftin * only the second byte of the word is being modified
5388c5ad0daSSasha Neftin */
5398c5ad0daSSasha Neftin ret_val = hw->nvm.ops.read(hw, first_word, 1,
5408c5ad0daSSasha Neftin &eeprom_buff[0]);
5418c5ad0daSSasha Neftin ptr++;
5428c5ad0daSSasha Neftin }
5438c5ad0daSSasha Neftin if (((eeprom->offset + eeprom->len) & 1) && ret_val == 0) {
5448c5ad0daSSasha Neftin /* need read/modify/write of last changed EEPROM word
5458c5ad0daSSasha Neftin * only the first byte of the word is being modified
5468c5ad0daSSasha Neftin */
5478c5ad0daSSasha Neftin ret_val = hw->nvm.ops.read(hw, last_word, 1,
5488c5ad0daSSasha Neftin &eeprom_buff[last_word - first_word]);
5498c5ad0daSSasha Neftin }
5508c5ad0daSSasha Neftin
5518c5ad0daSSasha Neftin /* Device's eeprom is always little-endian, word addressable */
5528c5ad0daSSasha Neftin for (i = 0; i < last_word - first_word + 1; i++)
5538c5ad0daSSasha Neftin le16_to_cpus(&eeprom_buff[i]);
5548c5ad0daSSasha Neftin
5558c5ad0daSSasha Neftin memcpy(ptr, bytes, eeprom->len);
5568c5ad0daSSasha Neftin
5578c5ad0daSSasha Neftin for (i = 0; i < last_word - first_word + 1; i++)
558c40591ccSJesse Brandeburg cpu_to_le16s(&eeprom_buff[i]);
5598c5ad0daSSasha Neftin
5608c5ad0daSSasha Neftin ret_val = hw->nvm.ops.write(hw, first_word,
5618c5ad0daSSasha Neftin last_word - first_word + 1, eeprom_buff);
5628c5ad0daSSasha Neftin
5638c5ad0daSSasha Neftin /* Update the checksum if nvm write succeeded */
5648c5ad0daSSasha Neftin if (ret_val == 0)
5658c5ad0daSSasha Neftin hw->nvm.ops.update(hw);
5668c5ad0daSSasha Neftin
5678c5ad0daSSasha Neftin kfree(eeprom_buff);
5688c5ad0daSSasha Neftin return ret_val;
5698c5ad0daSSasha Neftin }
5708c5ad0daSSasha Neftin
57174624944SHao Chen static void
igc_ethtool_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ering,struct netlink_ext_ack * extack)57274624944SHao Chen igc_ethtool_get_ringparam(struct net_device *netdev,
57374624944SHao Chen struct ethtool_ringparam *ring,
57474624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering,
57574624944SHao Chen struct netlink_ext_ack *extack)
5768c5ad0daSSasha Neftin {
5778c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
5788c5ad0daSSasha Neftin
5798c5ad0daSSasha Neftin ring->rx_max_pending = IGC_MAX_RXD;
5808c5ad0daSSasha Neftin ring->tx_max_pending = IGC_MAX_TXD;
5818c5ad0daSSasha Neftin ring->rx_pending = adapter->rx_ring_count;
5828c5ad0daSSasha Neftin ring->tx_pending = adapter->tx_ring_count;
5838c5ad0daSSasha Neftin }
5848c5ad0daSSasha Neftin
58574624944SHao Chen static int
igc_ethtool_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ering,struct netlink_ext_ack * extack)58674624944SHao Chen igc_ethtool_set_ringparam(struct net_device *netdev,
58774624944SHao Chen struct ethtool_ringparam *ring,
58874624944SHao Chen struct kernel_ethtool_ringparam *kernel_ering,
58974624944SHao Chen struct netlink_ext_ack *extack)
5908c5ad0daSSasha Neftin {
5918c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
5928c5ad0daSSasha Neftin struct igc_ring *temp_ring;
5938c5ad0daSSasha Neftin u16 new_rx_count, new_tx_count;
5948c5ad0daSSasha Neftin int i, err = 0;
5958c5ad0daSSasha Neftin
5968c5ad0daSSasha Neftin if (ring->rx_mini_pending || ring->rx_jumbo_pending)
5978c5ad0daSSasha Neftin return -EINVAL;
5988c5ad0daSSasha Neftin
5998c5ad0daSSasha Neftin new_rx_count = min_t(u32, ring->rx_pending, IGC_MAX_RXD);
6008c5ad0daSSasha Neftin new_rx_count = max_t(u16, new_rx_count, IGC_MIN_RXD);
6018c5ad0daSSasha Neftin new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
6028c5ad0daSSasha Neftin
6038c5ad0daSSasha Neftin new_tx_count = min_t(u32, ring->tx_pending, IGC_MAX_TXD);
6048c5ad0daSSasha Neftin new_tx_count = max_t(u16, new_tx_count, IGC_MIN_TXD);
6058c5ad0daSSasha Neftin new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
6068c5ad0daSSasha Neftin
6078c5ad0daSSasha Neftin if (new_tx_count == adapter->tx_ring_count &&
6088c5ad0daSSasha Neftin new_rx_count == adapter->rx_ring_count) {
6098c5ad0daSSasha Neftin /* nothing to do */
6108c5ad0daSSasha Neftin return 0;
6118c5ad0daSSasha Neftin }
6128c5ad0daSSasha Neftin
6138c5ad0daSSasha Neftin while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
6148c5ad0daSSasha Neftin usleep_range(1000, 2000);
6158c5ad0daSSasha Neftin
6168c5ad0daSSasha Neftin if (!netif_running(adapter->netdev)) {
6178c5ad0daSSasha Neftin for (i = 0; i < adapter->num_tx_queues; i++)
6188c5ad0daSSasha Neftin adapter->tx_ring[i]->count = new_tx_count;
6198c5ad0daSSasha Neftin for (i = 0; i < adapter->num_rx_queues; i++)
6208c5ad0daSSasha Neftin adapter->rx_ring[i]->count = new_rx_count;
6218c5ad0daSSasha Neftin adapter->tx_ring_count = new_tx_count;
6228c5ad0daSSasha Neftin adapter->rx_ring_count = new_rx_count;
6238c5ad0daSSasha Neftin goto clear_reset;
6248c5ad0daSSasha Neftin }
6258c5ad0daSSasha Neftin
6268c5ad0daSSasha Neftin if (adapter->num_tx_queues > adapter->num_rx_queues)
6278c5ad0daSSasha Neftin temp_ring = vmalloc(array_size(sizeof(struct igc_ring),
6288c5ad0daSSasha Neftin adapter->num_tx_queues));
6298c5ad0daSSasha Neftin else
6308c5ad0daSSasha Neftin temp_ring = vmalloc(array_size(sizeof(struct igc_ring),
6318c5ad0daSSasha Neftin adapter->num_rx_queues));
6328c5ad0daSSasha Neftin
6338c5ad0daSSasha Neftin if (!temp_ring) {
6348c5ad0daSSasha Neftin err = -ENOMEM;
6358c5ad0daSSasha Neftin goto clear_reset;
6368c5ad0daSSasha Neftin }
6378c5ad0daSSasha Neftin
6388c5ad0daSSasha Neftin igc_down(adapter);
6398c5ad0daSSasha Neftin
6408c5ad0daSSasha Neftin /* We can't just free everything and then setup again,
6418c5ad0daSSasha Neftin * because the ISRs in MSI-X mode get passed pointers
6428c5ad0daSSasha Neftin * to the Tx and Rx ring structs.
6438c5ad0daSSasha Neftin */
6448c5ad0daSSasha Neftin if (new_tx_count != adapter->tx_ring_count) {
6458c5ad0daSSasha Neftin for (i = 0; i < adapter->num_tx_queues; i++) {
6468c5ad0daSSasha Neftin memcpy(&temp_ring[i], adapter->tx_ring[i],
6478c5ad0daSSasha Neftin sizeof(struct igc_ring));
6488c5ad0daSSasha Neftin
6498c5ad0daSSasha Neftin temp_ring[i].count = new_tx_count;
6508c5ad0daSSasha Neftin err = igc_setup_tx_resources(&temp_ring[i]);
6518c5ad0daSSasha Neftin if (err) {
6528c5ad0daSSasha Neftin while (i) {
6538c5ad0daSSasha Neftin i--;
6548c5ad0daSSasha Neftin igc_free_tx_resources(&temp_ring[i]);
6558c5ad0daSSasha Neftin }
6568c5ad0daSSasha Neftin goto err_setup;
6578c5ad0daSSasha Neftin }
6588c5ad0daSSasha Neftin }
6598c5ad0daSSasha Neftin
6608c5ad0daSSasha Neftin for (i = 0; i < adapter->num_tx_queues; i++) {
6618c5ad0daSSasha Neftin igc_free_tx_resources(adapter->tx_ring[i]);
6628c5ad0daSSasha Neftin
6638c5ad0daSSasha Neftin memcpy(adapter->tx_ring[i], &temp_ring[i],
6648c5ad0daSSasha Neftin sizeof(struct igc_ring));
6658c5ad0daSSasha Neftin }
6668c5ad0daSSasha Neftin
6678c5ad0daSSasha Neftin adapter->tx_ring_count = new_tx_count;
6688c5ad0daSSasha Neftin }
6698c5ad0daSSasha Neftin
6708c5ad0daSSasha Neftin if (new_rx_count != adapter->rx_ring_count) {
6718c5ad0daSSasha Neftin for (i = 0; i < adapter->num_rx_queues; i++) {
6728c5ad0daSSasha Neftin memcpy(&temp_ring[i], adapter->rx_ring[i],
6738c5ad0daSSasha Neftin sizeof(struct igc_ring));
6748c5ad0daSSasha Neftin
6758c5ad0daSSasha Neftin temp_ring[i].count = new_rx_count;
6768c5ad0daSSasha Neftin err = igc_setup_rx_resources(&temp_ring[i]);
6778c5ad0daSSasha Neftin if (err) {
6788c5ad0daSSasha Neftin while (i) {
6798c5ad0daSSasha Neftin i--;
6808c5ad0daSSasha Neftin igc_free_rx_resources(&temp_ring[i]);
6818c5ad0daSSasha Neftin }
6828c5ad0daSSasha Neftin goto err_setup;
6838c5ad0daSSasha Neftin }
6848c5ad0daSSasha Neftin }
6858c5ad0daSSasha Neftin
6868c5ad0daSSasha Neftin for (i = 0; i < adapter->num_rx_queues; i++) {
6878c5ad0daSSasha Neftin igc_free_rx_resources(adapter->rx_ring[i]);
6888c5ad0daSSasha Neftin
6898c5ad0daSSasha Neftin memcpy(adapter->rx_ring[i], &temp_ring[i],
6908c5ad0daSSasha Neftin sizeof(struct igc_ring));
6918c5ad0daSSasha Neftin }
6928c5ad0daSSasha Neftin
6938c5ad0daSSasha Neftin adapter->rx_ring_count = new_rx_count;
6948c5ad0daSSasha Neftin }
6958c5ad0daSSasha Neftin err_setup:
6968c5ad0daSSasha Neftin igc_up(adapter);
6978c5ad0daSSasha Neftin vfree(temp_ring);
6988c5ad0daSSasha Neftin clear_reset:
6998c5ad0daSSasha Neftin clear_bit(__IGC_RESETTING, &adapter->state);
7008c5ad0daSSasha Neftin return err;
7018c5ad0daSSasha Neftin }
7028c5ad0daSSasha Neftin
igc_ethtool_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)7037df76bd1SAndre Guedes static void igc_ethtool_get_pauseparam(struct net_device *netdev,
7048c5ad0daSSasha Neftin struct ethtool_pauseparam *pause)
7058c5ad0daSSasha Neftin {
7068c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
7078c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
7088c5ad0daSSasha Neftin
7098c5ad0daSSasha Neftin pause->autoneg =
7108c5ad0daSSasha Neftin (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
7118c5ad0daSSasha Neftin
7128c5ad0daSSasha Neftin if (hw->fc.current_mode == igc_fc_rx_pause) {
7138c5ad0daSSasha Neftin pause->rx_pause = 1;
7148c5ad0daSSasha Neftin } else if (hw->fc.current_mode == igc_fc_tx_pause) {
7158c5ad0daSSasha Neftin pause->tx_pause = 1;
7168c5ad0daSSasha Neftin } else if (hw->fc.current_mode == igc_fc_full) {
7178c5ad0daSSasha Neftin pause->rx_pause = 1;
7188c5ad0daSSasha Neftin pause->tx_pause = 1;
7198c5ad0daSSasha Neftin }
7208c5ad0daSSasha Neftin }
7218c5ad0daSSasha Neftin
igc_ethtool_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)7227df76bd1SAndre Guedes static int igc_ethtool_set_pauseparam(struct net_device *netdev,
7238c5ad0daSSasha Neftin struct ethtool_pauseparam *pause)
7248c5ad0daSSasha Neftin {
7258c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
7268c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
7278c5ad0daSSasha Neftin int retval = 0;
7288c5ad0daSSasha Neftin
7298c5ad0daSSasha Neftin adapter->fc_autoneg = pause->autoneg;
7308c5ad0daSSasha Neftin
7318c5ad0daSSasha Neftin while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
7328c5ad0daSSasha Neftin usleep_range(1000, 2000);
7338c5ad0daSSasha Neftin
7348c5ad0daSSasha Neftin if (adapter->fc_autoneg == AUTONEG_ENABLE) {
7358c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_default;
7368c5ad0daSSasha Neftin if (netif_running(adapter->netdev)) {
7378c5ad0daSSasha Neftin igc_down(adapter);
7388c5ad0daSSasha Neftin igc_up(adapter);
7398c5ad0daSSasha Neftin } else {
7408c5ad0daSSasha Neftin igc_reset(adapter);
7418c5ad0daSSasha Neftin }
7428c5ad0daSSasha Neftin } else {
7438c5ad0daSSasha Neftin if (pause->rx_pause && pause->tx_pause)
7448c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_full;
7458c5ad0daSSasha Neftin else if (pause->rx_pause && !pause->tx_pause)
7468c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_rx_pause;
7478c5ad0daSSasha Neftin else if (!pause->rx_pause && pause->tx_pause)
7488c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_tx_pause;
7498c5ad0daSSasha Neftin else if (!pause->rx_pause && !pause->tx_pause)
7508c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_none;
7518c5ad0daSSasha Neftin
7528c5ad0daSSasha Neftin hw->fc.current_mode = hw->fc.requested_mode;
7538c5ad0daSSasha Neftin
7548c5ad0daSSasha Neftin retval = ((hw->phy.media_type == igc_media_type_copper) ?
7558c5ad0daSSasha Neftin igc_force_mac_fc(hw) : igc_setup_link(hw));
7568c5ad0daSSasha Neftin }
7578c5ad0daSSasha Neftin
7588c5ad0daSSasha Neftin clear_bit(__IGC_RESETTING, &adapter->state);
7598c5ad0daSSasha Neftin return retval;
7608c5ad0daSSasha Neftin }
7618c5ad0daSSasha Neftin
igc_ethtool_get_strings(struct net_device * netdev,u32 stringset,u8 * data)7627df76bd1SAndre Guedes static void igc_ethtool_get_strings(struct net_device *netdev, u32 stringset,
7637df76bd1SAndre Guedes u8 *data)
76436b9fea6SSasha Neftin {
76536b9fea6SSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
76636b9fea6SSasha Neftin u8 *p = data;
76736b9fea6SSasha Neftin int i;
76836b9fea6SSasha Neftin
76936b9fea6SSasha Neftin switch (stringset) {
77036b9fea6SSasha Neftin case ETH_SS_TEST:
77136b9fea6SSasha Neftin memcpy(data, *igc_gstrings_test,
77236b9fea6SSasha Neftin IGC_TEST_LEN * ETH_GSTRING_LEN);
77336b9fea6SSasha Neftin break;
77436b9fea6SSasha Neftin case ETH_SS_STATS:
775220ef1f9SSasha Neftin for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++)
776220ef1f9SSasha Neftin ethtool_sprintf(&p, igc_gstrings_stats[i].stat_string);
777220ef1f9SSasha Neftin for (i = 0; i < IGC_NETDEV_STATS_LEN; i++)
778220ef1f9SSasha Neftin ethtool_sprintf(&p,
779220ef1f9SSasha Neftin igc_gstrings_net_stats[i].stat_string);
78036b9fea6SSasha Neftin for (i = 0; i < adapter->num_tx_queues; i++) {
781220ef1f9SSasha Neftin ethtool_sprintf(&p, "tx_queue_%u_packets", i);
782220ef1f9SSasha Neftin ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
783220ef1f9SSasha Neftin ethtool_sprintf(&p, "tx_queue_%u_restart", i);
78436b9fea6SSasha Neftin }
78536b9fea6SSasha Neftin for (i = 0; i < adapter->num_rx_queues; i++) {
786220ef1f9SSasha Neftin ethtool_sprintf(&p, "rx_queue_%u_packets", i);
787220ef1f9SSasha Neftin ethtool_sprintf(&p, "rx_queue_%u_bytes", i);
788220ef1f9SSasha Neftin ethtool_sprintf(&p, "rx_queue_%u_drops", i);
789220ef1f9SSasha Neftin ethtool_sprintf(&p, "rx_queue_%u_csum_err", i);
790220ef1f9SSasha Neftin ethtool_sprintf(&p, "rx_queue_%u_alloc_failed", i);
79136b9fea6SSasha Neftin }
79236b9fea6SSasha Neftin /* BUG_ON(p - data != IGC_STATS_LEN * ETH_GSTRING_LEN); */
79336b9fea6SSasha Neftin break;
79436b9fea6SSasha Neftin case ETH_SS_PRIV_FLAGS:
79536b9fea6SSasha Neftin memcpy(data, igc_priv_flags_strings,
79636b9fea6SSasha Neftin IGC_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
79736b9fea6SSasha Neftin break;
79836b9fea6SSasha Neftin }
79936b9fea6SSasha Neftin }
80036b9fea6SSasha Neftin
igc_ethtool_get_sset_count(struct net_device * netdev,int sset)8017df76bd1SAndre Guedes static int igc_ethtool_get_sset_count(struct net_device *netdev, int sset)
80236b9fea6SSasha Neftin {
80336b9fea6SSasha Neftin switch (sset) {
80436b9fea6SSasha Neftin case ETH_SS_STATS:
80536b9fea6SSasha Neftin return IGC_STATS_LEN;
80636b9fea6SSasha Neftin case ETH_SS_TEST:
80736b9fea6SSasha Neftin return IGC_TEST_LEN;
80836b9fea6SSasha Neftin case ETH_SS_PRIV_FLAGS:
80936b9fea6SSasha Neftin return IGC_PRIV_FLAGS_STR_LEN;
81036b9fea6SSasha Neftin default:
81136b9fea6SSasha Neftin return -ENOTSUPP;
81236b9fea6SSasha Neftin }
81336b9fea6SSasha Neftin }
81436b9fea6SSasha Neftin
igc_ethtool_get_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)8157df76bd1SAndre Guedes static void igc_ethtool_get_stats(struct net_device *netdev,
81636b9fea6SSasha Neftin struct ethtool_stats *stats, u64 *data)
81736b9fea6SSasha Neftin {
81836b9fea6SSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
81936b9fea6SSasha Neftin struct rtnl_link_stats64 *net_stats = &adapter->stats64;
82036b9fea6SSasha Neftin unsigned int start;
82136b9fea6SSasha Neftin struct igc_ring *ring;
82236b9fea6SSasha Neftin int i, j;
82336b9fea6SSasha Neftin char *p;
82436b9fea6SSasha Neftin
82536b9fea6SSasha Neftin spin_lock(&adapter->stats64_lock);
82636b9fea6SSasha Neftin igc_update_stats(adapter);
82736b9fea6SSasha Neftin
82836b9fea6SSasha Neftin for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++) {
82936b9fea6SSasha Neftin p = (char *)adapter + igc_gstrings_stats[i].stat_offset;
83036b9fea6SSasha Neftin data[i] = (igc_gstrings_stats[i].sizeof_stat ==
83136b9fea6SSasha Neftin sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
83236b9fea6SSasha Neftin }
83336b9fea6SSasha Neftin for (j = 0; j < IGC_NETDEV_STATS_LEN; j++, i++) {
83436b9fea6SSasha Neftin p = (char *)net_stats + igc_gstrings_net_stats[j].stat_offset;
83536b9fea6SSasha Neftin data[i] = (igc_gstrings_net_stats[j].sizeof_stat ==
83636b9fea6SSasha Neftin sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
83736b9fea6SSasha Neftin }
83836b9fea6SSasha Neftin for (j = 0; j < adapter->num_tx_queues; j++) {
83936b9fea6SSasha Neftin u64 restart2;
84036b9fea6SSasha Neftin
84136b9fea6SSasha Neftin ring = adapter->tx_ring[j];
84236b9fea6SSasha Neftin do {
843068c38adSThomas Gleixner start = u64_stats_fetch_begin(&ring->tx_syncp);
84436b9fea6SSasha Neftin data[i] = ring->tx_stats.packets;
84536b9fea6SSasha Neftin data[i + 1] = ring->tx_stats.bytes;
84636b9fea6SSasha Neftin data[i + 2] = ring->tx_stats.restart_queue;
847068c38adSThomas Gleixner } while (u64_stats_fetch_retry(&ring->tx_syncp, start));
84836b9fea6SSasha Neftin do {
849068c38adSThomas Gleixner start = u64_stats_fetch_begin(&ring->tx_syncp2);
85036b9fea6SSasha Neftin restart2 = ring->tx_stats.restart_queue2;
851068c38adSThomas Gleixner } while (u64_stats_fetch_retry(&ring->tx_syncp2, start));
85236b9fea6SSasha Neftin data[i + 2] += restart2;
85336b9fea6SSasha Neftin
85436b9fea6SSasha Neftin i += IGC_TX_QUEUE_STATS_LEN;
85536b9fea6SSasha Neftin }
85636b9fea6SSasha Neftin for (j = 0; j < adapter->num_rx_queues; j++) {
85736b9fea6SSasha Neftin ring = adapter->rx_ring[j];
85836b9fea6SSasha Neftin do {
859068c38adSThomas Gleixner start = u64_stats_fetch_begin(&ring->rx_syncp);
86036b9fea6SSasha Neftin data[i] = ring->rx_stats.packets;
86136b9fea6SSasha Neftin data[i + 1] = ring->rx_stats.bytes;
86236b9fea6SSasha Neftin data[i + 2] = ring->rx_stats.drops;
86336b9fea6SSasha Neftin data[i + 3] = ring->rx_stats.csum_err;
86436b9fea6SSasha Neftin data[i + 4] = ring->rx_stats.alloc_failed;
865068c38adSThomas Gleixner } while (u64_stats_fetch_retry(&ring->rx_syncp, start));
86636b9fea6SSasha Neftin i += IGC_RX_QUEUE_STATS_LEN;
86736b9fea6SSasha Neftin }
86836b9fea6SSasha Neftin spin_unlock(&adapter->stats64_lock);
86936b9fea6SSasha Neftin }
87036b9fea6SSasha Neftin
igc_ethtool_get_previous_rx_coalesce(struct igc_adapter * adapter)8711703b2e0SMuhammad Husaini Zulkifli static int igc_ethtool_get_previous_rx_coalesce(struct igc_adapter *adapter)
8721703b2e0SMuhammad Husaini Zulkifli {
8731703b2e0SMuhammad Husaini Zulkifli return (adapter->rx_itr_setting <= 3) ?
8741703b2e0SMuhammad Husaini Zulkifli adapter->rx_itr_setting : adapter->rx_itr_setting >> 2;
8751703b2e0SMuhammad Husaini Zulkifli }
8761703b2e0SMuhammad Husaini Zulkifli
igc_ethtool_get_previous_tx_coalesce(struct igc_adapter * adapter)8771703b2e0SMuhammad Husaini Zulkifli static int igc_ethtool_get_previous_tx_coalesce(struct igc_adapter *adapter)
8781703b2e0SMuhammad Husaini Zulkifli {
8791703b2e0SMuhammad Husaini Zulkifli return (adapter->tx_itr_setting <= 3) ?
8801703b2e0SMuhammad Husaini Zulkifli adapter->tx_itr_setting : adapter->tx_itr_setting >> 2;
8811703b2e0SMuhammad Husaini Zulkifli }
8821703b2e0SMuhammad Husaini Zulkifli
igc_ethtool_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)8837df76bd1SAndre Guedes static int igc_ethtool_get_coalesce(struct net_device *netdev,
884f3ccfda1SYufeng Mo struct ethtool_coalesce *ec,
885f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
886f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
8878c5ad0daSSasha Neftin {
8888c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
8898c5ad0daSSasha Neftin
8901703b2e0SMuhammad Husaini Zulkifli ec->rx_coalesce_usecs = igc_ethtool_get_previous_rx_coalesce(adapter);
8911703b2e0SMuhammad Husaini Zulkifli ec->tx_coalesce_usecs = igc_ethtool_get_previous_tx_coalesce(adapter);
8928c5ad0daSSasha Neftin
8938c5ad0daSSasha Neftin return 0;
8948c5ad0daSSasha Neftin }
8958c5ad0daSSasha Neftin
igc_ethtool_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * ec,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)8967df76bd1SAndre Guedes static int igc_ethtool_set_coalesce(struct net_device *netdev,
897f3ccfda1SYufeng Mo struct ethtool_coalesce *ec,
898f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
899f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
9008c5ad0daSSasha Neftin {
9018c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
9028c5ad0daSSasha Neftin int i;
9038c5ad0daSSasha Neftin
9048c5ad0daSSasha Neftin if (ec->rx_coalesce_usecs > IGC_MAX_ITR_USECS ||
9058c5ad0daSSasha Neftin (ec->rx_coalesce_usecs > 3 &&
9068c5ad0daSSasha Neftin ec->rx_coalesce_usecs < IGC_MIN_ITR_USECS) ||
9078c5ad0daSSasha Neftin ec->rx_coalesce_usecs == 2)
9088c5ad0daSSasha Neftin return -EINVAL;
9098c5ad0daSSasha Neftin
9108c5ad0daSSasha Neftin if (ec->tx_coalesce_usecs > IGC_MAX_ITR_USECS ||
9118c5ad0daSSasha Neftin (ec->tx_coalesce_usecs > 3 &&
9128c5ad0daSSasha Neftin ec->tx_coalesce_usecs < IGC_MIN_ITR_USECS) ||
9138c5ad0daSSasha Neftin ec->tx_coalesce_usecs == 2)
9148c5ad0daSSasha Neftin return -EINVAL;
9158c5ad0daSSasha Neftin
9161703b2e0SMuhammad Husaini Zulkifli if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) &&
9171703b2e0SMuhammad Husaini Zulkifli ec->tx_coalesce_usecs != igc_ethtool_get_previous_tx_coalesce(adapter)) {
9181703b2e0SMuhammad Husaini Zulkifli NL_SET_ERR_MSG_MOD(extack,
9191703b2e0SMuhammad Husaini Zulkifli "Queue Pair mode enabled, both Rx and Tx coalescing controlled by rx-usecs");
9208c5ad0daSSasha Neftin return -EINVAL;
9211703b2e0SMuhammad Husaini Zulkifli }
9228c5ad0daSSasha Neftin
9238c5ad0daSSasha Neftin /* If ITR is disabled, disable DMAC */
9248c5ad0daSSasha Neftin if (ec->rx_coalesce_usecs == 0) {
9258c5ad0daSSasha Neftin if (adapter->flags & IGC_FLAG_DMAC)
9268c5ad0daSSasha Neftin adapter->flags &= ~IGC_FLAG_DMAC;
9278c5ad0daSSasha Neftin }
9288c5ad0daSSasha Neftin
9298c5ad0daSSasha Neftin /* convert to rate of irq's per second */
9308c5ad0daSSasha Neftin if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
9318c5ad0daSSasha Neftin adapter->rx_itr_setting = ec->rx_coalesce_usecs;
9328c5ad0daSSasha Neftin else
9338c5ad0daSSasha Neftin adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2;
9348c5ad0daSSasha Neftin
9358c5ad0daSSasha Neftin /* convert to rate of irq's per second */
9368c5ad0daSSasha Neftin if (adapter->flags & IGC_FLAG_QUEUE_PAIRS)
9378c5ad0daSSasha Neftin adapter->tx_itr_setting = adapter->rx_itr_setting;
9388c5ad0daSSasha Neftin else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3)
9398c5ad0daSSasha Neftin adapter->tx_itr_setting = ec->tx_coalesce_usecs;
9408c5ad0daSSasha Neftin else
9418c5ad0daSSasha Neftin adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2;
9428c5ad0daSSasha Neftin
9438c5ad0daSSasha Neftin for (i = 0; i < adapter->num_q_vectors; i++) {
9448c5ad0daSSasha Neftin struct igc_q_vector *q_vector = adapter->q_vector[i];
9458c5ad0daSSasha Neftin
9468c5ad0daSSasha Neftin q_vector->tx.work_limit = adapter->tx_work_limit;
9478c5ad0daSSasha Neftin if (q_vector->rx.ring)
9488c5ad0daSSasha Neftin q_vector->itr_val = adapter->rx_itr_setting;
9498c5ad0daSSasha Neftin else
9508c5ad0daSSasha Neftin q_vector->itr_val = adapter->tx_itr_setting;
9518c5ad0daSSasha Neftin if (q_vector->itr_val && q_vector->itr_val <= 3)
9528c5ad0daSSasha Neftin q_vector->itr_val = IGC_START_ITR;
9538c5ad0daSSasha Neftin q_vector->set_itr = 1;
9548c5ad0daSSasha Neftin }
9558c5ad0daSSasha Neftin
9568c5ad0daSSasha Neftin return 0;
9578c5ad0daSSasha Neftin }
9588c5ad0daSSasha Neftin
9596245c848SSasha Neftin #define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
96008144bacSKurt Kanzenbach #define VLAN_TCI_FULL_MASK ((__force __be16)~0)
igc_ethtool_get_nfc_rule(struct igc_adapter * adapter,struct ethtool_rxnfc * cmd)96197700bc8SAndre Guedes static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter,
9626245c848SSasha Neftin struct ethtool_rxnfc *cmd)
9636245c848SSasha Neftin {
9646245c848SSasha Neftin struct ethtool_rx_flow_spec *fsp = &cmd->fs;
96597700bc8SAndre Guedes struct igc_nfc_rule *rule = NULL;
9666245c848SSasha Neftin
96797700bc8SAndre Guedes cmd->data = IGC_MAX_RXNFC_RULES;
9686245c848SSasha Neftin
96942fc5dc0SAndre Guedes mutex_lock(&adapter->nfc_rule_lock);
970b500350aSAndre Guedes
97136fa2152SAndre Guedes rule = igc_get_nfc_rule(adapter, fsp->location);
97236fa2152SAndre Guedes if (!rule)
973b500350aSAndre Guedes goto out;
974876ea04dSAndre Guedes
9756245c848SSasha Neftin fsp->flow_type = ETHER_FLOW;
9766245c848SSasha Neftin fsp->ring_cookie = rule->action;
977876ea04dSAndre Guedes
9786245c848SSasha Neftin if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
979c983e327SAndre Guedes fsp->h_u.ether_spec.h_proto = htons(rule->filter.etype);
9806245c848SSasha Neftin fsp->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK;
9816245c848SSasha Neftin }
982876ea04dSAndre Guedes
9834109b21eSKurt Kanzenbach if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_ETYPE) {
9844109b21eSKurt Kanzenbach fsp->flow_type |= FLOW_EXT;
9854109b21eSKurt Kanzenbach fsp->h_ext.vlan_etype = rule->filter.vlan_etype;
9864109b21eSKurt Kanzenbach fsp->m_ext.vlan_etype = ETHER_TYPE_FULL_MASK;
9874109b21eSKurt Kanzenbach }
9884109b21eSKurt Kanzenbach
9896245c848SSasha Neftin if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
9906245c848SSasha Neftin fsp->flow_type |= FLOW_EXT;
991c983e327SAndre Guedes fsp->h_ext.vlan_tci = htons(rule->filter.vlan_tci);
99208144bacSKurt Kanzenbach fsp->m_ext.vlan_tci = htons(rule->filter.vlan_tci_mask);
9936245c848SSasha Neftin }
994876ea04dSAndre Guedes
9956245c848SSasha Neftin if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
9966245c848SSasha Neftin ether_addr_copy(fsp->h_u.ether_spec.h_dest,
9976245c848SSasha Neftin rule->filter.dst_addr);
9986245c848SSasha Neftin eth_broadcast_addr(fsp->m_u.ether_spec.h_dest);
9996245c848SSasha Neftin }
1000876ea04dSAndre Guedes
10016245c848SSasha Neftin if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
10026245c848SSasha Neftin ether_addr_copy(fsp->h_u.ether_spec.h_source,
10036245c848SSasha Neftin rule->filter.src_addr);
10046245c848SSasha Neftin eth_broadcast_addr(fsp->m_u.ether_spec.h_source);
10056245c848SSasha Neftin }
10066245c848SSasha Neftin
10072b477d05SKurt Kanzenbach if (rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA) {
10082b477d05SKurt Kanzenbach fsp->flow_type |= FLOW_EXT;
10092b477d05SKurt Kanzenbach memcpy(fsp->h_ext.data, rule->filter.user_data, sizeof(fsp->h_ext.data));
10102b477d05SKurt Kanzenbach memcpy(fsp->m_ext.data, rule->filter.user_mask, sizeof(fsp->m_ext.data));
10112b477d05SKurt Kanzenbach }
10122b477d05SKurt Kanzenbach
101342fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
10146245c848SSasha Neftin return 0;
1015b500350aSAndre Guedes
1016b500350aSAndre Guedes out:
101742fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
1018b500350aSAndre Guedes return -EINVAL;
10196245c848SSasha Neftin }
10206245c848SSasha Neftin
igc_ethtool_get_nfc_rules(struct igc_adapter * adapter,struct ethtool_rxnfc * cmd,u32 * rule_locs)102197700bc8SAndre Guedes static int igc_ethtool_get_nfc_rules(struct igc_adapter *adapter,
10226245c848SSasha Neftin struct ethtool_rxnfc *cmd,
10236245c848SSasha Neftin u32 *rule_locs)
10246245c848SSasha Neftin {
102597700bc8SAndre Guedes struct igc_nfc_rule *rule;
10266245c848SSasha Neftin int cnt = 0;
10276245c848SSasha Neftin
102897700bc8SAndre Guedes cmd->data = IGC_MAX_RXNFC_RULES;
10296245c848SSasha Neftin
103042fc5dc0SAndre Guedes mutex_lock(&adapter->nfc_rule_lock);
1031b500350aSAndre Guedes
1032d957c601SAndre Guedes list_for_each_entry(rule, &adapter->nfc_rule_list, list) {
1033b500350aSAndre Guedes if (cnt == cmd->rule_cnt) {
103442fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
10356245c848SSasha Neftin return -EMSGSIZE;
1036b500350aSAndre Guedes }
1037d3ba9e6fSAndre Guedes rule_locs[cnt] = rule->location;
10386245c848SSasha Neftin cnt++;
10396245c848SSasha Neftin }
10406245c848SSasha Neftin
104142fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
1042b500350aSAndre Guedes
10436245c848SSasha Neftin cmd->rule_cnt = cnt;
10446245c848SSasha Neftin
10456245c848SSasha Neftin return 0;
10466245c848SSasha Neftin }
10476245c848SSasha Neftin
igc_ethtool_get_rss_hash_opts(struct igc_adapter * adapter,struct ethtool_rxnfc * cmd)10487df76bd1SAndre Guedes static int igc_ethtool_get_rss_hash_opts(struct igc_adapter *adapter,
10496245c848SSasha Neftin struct ethtool_rxnfc *cmd)
10506245c848SSasha Neftin {
10516245c848SSasha Neftin cmd->data = 0;
10526245c848SSasha Neftin
10536245c848SSasha Neftin /* Report default options for RSS on igc */
10546245c848SSasha Neftin switch (cmd->flow_type) {
10556245c848SSasha Neftin case TCP_V4_FLOW:
10566245c848SSasha Neftin cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
10575463fce6SJeff Kirsher fallthrough;
10586245c848SSasha Neftin case UDP_V4_FLOW:
10596245c848SSasha Neftin if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV4_UDP)
10606245c848SSasha Neftin cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
10615463fce6SJeff Kirsher fallthrough;
10626245c848SSasha Neftin case SCTP_V4_FLOW:
10636245c848SSasha Neftin case AH_ESP_V4_FLOW:
10646245c848SSasha Neftin case AH_V4_FLOW:
10656245c848SSasha Neftin case ESP_V4_FLOW:
10666245c848SSasha Neftin case IPV4_FLOW:
10676245c848SSasha Neftin cmd->data |= RXH_IP_SRC | RXH_IP_DST;
10686245c848SSasha Neftin break;
10696245c848SSasha Neftin case TCP_V6_FLOW:
10706245c848SSasha Neftin cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
10715463fce6SJeff Kirsher fallthrough;
10726245c848SSasha Neftin case UDP_V6_FLOW:
10736245c848SSasha Neftin if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV6_UDP)
10746245c848SSasha Neftin cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
10755463fce6SJeff Kirsher fallthrough;
10766245c848SSasha Neftin case SCTP_V6_FLOW:
10776245c848SSasha Neftin case AH_ESP_V6_FLOW:
10786245c848SSasha Neftin case AH_V6_FLOW:
10796245c848SSasha Neftin case ESP_V6_FLOW:
10806245c848SSasha Neftin case IPV6_FLOW:
10816245c848SSasha Neftin cmd->data |= RXH_IP_SRC | RXH_IP_DST;
10826245c848SSasha Neftin break;
10836245c848SSasha Neftin default:
10846245c848SSasha Neftin return -EINVAL;
10856245c848SSasha Neftin }
10866245c848SSasha Neftin
10876245c848SSasha Neftin return 0;
10886245c848SSasha Neftin }
10896245c848SSasha Neftin
igc_ethtool_get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * cmd,u32 * rule_locs)10907df76bd1SAndre Guedes static int igc_ethtool_get_rxnfc(struct net_device *dev,
10917df76bd1SAndre Guedes struct ethtool_rxnfc *cmd, u32 *rule_locs)
10926245c848SSasha Neftin {
10936245c848SSasha Neftin struct igc_adapter *adapter = netdev_priv(dev);
10946245c848SSasha Neftin
10956245c848SSasha Neftin switch (cmd->cmd) {
10966245c848SSasha Neftin case ETHTOOL_GRXRINGS:
10976245c848SSasha Neftin cmd->data = adapter->num_rx_queues;
10988b9c23cdSAndre Guedes return 0;
10996245c848SSasha Neftin case ETHTOOL_GRXCLSRLCNT:
110097700bc8SAndre Guedes cmd->rule_cnt = adapter->nfc_rule_count;
11018b9c23cdSAndre Guedes return 0;
11026245c848SSasha Neftin case ETHTOOL_GRXCLSRULE:
110397700bc8SAndre Guedes return igc_ethtool_get_nfc_rule(adapter, cmd);
11046245c848SSasha Neftin case ETHTOOL_GRXCLSRLALL:
110597700bc8SAndre Guedes return igc_ethtool_get_nfc_rules(adapter, cmd, rule_locs);
11066245c848SSasha Neftin case ETHTOOL_GRXFH:
11077df76bd1SAndre Guedes return igc_ethtool_get_rss_hash_opts(adapter, cmd);
11086245c848SSasha Neftin default:
11098b9c23cdSAndre Guedes return -EOPNOTSUPP;
11106245c848SSasha Neftin }
11116245c848SSasha Neftin }
11126245c848SSasha Neftin
11136245c848SSasha Neftin #define UDP_RSS_FLAGS (IGC_FLAG_RSS_FIELD_IPV4_UDP | \
11146245c848SSasha Neftin IGC_FLAG_RSS_FIELD_IPV6_UDP)
igc_ethtool_set_rss_hash_opt(struct igc_adapter * adapter,struct ethtool_rxnfc * nfc)11157df76bd1SAndre Guedes static int igc_ethtool_set_rss_hash_opt(struct igc_adapter *adapter,
11166245c848SSasha Neftin struct ethtool_rxnfc *nfc)
11176245c848SSasha Neftin {
11186245c848SSasha Neftin u32 flags = adapter->flags;
11196245c848SSasha Neftin
11206245c848SSasha Neftin /* RSS does not support anything other than hashing
11216245c848SSasha Neftin * to queues on src and dst IPs and ports
11226245c848SSasha Neftin */
11236245c848SSasha Neftin if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
11246245c848SSasha Neftin RXH_L4_B_0_1 | RXH_L4_B_2_3))
11256245c848SSasha Neftin return -EINVAL;
11266245c848SSasha Neftin
11276245c848SSasha Neftin switch (nfc->flow_type) {
11286245c848SSasha Neftin case TCP_V4_FLOW:
11296245c848SSasha Neftin case TCP_V6_FLOW:
11306245c848SSasha Neftin if (!(nfc->data & RXH_IP_SRC) ||
11316245c848SSasha Neftin !(nfc->data & RXH_IP_DST) ||
11326245c848SSasha Neftin !(nfc->data & RXH_L4_B_0_1) ||
11336245c848SSasha Neftin !(nfc->data & RXH_L4_B_2_3))
11346245c848SSasha Neftin return -EINVAL;
11356245c848SSasha Neftin break;
11366245c848SSasha Neftin case UDP_V4_FLOW:
11376245c848SSasha Neftin if (!(nfc->data & RXH_IP_SRC) ||
11386245c848SSasha Neftin !(nfc->data & RXH_IP_DST))
11396245c848SSasha Neftin return -EINVAL;
11406245c848SSasha Neftin switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
11416245c848SSasha Neftin case 0:
11426245c848SSasha Neftin flags &= ~IGC_FLAG_RSS_FIELD_IPV4_UDP;
11436245c848SSasha Neftin break;
11446245c848SSasha Neftin case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
11456245c848SSasha Neftin flags |= IGC_FLAG_RSS_FIELD_IPV4_UDP;
11466245c848SSasha Neftin break;
11476245c848SSasha Neftin default:
11486245c848SSasha Neftin return -EINVAL;
11496245c848SSasha Neftin }
11506245c848SSasha Neftin break;
11516245c848SSasha Neftin case UDP_V6_FLOW:
11526245c848SSasha Neftin if (!(nfc->data & RXH_IP_SRC) ||
11536245c848SSasha Neftin !(nfc->data & RXH_IP_DST))
11546245c848SSasha Neftin return -EINVAL;
11556245c848SSasha Neftin switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
11566245c848SSasha Neftin case 0:
11576245c848SSasha Neftin flags &= ~IGC_FLAG_RSS_FIELD_IPV6_UDP;
11586245c848SSasha Neftin break;
11596245c848SSasha Neftin case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
11606245c848SSasha Neftin flags |= IGC_FLAG_RSS_FIELD_IPV6_UDP;
11616245c848SSasha Neftin break;
11626245c848SSasha Neftin default:
11636245c848SSasha Neftin return -EINVAL;
11646245c848SSasha Neftin }
11656245c848SSasha Neftin break;
11666245c848SSasha Neftin case AH_ESP_V4_FLOW:
11676245c848SSasha Neftin case AH_V4_FLOW:
11686245c848SSasha Neftin case ESP_V4_FLOW:
11696245c848SSasha Neftin case SCTP_V4_FLOW:
11706245c848SSasha Neftin case AH_ESP_V6_FLOW:
11716245c848SSasha Neftin case AH_V6_FLOW:
11726245c848SSasha Neftin case ESP_V6_FLOW:
11736245c848SSasha Neftin case SCTP_V6_FLOW:
11746245c848SSasha Neftin if (!(nfc->data & RXH_IP_SRC) ||
11756245c848SSasha Neftin !(nfc->data & RXH_IP_DST) ||
11766245c848SSasha Neftin (nfc->data & RXH_L4_B_0_1) ||
11776245c848SSasha Neftin (nfc->data & RXH_L4_B_2_3))
11786245c848SSasha Neftin return -EINVAL;
11796245c848SSasha Neftin break;
11806245c848SSasha Neftin default:
11816245c848SSasha Neftin return -EINVAL;
11826245c848SSasha Neftin }
11836245c848SSasha Neftin
11846245c848SSasha Neftin /* if we changed something we need to update flags */
11856245c848SSasha Neftin if (flags != adapter->flags) {
11866245c848SSasha Neftin struct igc_hw *hw = &adapter->hw;
11876245c848SSasha Neftin u32 mrqc = rd32(IGC_MRQC);
11886245c848SSasha Neftin
11896245c848SSasha Neftin if ((flags & UDP_RSS_FLAGS) &&
11906245c848SSasha Neftin !(adapter->flags & UDP_RSS_FLAGS))
119195f96a9fSAndre Guedes netdev_err(adapter->netdev,
119295f96a9fSAndre Guedes "Enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
11936245c848SSasha Neftin
11946245c848SSasha Neftin adapter->flags = flags;
11956245c848SSasha Neftin
11966245c848SSasha Neftin /* Perform hash on these packet types */
11976245c848SSasha Neftin mrqc |= IGC_MRQC_RSS_FIELD_IPV4 |
11986245c848SSasha Neftin IGC_MRQC_RSS_FIELD_IPV4_TCP |
11996245c848SSasha Neftin IGC_MRQC_RSS_FIELD_IPV6 |
12006245c848SSasha Neftin IGC_MRQC_RSS_FIELD_IPV6_TCP;
12016245c848SSasha Neftin
12026245c848SSasha Neftin mrqc &= ~(IGC_MRQC_RSS_FIELD_IPV4_UDP |
12036245c848SSasha Neftin IGC_MRQC_RSS_FIELD_IPV6_UDP);
12046245c848SSasha Neftin
12056245c848SSasha Neftin if (flags & IGC_FLAG_RSS_FIELD_IPV4_UDP)
12066245c848SSasha Neftin mrqc |= IGC_MRQC_RSS_FIELD_IPV4_UDP;
12076245c848SSasha Neftin
12086245c848SSasha Neftin if (flags & IGC_FLAG_RSS_FIELD_IPV6_UDP)
12096245c848SSasha Neftin mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP;
12106245c848SSasha Neftin
12116245c848SSasha Neftin wr32(IGC_MRQC, mrqc);
12126245c848SSasha Neftin }
12136245c848SSasha Neftin
12146245c848SSasha Neftin return 0;
12156245c848SSasha Neftin }
12166245c848SSasha Neftin
igc_ethtool_init_nfc_rule(struct igc_nfc_rule * rule,const struct ethtool_rx_flow_spec * fsp)121716fdc16cSAndre Guedes static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
121816fdc16cSAndre Guedes const struct ethtool_rx_flow_spec *fsp)
12196245c848SSasha Neftin {
1220d957c601SAndre Guedes INIT_LIST_HEAD(&rule->list);
12216245c848SSasha Neftin
122216fdc16cSAndre Guedes rule->action = fsp->ring_cookie;
1223d3ba9e6fSAndre Guedes rule->location = fsp->location;
12246245c848SSasha Neftin
122516fdc16cSAndre Guedes if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
122616fdc16cSAndre Guedes rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci);
122708144bacSKurt Kanzenbach rule->filter.vlan_tci_mask = ntohs(fsp->m_ext.vlan_tci);
122816fdc16cSAndre Guedes rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI;
12296245c848SSasha Neftin }
12306245c848SSasha Neftin
12316245c848SSasha Neftin if (fsp->m_u.ether_spec.h_proto == ETHER_TYPE_FULL_MASK) {
1232c983e327SAndre Guedes rule->filter.etype = ntohs(fsp->h_u.ether_spec.h_proto);
123397700bc8SAndre Guedes rule->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE;
12346245c848SSasha Neftin }
12356245c848SSasha Neftin
12368eb2449dSAndre Guedes /* Both source and destination address filters only support the full
12378eb2449dSAndre Guedes * mask.
12388eb2449dSAndre Guedes */
12396245c848SSasha Neftin if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) {
124097700bc8SAndre Guedes rule->filter.match_flags |= IGC_FILTER_FLAG_SRC_MAC_ADDR;
124197700bc8SAndre Guedes ether_addr_copy(rule->filter.src_addr,
12426245c848SSasha Neftin fsp->h_u.ether_spec.h_source);
12436245c848SSasha Neftin }
12446245c848SSasha Neftin
12456245c848SSasha Neftin if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) {
124697700bc8SAndre Guedes rule->filter.match_flags |= IGC_FILTER_FLAG_DST_MAC_ADDR;
124797700bc8SAndre Guedes ether_addr_copy(rule->filter.dst_addr,
12486245c848SSasha Neftin fsp->h_u.ether_spec.h_dest);
12496245c848SSasha Neftin }
12502b477d05SKurt Kanzenbach
125173744262SKurt Kanzenbach /* VLAN etype matching */
125273744262SKurt Kanzenbach if ((fsp->flow_type & FLOW_EXT) && fsp->h_ext.vlan_etype) {
125373744262SKurt Kanzenbach rule->filter.vlan_etype = fsp->h_ext.vlan_etype;
125473744262SKurt Kanzenbach rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_ETYPE;
125573744262SKurt Kanzenbach }
125673744262SKurt Kanzenbach
12572b477d05SKurt Kanzenbach /* Check for user defined data */
12582b477d05SKurt Kanzenbach if ((fsp->flow_type & FLOW_EXT) &&
12592b477d05SKurt Kanzenbach (fsp->h_ext.data[0] || fsp->h_ext.data[1])) {
12602b477d05SKurt Kanzenbach rule->filter.match_flags |= IGC_FILTER_FLAG_USER_DATA;
12612b477d05SKurt Kanzenbach memcpy(rule->filter.user_data, fsp->h_ext.data, sizeof(fsp->h_ext.data));
12622b477d05SKurt Kanzenbach memcpy(rule->filter.user_mask, fsp->m_ext.data, sizeof(fsp->m_ext.data));
126373744262SKurt Kanzenbach }
12642b477d05SKurt Kanzenbach
126508144bacSKurt Kanzenbach /* The i225/i226 has various different filters. Flex filters provide a
126608144bacSKurt Kanzenbach * way to match up to the first 128 bytes of a packet. Use them for:
126708144bacSKurt Kanzenbach * a) For specific user data
126808144bacSKurt Kanzenbach * b) For VLAN EtherType
126908144bacSKurt Kanzenbach * c) For full TCI match
127008144bacSKurt Kanzenbach * d) Or in case multiple filter criteria are set
127108144bacSKurt Kanzenbach *
127208144bacSKurt Kanzenbach * Otherwise, use the simple MAC, VLAN PRIO or EtherType filters.
127373744262SKurt Kanzenbach */
127473744262SKurt Kanzenbach if ((rule->filter.match_flags & IGC_FILTER_FLAG_USER_DATA) ||
127573744262SKurt Kanzenbach (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_ETYPE) ||
127608144bacSKurt Kanzenbach ((rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) &&
127708144bacSKurt Kanzenbach rule->filter.vlan_tci_mask == ntohs(VLAN_TCI_FULL_MASK)) ||
127873744262SKurt Kanzenbach (rule->filter.match_flags & (rule->filter.match_flags - 1)))
127973744262SKurt Kanzenbach rule->flex = true;
128073744262SKurt Kanzenbach else
128173744262SKurt Kanzenbach rule->flex = false;
12828eb2449dSAndre Guedes }
12838eb2449dSAndre Guedes
128416fdc16cSAndre Guedes /**
128516fdc16cSAndre Guedes * igc_ethtool_check_nfc_rule() - Check if NFC rule is valid
128616fdc16cSAndre Guedes * @adapter: Pointer to adapter
128716fdc16cSAndre Guedes * @rule: Rule under evaluation
128816fdc16cSAndre Guedes *
12893d3e9b6bSAndre Guedes * The driver doesn't support rules with multiple matches so if more than
12903d3e9b6bSAndre Guedes * one bit in filter flags is set, @rule is considered invalid.
129116fdc16cSAndre Guedes *
12921894df0cSAndre Guedes * Also, if there is already another rule with the same filter in a different
12931894df0cSAndre Guedes * location, @rule is considered invalid.
129416fdc16cSAndre Guedes *
129516fdc16cSAndre Guedes * Context: Expects adapter->nfc_rule_lock to be held by caller.
129616fdc16cSAndre Guedes *
129716fdc16cSAndre Guedes * Return: 0 in case of success, negative errno code otherwise.
129816fdc16cSAndre Guedes */
igc_ethtool_check_nfc_rule(struct igc_adapter * adapter,struct igc_nfc_rule * rule)129916fdc16cSAndre Guedes static int igc_ethtool_check_nfc_rule(struct igc_adapter *adapter,
130016fdc16cSAndre Guedes struct igc_nfc_rule *rule)
130116fdc16cSAndre Guedes {
130216fdc16cSAndre Guedes struct net_device *dev = adapter->netdev;
130316fdc16cSAndre Guedes u8 flags = rule->filter.match_flags;
130416fdc16cSAndre Guedes struct igc_nfc_rule *tmp;
130516fdc16cSAndre Guedes
130616fdc16cSAndre Guedes if (!flags) {
130716fdc16cSAndre Guedes netdev_dbg(dev, "Rule with no match\n");
130816fdc16cSAndre Guedes return -EINVAL;
13096245c848SSasha Neftin }
13106245c848SSasha Neftin
1311d957c601SAndre Guedes list_for_each_entry(tmp, &adapter->nfc_rule_list, list) {
131297700bc8SAndre Guedes if (!memcmp(&rule->filter, &tmp->filter,
13131894df0cSAndre Guedes sizeof(rule->filter)) &&
13141894df0cSAndre Guedes tmp->location != rule->location) {
131516fdc16cSAndre Guedes netdev_dbg(dev, "Rule already exists\n");
131616fdc16cSAndre Guedes return -EEXIST;
13176245c848SSasha Neftin }
13186245c848SSasha Neftin }
13196245c848SSasha Neftin
132016fdc16cSAndre Guedes return 0;
132116fdc16cSAndre Guedes }
132216fdc16cSAndre Guedes
igc_ethtool_add_nfc_rule(struct igc_adapter * adapter,struct ethtool_rxnfc * cmd)132316fdc16cSAndre Guedes static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
132416fdc16cSAndre Guedes struct ethtool_rxnfc *cmd)
132516fdc16cSAndre Guedes {
132616fdc16cSAndre Guedes struct net_device *netdev = adapter->netdev;
132716fdc16cSAndre Guedes struct ethtool_rx_flow_spec *fsp =
132816fdc16cSAndre Guedes (struct ethtool_rx_flow_spec *)&cmd->fs;
132936fa2152SAndre Guedes struct igc_nfc_rule *rule, *old_rule;
133016fdc16cSAndre Guedes int err;
133116fdc16cSAndre Guedes
133216fdc16cSAndre Guedes if (!(netdev->hw_features & NETIF_F_NTUPLE)) {
133316fdc16cSAndre Guedes netdev_dbg(netdev, "N-tuple filters disabled\n");
133416fdc16cSAndre Guedes return -EOPNOTSUPP;
133516fdc16cSAndre Guedes }
133616fdc16cSAndre Guedes
133716fdc16cSAndre Guedes if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW) {
133816fdc16cSAndre Guedes netdev_dbg(netdev, "Only ethernet flow type is supported\n");
133916fdc16cSAndre Guedes return -EOPNOTSUPP;
134016fdc16cSAndre Guedes }
134116fdc16cSAndre Guedes
134216fdc16cSAndre Guedes if (fsp->ring_cookie >= adapter->num_rx_queues) {
134316fdc16cSAndre Guedes netdev_dbg(netdev, "Invalid action\n");
134416fdc16cSAndre Guedes return -EINVAL;
134516fdc16cSAndre Guedes }
134616fdc16cSAndre Guedes
134708144bacSKurt Kanzenbach /* There are two ways to match the VLAN TCI:
134808144bacSKurt Kanzenbach * 1. Match on PCP field and use vlan prio filter for it
134908144bacSKurt Kanzenbach * 2. Match on complete TCI field and use flex filter for it
135008144bacSKurt Kanzenbach */
135108144bacSKurt Kanzenbach if ((fsp->flow_type & FLOW_EXT) &&
135208144bacSKurt Kanzenbach fsp->m_ext.vlan_tci &&
135308144bacSKurt Kanzenbach fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK) &&
135408144bacSKurt Kanzenbach fsp->m_ext.vlan_tci != VLAN_TCI_FULL_MASK) {
135508144bacSKurt Kanzenbach netdev_dbg(netdev, "VLAN mask not supported\n");
135608144bacSKurt Kanzenbach return -EOPNOTSUPP;
135708144bacSKurt Kanzenbach }
135808144bacSKurt Kanzenbach
1359*38036a73SKurt Kanzenbach /* VLAN EtherType can only be matched by full mask. */
1360*38036a73SKurt Kanzenbach if ((fsp->flow_type & FLOW_EXT) &&
1361*38036a73SKurt Kanzenbach fsp->m_ext.vlan_etype &&
1362*38036a73SKurt Kanzenbach fsp->m_ext.vlan_etype != ETHER_TYPE_FULL_MASK) {
1363*38036a73SKurt Kanzenbach netdev_dbg(netdev, "VLAN EtherType mask not supported\n");
1364*38036a73SKurt Kanzenbach return -EOPNOTSUPP;
1365*38036a73SKurt Kanzenbach }
1366*38036a73SKurt Kanzenbach
136716fdc16cSAndre Guedes if (fsp->location >= IGC_MAX_RXNFC_RULES) {
136816fdc16cSAndre Guedes netdev_dbg(netdev, "Invalid location\n");
136916fdc16cSAndre Guedes return -EINVAL;
137016fdc16cSAndre Guedes }
137116fdc16cSAndre Guedes
137216fdc16cSAndre Guedes rule = kzalloc(sizeof(*rule), GFP_KERNEL);
137316fdc16cSAndre Guedes if (!rule)
137416fdc16cSAndre Guedes return -ENOMEM;
137516fdc16cSAndre Guedes
137616fdc16cSAndre Guedes igc_ethtool_init_nfc_rule(rule, fsp);
137716fdc16cSAndre Guedes
137842fc5dc0SAndre Guedes mutex_lock(&adapter->nfc_rule_lock);
137916fdc16cSAndre Guedes
138016fdc16cSAndre Guedes err = igc_ethtool_check_nfc_rule(adapter, rule);
138116fdc16cSAndre Guedes if (err)
138216fdc16cSAndre Guedes goto err;
138316fdc16cSAndre Guedes
138436fa2152SAndre Guedes old_rule = igc_get_nfc_rule(adapter, fsp->location);
138536fa2152SAndre Guedes if (old_rule)
138636fa2152SAndre Guedes igc_del_nfc_rule(adapter, old_rule);
138736fa2152SAndre Guedes
138836fa2152SAndre Guedes err = igc_add_nfc_rule(adapter, rule);
13896245c848SSasha Neftin if (err)
139016fdc16cSAndre Guedes goto err;
13916245c848SSasha Neftin
139242fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
13936245c848SSasha Neftin return 0;
13946245c848SSasha Neftin
139516fdc16cSAndre Guedes err:
139642fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
139797700bc8SAndre Guedes kfree(rule);
13986245c848SSasha Neftin return err;
13996245c848SSasha Neftin }
14006245c848SSasha Neftin
igc_ethtool_del_nfc_rule(struct igc_adapter * adapter,struct ethtool_rxnfc * cmd)140197700bc8SAndre Guedes static int igc_ethtool_del_nfc_rule(struct igc_adapter *adapter,
14026245c848SSasha Neftin struct ethtool_rxnfc *cmd)
14036245c848SSasha Neftin {
14046245c848SSasha Neftin struct ethtool_rx_flow_spec *fsp =
14056245c848SSasha Neftin (struct ethtool_rx_flow_spec *)&cmd->fs;
140636fa2152SAndre Guedes struct igc_nfc_rule *rule;
14076245c848SSasha Neftin
140842fc5dc0SAndre Guedes mutex_lock(&adapter->nfc_rule_lock);
14096245c848SSasha Neftin
141036fa2152SAndre Guedes rule = igc_get_nfc_rule(adapter, fsp->location);
141136fa2152SAndre Guedes if (!rule) {
141242fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
141336fa2152SAndre Guedes return -EINVAL;
141436fa2152SAndre Guedes }
141536fa2152SAndre Guedes
141636fa2152SAndre Guedes igc_del_nfc_rule(adapter, rule);
141736fa2152SAndre Guedes
141842fc5dc0SAndre Guedes mutex_unlock(&adapter->nfc_rule_lock);
141936fa2152SAndre Guedes return 0;
14206245c848SSasha Neftin }
14216245c848SSasha Neftin
igc_ethtool_set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * cmd)14227df76bd1SAndre Guedes static int igc_ethtool_set_rxnfc(struct net_device *dev,
14237df76bd1SAndre Guedes struct ethtool_rxnfc *cmd)
14246245c848SSasha Neftin {
14256245c848SSasha Neftin struct igc_adapter *adapter = netdev_priv(dev);
14266245c848SSasha Neftin
14276245c848SSasha Neftin switch (cmd->cmd) {
14286245c848SSasha Neftin case ETHTOOL_SRXFH:
14297df76bd1SAndre Guedes return igc_ethtool_set_rss_hash_opt(adapter, cmd);
14306245c848SSasha Neftin case ETHTOOL_SRXCLSRLINS:
143197700bc8SAndre Guedes return igc_ethtool_add_nfc_rule(adapter, cmd);
14326245c848SSasha Neftin case ETHTOOL_SRXCLSRLDEL:
143397700bc8SAndre Guedes return igc_ethtool_del_nfc_rule(adapter, cmd);
14346245c848SSasha Neftin default:
14358b9c23cdSAndre Guedes return -EOPNOTSUPP;
14366245c848SSasha Neftin }
14376245c848SSasha Neftin }
14386245c848SSasha Neftin
igc_write_rss_indir_tbl(struct igc_adapter * adapter)14398c5ad0daSSasha Neftin void igc_write_rss_indir_tbl(struct igc_adapter *adapter)
14408c5ad0daSSasha Neftin {
14418c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
14428c5ad0daSSasha Neftin u32 reg = IGC_RETA(0);
14438c5ad0daSSasha Neftin u32 shift = 0;
14448c5ad0daSSasha Neftin int i = 0;
14458c5ad0daSSasha Neftin
14468c5ad0daSSasha Neftin while (i < IGC_RETA_SIZE) {
14478c5ad0daSSasha Neftin u32 val = 0;
14488c5ad0daSSasha Neftin int j;
14498c5ad0daSSasha Neftin
14508c5ad0daSSasha Neftin for (j = 3; j >= 0; j--) {
14518c5ad0daSSasha Neftin val <<= 8;
14528c5ad0daSSasha Neftin val |= adapter->rss_indir_tbl[i + j];
14538c5ad0daSSasha Neftin }
14548c5ad0daSSasha Neftin
14558c5ad0daSSasha Neftin wr32(reg, val << shift);
14568c5ad0daSSasha Neftin reg += 4;
14578c5ad0daSSasha Neftin i += 4;
14588c5ad0daSSasha Neftin }
14598c5ad0daSSasha Neftin }
14608c5ad0daSSasha Neftin
igc_ethtool_get_rxfh_indir_size(struct net_device * netdev)14617df76bd1SAndre Guedes static u32 igc_ethtool_get_rxfh_indir_size(struct net_device *netdev)
14628c5ad0daSSasha Neftin {
14638c5ad0daSSasha Neftin return IGC_RETA_SIZE;
14648c5ad0daSSasha Neftin }
14658c5ad0daSSasha Neftin
igc_ethtool_get_rxfh(struct net_device * netdev,u32 * indir,u8 * key,u8 * hfunc)14667df76bd1SAndre Guedes static int igc_ethtool_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
14678c5ad0daSSasha Neftin u8 *hfunc)
14688c5ad0daSSasha Neftin {
14698c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
14708c5ad0daSSasha Neftin int i;
14718c5ad0daSSasha Neftin
14728c5ad0daSSasha Neftin if (hfunc)
14738c5ad0daSSasha Neftin *hfunc = ETH_RSS_HASH_TOP;
14748c5ad0daSSasha Neftin if (!indir)
14758c5ad0daSSasha Neftin return 0;
14768c5ad0daSSasha Neftin for (i = 0; i < IGC_RETA_SIZE; i++)
14778c5ad0daSSasha Neftin indir[i] = adapter->rss_indir_tbl[i];
14788c5ad0daSSasha Neftin
14798c5ad0daSSasha Neftin return 0;
14808c5ad0daSSasha Neftin }
14818c5ad0daSSasha Neftin
igc_ethtool_set_rxfh(struct net_device * netdev,const u32 * indir,const u8 * key,const u8 hfunc)14827df76bd1SAndre Guedes static int igc_ethtool_set_rxfh(struct net_device *netdev, const u32 *indir,
14838c5ad0daSSasha Neftin const u8 *key, const u8 hfunc)
14848c5ad0daSSasha Neftin {
14858c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
14868c5ad0daSSasha Neftin u32 num_queues;
14878c5ad0daSSasha Neftin int i;
14888c5ad0daSSasha Neftin
14898c5ad0daSSasha Neftin /* We do not allow change in unsupported parameters */
14908c5ad0daSSasha Neftin if (key ||
14918c5ad0daSSasha Neftin (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
14928c5ad0daSSasha Neftin return -EOPNOTSUPP;
14938c5ad0daSSasha Neftin if (!indir)
14948c5ad0daSSasha Neftin return 0;
14958c5ad0daSSasha Neftin
14968c5ad0daSSasha Neftin num_queues = adapter->rss_queues;
14978c5ad0daSSasha Neftin
14988c5ad0daSSasha Neftin /* Verify user input. */
14998c5ad0daSSasha Neftin for (i = 0; i < IGC_RETA_SIZE; i++)
15008c5ad0daSSasha Neftin if (indir[i] >= num_queues)
15018c5ad0daSSasha Neftin return -EINVAL;
15028c5ad0daSSasha Neftin
15038c5ad0daSSasha Neftin for (i = 0; i < IGC_RETA_SIZE; i++)
15048c5ad0daSSasha Neftin adapter->rss_indir_tbl[i] = indir[i];
15058c5ad0daSSasha Neftin
15068c5ad0daSSasha Neftin igc_write_rss_indir_tbl(adapter);
15078c5ad0daSSasha Neftin
15088c5ad0daSSasha Neftin return 0;
15098c5ad0daSSasha Neftin }
15108c5ad0daSSasha Neftin
igc_ethtool_get_channels(struct net_device * netdev,struct ethtool_channels * ch)15117df76bd1SAndre Guedes static void igc_ethtool_get_channels(struct net_device *netdev,
15128c5ad0daSSasha Neftin struct ethtool_channels *ch)
15138c5ad0daSSasha Neftin {
15148c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
15158c5ad0daSSasha Neftin
15168c5ad0daSSasha Neftin /* Report maximum channels */
15174d0710c2SAndre Guedes ch->max_combined = igc_get_max_rss_queues(adapter);
15188c5ad0daSSasha Neftin
15198c5ad0daSSasha Neftin /* Report info for other vector */
15208c5ad0daSSasha Neftin if (adapter->flags & IGC_FLAG_HAS_MSIX) {
15218c5ad0daSSasha Neftin ch->max_other = NON_Q_VECTORS;
15228c5ad0daSSasha Neftin ch->other_count = NON_Q_VECTORS;
15238c5ad0daSSasha Neftin }
15248c5ad0daSSasha Neftin
15258c5ad0daSSasha Neftin ch->combined_count = adapter->rss_queues;
15268c5ad0daSSasha Neftin }
15278c5ad0daSSasha Neftin
igc_ethtool_set_channels(struct net_device * netdev,struct ethtool_channels * ch)15287df76bd1SAndre Guedes static int igc_ethtool_set_channels(struct net_device *netdev,
15298c5ad0daSSasha Neftin struct ethtool_channels *ch)
15308c5ad0daSSasha Neftin {
15318c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
15328c5ad0daSSasha Neftin unsigned int count = ch->combined_count;
15338c5ad0daSSasha Neftin unsigned int max_combined = 0;
15348c5ad0daSSasha Neftin
15358c5ad0daSSasha Neftin /* Verify they are not requesting separate vectors */
15368c5ad0daSSasha Neftin if (!count || ch->rx_count || ch->tx_count)
15378c5ad0daSSasha Neftin return -EINVAL;
15388c5ad0daSSasha Neftin
15398c5ad0daSSasha Neftin /* Verify other_count is valid and has not been changed */
15408c5ad0daSSasha Neftin if (ch->other_count != NON_Q_VECTORS)
15418c5ad0daSSasha Neftin return -EINVAL;
15428c5ad0daSSasha Neftin
15438c5ad0daSSasha Neftin /* Verify the number of channels doesn't exceed hw limits */
15444d0710c2SAndre Guedes max_combined = igc_get_max_rss_queues(adapter);
15458c5ad0daSSasha Neftin if (count > max_combined)
15468c5ad0daSSasha Neftin return -EINVAL;
15478c5ad0daSSasha Neftin
15488c5ad0daSSasha Neftin if (count != adapter->rss_queues) {
15498c5ad0daSSasha Neftin adapter->rss_queues = count;
15508c5ad0daSSasha Neftin igc_set_flag_queue_pairs(adapter, max_combined);
15518c5ad0daSSasha Neftin
15528c5ad0daSSasha Neftin /* Hardware has to reinitialize queues and interrupts to
15538c5ad0daSSasha Neftin * match the new configuration.
15548c5ad0daSSasha Neftin */
15558c5ad0daSSasha Neftin return igc_reinit_queues(adapter);
15568c5ad0daSSasha Neftin }
15578c5ad0daSSasha Neftin
15588c5ad0daSSasha Neftin return 0;
15598c5ad0daSSasha Neftin }
15608c5ad0daSSasha Neftin
igc_ethtool_get_ts_info(struct net_device * dev,struct ethtool_ts_info * info)15617df76bd1SAndre Guedes static int igc_ethtool_get_ts_info(struct net_device *dev,
156260dbede0SVinicius Costa Gomes struct ethtool_ts_info *info)
156360dbede0SVinicius Costa Gomes {
156460dbede0SVinicius Costa Gomes struct igc_adapter *adapter = netdev_priv(dev);
156560dbede0SVinicius Costa Gomes
156660dbede0SVinicius Costa Gomes if (adapter->ptp_clock)
156760dbede0SVinicius Costa Gomes info->phc_index = ptp_clock_index(adapter->ptp_clock);
156860dbede0SVinicius Costa Gomes else
156960dbede0SVinicius Costa Gomes info->phc_index = -1;
157060dbede0SVinicius Costa Gomes
157160dbede0SVinicius Costa Gomes switch (adapter->hw.mac.type) {
157260dbede0SVinicius Costa Gomes case igc_i225:
157360dbede0SVinicius Costa Gomes info->so_timestamping =
157460dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_TX_SOFTWARE |
157560dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_RX_SOFTWARE |
157660dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_SOFTWARE |
157760dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_TX_HARDWARE |
157860dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_RX_HARDWARE |
157960dbede0SVinicius Costa Gomes SOF_TIMESTAMPING_RAW_HARDWARE;
158060dbede0SVinicius Costa Gomes
158160dbede0SVinicius Costa Gomes info->tx_types =
158260dbede0SVinicius Costa Gomes BIT(HWTSTAMP_TX_OFF) |
158360dbede0SVinicius Costa Gomes BIT(HWTSTAMP_TX_ON);
158460dbede0SVinicius Costa Gomes
158560dbede0SVinicius Costa Gomes info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
158660dbede0SVinicius Costa Gomes info->rx_filters |= BIT(HWTSTAMP_FILTER_ALL);
158760dbede0SVinicius Costa Gomes
158860dbede0SVinicius Costa Gomes return 0;
158960dbede0SVinicius Costa Gomes default:
159060dbede0SVinicius Costa Gomes return -EOPNOTSUPP;
159160dbede0SVinicius Costa Gomes }
159260dbede0SVinicius Costa Gomes }
159360dbede0SVinicius Costa Gomes
igc_ethtool_get_priv_flags(struct net_device * netdev)15947df76bd1SAndre Guedes static u32 igc_ethtool_get_priv_flags(struct net_device *netdev)
15958c5ad0daSSasha Neftin {
15968c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
15978c5ad0daSSasha Neftin u32 priv_flags = 0;
15988c5ad0daSSasha Neftin
15998c5ad0daSSasha Neftin if (adapter->flags & IGC_FLAG_RX_LEGACY)
16008c5ad0daSSasha Neftin priv_flags |= IGC_PRIV_FLAGS_LEGACY_RX;
16018c5ad0daSSasha Neftin
16028c5ad0daSSasha Neftin return priv_flags;
16038c5ad0daSSasha Neftin }
16048c5ad0daSSasha Neftin
igc_ethtool_set_priv_flags(struct net_device * netdev,u32 priv_flags)16057df76bd1SAndre Guedes static int igc_ethtool_set_priv_flags(struct net_device *netdev, u32 priv_flags)
16068c5ad0daSSasha Neftin {
16078c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
16088c5ad0daSSasha Neftin unsigned int flags = adapter->flags;
16098c5ad0daSSasha Neftin
16108c5ad0daSSasha Neftin flags &= ~IGC_FLAG_RX_LEGACY;
16118c5ad0daSSasha Neftin if (priv_flags & IGC_PRIV_FLAGS_LEGACY_RX)
16128c5ad0daSSasha Neftin flags |= IGC_FLAG_RX_LEGACY;
16138c5ad0daSSasha Neftin
16148c5ad0daSSasha Neftin if (flags != adapter->flags) {
16158c5ad0daSSasha Neftin adapter->flags = flags;
16168c5ad0daSSasha Neftin
16178c5ad0daSSasha Neftin /* reset interface to repopulate queues */
16188c5ad0daSSasha Neftin if (netif_running(netdev))
16198c5ad0daSSasha Neftin igc_reinit_locked(adapter);
16208c5ad0daSSasha Neftin }
16218c5ad0daSSasha Neftin
16228c5ad0daSSasha Neftin return 0;
16238c5ad0daSSasha Neftin }
16248c5ad0daSSasha Neftin
igc_ethtool_get_eee(struct net_device * netdev,struct ethtool_eee * edata)162593ec439aSSasha Neftin static int igc_ethtool_get_eee(struct net_device *netdev,
162693ec439aSSasha Neftin struct ethtool_eee *edata)
162793ec439aSSasha Neftin {
162893ec439aSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
162993ec439aSSasha Neftin struct igc_hw *hw = &adapter->hw;
163093ec439aSSasha Neftin u32 eeer;
163193ec439aSSasha Neftin
163293ec439aSSasha Neftin if (hw->dev_spec._base.eee_enable)
163393ec439aSSasha Neftin edata->advertised =
163493ec439aSSasha Neftin mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
163593ec439aSSasha Neftin
163693ec439aSSasha Neftin *edata = adapter->eee;
163793ec439aSSasha Neftin edata->supported = SUPPORTED_Autoneg;
163893ec439aSSasha Neftin
163993ec439aSSasha Neftin eeer = rd32(IGC_EEER);
164093ec439aSSasha Neftin
164193ec439aSSasha Neftin /* EEE status on negotiated link */
164293ec439aSSasha Neftin if (eeer & IGC_EEER_EEE_NEG)
164393ec439aSSasha Neftin edata->eee_active = true;
164493ec439aSSasha Neftin
164593ec439aSSasha Neftin if (eeer & IGC_EEER_TX_LPI_EN)
164693ec439aSSasha Neftin edata->tx_lpi_enabled = true;
164793ec439aSSasha Neftin
164893ec439aSSasha Neftin edata->eee_enabled = hw->dev_spec._base.eee_enable;
164993ec439aSSasha Neftin
165093ec439aSSasha Neftin edata->advertised = SUPPORTED_Autoneg;
165193ec439aSSasha Neftin edata->lp_advertised = SUPPORTED_Autoneg;
165293ec439aSSasha Neftin
165393ec439aSSasha Neftin /* Report correct negotiated EEE status for devices that
165493ec439aSSasha Neftin * wrongly report EEE at half-duplex
165593ec439aSSasha Neftin */
165693ec439aSSasha Neftin if (adapter->link_duplex == HALF_DUPLEX) {
165793ec439aSSasha Neftin edata->eee_enabled = false;
165893ec439aSSasha Neftin edata->eee_active = false;
165993ec439aSSasha Neftin edata->tx_lpi_enabled = false;
166093ec439aSSasha Neftin edata->advertised &= ~edata->advertised;
166193ec439aSSasha Neftin }
166293ec439aSSasha Neftin
166393ec439aSSasha Neftin return 0;
166493ec439aSSasha Neftin }
166593ec439aSSasha Neftin
igc_ethtool_set_eee(struct net_device * netdev,struct ethtool_eee * edata)166693ec439aSSasha Neftin static int igc_ethtool_set_eee(struct net_device *netdev,
166793ec439aSSasha Neftin struct ethtool_eee *edata)
166893ec439aSSasha Neftin {
166993ec439aSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
167093ec439aSSasha Neftin struct igc_hw *hw = &adapter->hw;
167193ec439aSSasha Neftin struct ethtool_eee eee_curr;
167293ec439aSSasha Neftin s32 ret_val;
167393ec439aSSasha Neftin
167493ec439aSSasha Neftin memset(&eee_curr, 0, sizeof(struct ethtool_eee));
167593ec439aSSasha Neftin
167693ec439aSSasha Neftin ret_val = igc_ethtool_get_eee(netdev, &eee_curr);
167793ec439aSSasha Neftin if (ret_val) {
167893ec439aSSasha Neftin netdev_err(netdev,
167993ec439aSSasha Neftin "Problem setting EEE advertisement options\n");
168093ec439aSSasha Neftin return -EINVAL;
168193ec439aSSasha Neftin }
168293ec439aSSasha Neftin
168393ec439aSSasha Neftin if (eee_curr.eee_enabled) {
168493ec439aSSasha Neftin if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
168593ec439aSSasha Neftin netdev_err(netdev,
168693ec439aSSasha Neftin "Setting EEE tx-lpi is not supported\n");
168793ec439aSSasha Neftin return -EINVAL;
168893ec439aSSasha Neftin }
168993ec439aSSasha Neftin
169093ec439aSSasha Neftin /* Tx LPI timer is not implemented currently */
169193ec439aSSasha Neftin if (edata->tx_lpi_timer) {
169293ec439aSSasha Neftin netdev_err(netdev,
169393ec439aSSasha Neftin "Setting EEE Tx LPI timer is not supported\n");
169493ec439aSSasha Neftin return -EINVAL;
169593ec439aSSasha Neftin }
169693ec439aSSasha Neftin } else if (!edata->eee_enabled) {
169793ec439aSSasha Neftin netdev_err(netdev,
169893ec439aSSasha Neftin "Setting EEE options are not supported with EEE disabled\n");
169993ec439aSSasha Neftin return -EINVAL;
170093ec439aSSasha Neftin }
170193ec439aSSasha Neftin
170293ec439aSSasha Neftin adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
170393ec439aSSasha Neftin if (hw->dev_spec._base.eee_enable != edata->eee_enabled) {
170493ec439aSSasha Neftin hw->dev_spec._base.eee_enable = edata->eee_enabled;
170593ec439aSSasha Neftin adapter->flags |= IGC_FLAG_EEE;
170693ec439aSSasha Neftin
170793ec439aSSasha Neftin /* reset link */
170893ec439aSSasha Neftin if (netif_running(netdev))
170993ec439aSSasha Neftin igc_reinit_locked(adapter);
171093ec439aSSasha Neftin else
171193ec439aSSasha Neftin igc_reset(adapter);
171293ec439aSSasha Neftin }
171393ec439aSSasha Neftin
171493ec439aSSasha Neftin return 0;
171593ec439aSSasha Neftin }
171693ec439aSSasha Neftin
igc_ethtool_begin(struct net_device * netdev)17178c5ad0daSSasha Neftin static int igc_ethtool_begin(struct net_device *netdev)
17188c5ad0daSSasha Neftin {
17198c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
17208c5ad0daSSasha Neftin
17218c5ad0daSSasha Neftin pm_runtime_get_sync(&adapter->pdev->dev);
17228c5ad0daSSasha Neftin return 0;
17238c5ad0daSSasha Neftin }
17248c5ad0daSSasha Neftin
igc_ethtool_complete(struct net_device * netdev)17258c5ad0daSSasha Neftin static void igc_ethtool_complete(struct net_device *netdev)
17268c5ad0daSSasha Neftin {
17278c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
17288c5ad0daSSasha Neftin
17298c5ad0daSSasha Neftin pm_runtime_put(&adapter->pdev->dev);
17308c5ad0daSSasha Neftin }
17318c5ad0daSSasha Neftin
igc_ethtool_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)17327df76bd1SAndre Guedes static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
17338c5ad0daSSasha Neftin struct ethtool_link_ksettings *cmd)
17348c5ad0daSSasha Neftin {
17358c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
17368c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
17378c5ad0daSSasha Neftin u32 status;
17388c5ad0daSSasha Neftin u32 speed;
17398c5ad0daSSasha Neftin
17408c5ad0daSSasha Neftin ethtool_link_ksettings_zero_link_mode(cmd, supported);
17418c5ad0daSSasha Neftin ethtool_link_ksettings_zero_link_mode(cmd, advertising);
17428c5ad0daSSasha Neftin
17438c5ad0daSSasha Neftin /* supported link modes */
17448c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half);
17458c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full);
17468c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half);
17478c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full);
17488c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full);
17498c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, 2500baseT_Full);
17508c5ad0daSSasha Neftin
17518c5ad0daSSasha Neftin /* twisted pair */
17528c5ad0daSSasha Neftin cmd->base.port = PORT_TP;
17538c5ad0daSSasha Neftin cmd->base.phy_address = hw->phy.addr;
17549ac3fc2fSPrasad Koya ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
17559ac3fc2fSPrasad Koya ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
17568c5ad0daSSasha Neftin
17578c5ad0daSSasha Neftin /* advertising link modes */
1758329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
17598c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half);
1760329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_10_FULL)
17618c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full);
1762329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_100_HALF)
17638c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half);
1764329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)
17658c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full);
1766329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_1000_FULL)
17678c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
1768329a3678SCorinna Vinschen if (hw->phy.autoneg_advertised & ADVERTISE_2500_FULL)
17698c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full);
17708c5ad0daSSasha Neftin
17718c5ad0daSSasha Neftin /* set autoneg settings */
17728c5ad0daSSasha Neftin if (hw->mac.autoneg == 1) {
17738c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
17748c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising,
17758c5ad0daSSasha Neftin Autoneg);
17768c5ad0daSSasha Neftin }
17778c5ad0daSSasha Neftin
17789a4a1cdcSMuhammad Husaini Zulkifli /* Set pause flow control settings */
17799a4a1cdcSMuhammad Husaini Zulkifli ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
17809a4a1cdcSMuhammad Husaini Zulkifli
17818c5ad0daSSasha Neftin switch (hw->fc.requested_mode) {
17828c5ad0daSSasha Neftin case igc_fc_full:
17838c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
17848c5ad0daSSasha Neftin break;
17858c5ad0daSSasha Neftin case igc_fc_rx_pause:
17868c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
17878c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising,
17888c5ad0daSSasha Neftin Asym_Pause);
17898c5ad0daSSasha Neftin break;
17908c5ad0daSSasha Neftin case igc_fc_tx_pause:
17918c5ad0daSSasha Neftin ethtool_link_ksettings_add_link_mode(cmd, advertising,
17928c5ad0daSSasha Neftin Asym_Pause);
17938c5ad0daSSasha Neftin break;
17948c5ad0daSSasha Neftin default:
179588765294SMuhammad Husaini Zulkifli break;
17968c5ad0daSSasha Neftin }
17978c5ad0daSSasha Neftin
17982e99dedcSKai-Heng Feng status = pm_runtime_suspended(&adapter->pdev->dev) ?
17992e99dedcSKai-Heng Feng 0 : rd32(IGC_STATUS);
18008c5ad0daSSasha Neftin
18018c5ad0daSSasha Neftin if (status & IGC_STATUS_LU) {
18028c5ad0daSSasha Neftin if (status & IGC_STATUS_SPEED_1000) {
18038c5ad0daSSasha Neftin /* For I225, STATUS will indicate 1G speed in both
18048c5ad0daSSasha Neftin * 1 Gbps and 2.5 Gbps link modes.
18058c5ad0daSSasha Neftin * An additional bit is used
18068c5ad0daSSasha Neftin * to differentiate between 1 Gbps and 2.5 Gbps.
18078c5ad0daSSasha Neftin */
18088c5ad0daSSasha Neftin if (hw->mac.type == igc_i225 &&
18098c5ad0daSSasha Neftin (status & IGC_STATUS_SPEED_2500)) {
18108c5ad0daSSasha Neftin speed = SPEED_2500;
18118c5ad0daSSasha Neftin } else {
18128c5ad0daSSasha Neftin speed = SPEED_1000;
18138c5ad0daSSasha Neftin }
18148c5ad0daSSasha Neftin } else if (status & IGC_STATUS_SPEED_100) {
18158c5ad0daSSasha Neftin speed = SPEED_100;
18168c5ad0daSSasha Neftin } else {
18178c5ad0daSSasha Neftin speed = SPEED_10;
18188c5ad0daSSasha Neftin }
18198c5ad0daSSasha Neftin if ((status & IGC_STATUS_FD) ||
18208c5ad0daSSasha Neftin hw->phy.media_type != igc_media_type_copper)
18218c5ad0daSSasha Neftin cmd->base.duplex = DUPLEX_FULL;
18228c5ad0daSSasha Neftin else
18238c5ad0daSSasha Neftin cmd->base.duplex = DUPLEX_HALF;
18248c5ad0daSSasha Neftin } else {
18258c5ad0daSSasha Neftin speed = SPEED_UNKNOWN;
18268c5ad0daSSasha Neftin cmd->base.duplex = DUPLEX_UNKNOWN;
18278c5ad0daSSasha Neftin }
18288c5ad0daSSasha Neftin cmd->base.speed = speed;
18298c5ad0daSSasha Neftin if (hw->mac.autoneg)
18308c5ad0daSSasha Neftin cmd->base.autoneg = AUTONEG_ENABLE;
18318c5ad0daSSasha Neftin else
18328c5ad0daSSasha Neftin cmd->base.autoneg = AUTONEG_DISABLE;
18338c5ad0daSSasha Neftin
18348c5ad0daSSasha Neftin /* MDI-X => 2; MDI =>1; Invalid =>0 */
18358c5ad0daSSasha Neftin if (hw->phy.media_type == igc_media_type_copper)
18368c5ad0daSSasha Neftin cmd->base.eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
18378c5ad0daSSasha Neftin ETH_TP_MDI;
18388c5ad0daSSasha Neftin else
18398c5ad0daSSasha Neftin cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
18408c5ad0daSSasha Neftin
18418c5ad0daSSasha Neftin if (hw->phy.mdix == AUTO_ALL_MODES)
18428c5ad0daSSasha Neftin cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
18438c5ad0daSSasha Neftin else
18448c5ad0daSSasha Neftin cmd->base.eth_tp_mdix_ctrl = hw->phy.mdix;
18458c5ad0daSSasha Neftin
18468c5ad0daSSasha Neftin return 0;
18478c5ad0daSSasha Neftin }
18488c5ad0daSSasha Neftin
18497df76bd1SAndre Guedes static int
igc_ethtool_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)18507df76bd1SAndre Guedes igc_ethtool_set_link_ksettings(struct net_device *netdev,
18518c5ad0daSSasha Neftin const struct ethtool_link_ksettings *cmd)
18528c5ad0daSSasha Neftin {
18538c5ad0daSSasha Neftin struct igc_adapter *adapter = netdev_priv(netdev);
185495f96a9fSAndre Guedes struct net_device *dev = adapter->netdev;
18558c5ad0daSSasha Neftin struct igc_hw *hw = &adapter->hw;
1856e7684d29SSasha Neftin u16 advertised = 0;
18578c5ad0daSSasha Neftin
18588c5ad0daSSasha Neftin /* When adapter in resetting mode, autoneg/speed/duplex
18598c5ad0daSSasha Neftin * cannot be changed
18608c5ad0daSSasha Neftin */
18618c5ad0daSSasha Neftin if (igc_check_reset_block(hw)) {
186295f96a9fSAndre Guedes netdev_err(dev, "Cannot change link characteristics when reset is active\n");
18638c5ad0daSSasha Neftin return -EINVAL;
18648c5ad0daSSasha Neftin }
18658c5ad0daSSasha Neftin
18668c5ad0daSSasha Neftin /* MDI setting is only allowed when autoneg enabled because
18678c5ad0daSSasha Neftin * some hardware doesn't allow MDI setting when speed or
18688c5ad0daSSasha Neftin * duplex is forced.
18698c5ad0daSSasha Neftin */
18708c5ad0daSSasha Neftin if (cmd->base.eth_tp_mdix_ctrl) {
18718c5ad0daSSasha Neftin if (cmd->base.eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO &&
18728c5ad0daSSasha Neftin cmd->base.autoneg != AUTONEG_ENABLE) {
187395f96a9fSAndre Guedes netdev_err(dev, "Forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
18748c5ad0daSSasha Neftin return -EINVAL;
18758c5ad0daSSasha Neftin }
18768c5ad0daSSasha Neftin }
18778c5ad0daSSasha Neftin
18788c5ad0daSSasha Neftin while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
18798c5ad0daSSasha Neftin usleep_range(1000, 2000);
18808c5ad0daSSasha Neftin
1881e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1882e7684d29SSasha Neftin 2500baseT_Full))
1883e7684d29SSasha Neftin advertised |= ADVERTISE_2500_FULL;
1884e7684d29SSasha Neftin
1885e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1886e7684d29SSasha Neftin 1000baseT_Full))
1887e7684d29SSasha Neftin advertised |= ADVERTISE_1000_FULL;
1888e7684d29SSasha Neftin
1889e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1890e7684d29SSasha Neftin 100baseT_Full))
1891e7684d29SSasha Neftin advertised |= ADVERTISE_100_FULL;
1892e7684d29SSasha Neftin
1893e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1894e7684d29SSasha Neftin 100baseT_Half))
1895e7684d29SSasha Neftin advertised |= ADVERTISE_100_HALF;
1896e7684d29SSasha Neftin
1897e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1898e7684d29SSasha Neftin 10baseT_Full))
1899e7684d29SSasha Neftin advertised |= ADVERTISE_10_FULL;
1900e7684d29SSasha Neftin
1901e7684d29SSasha Neftin if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
1902e7684d29SSasha Neftin 10baseT_Half))
1903e7684d29SSasha Neftin advertised |= ADVERTISE_10_HALF;
19048c5ad0daSSasha Neftin
19058c5ad0daSSasha Neftin if (cmd->base.autoneg == AUTONEG_ENABLE) {
19068c5ad0daSSasha Neftin hw->mac.autoneg = 1;
1907e7684d29SSasha Neftin hw->phy.autoneg_advertised = advertised;
19088c5ad0daSSasha Neftin if (adapter->fc_autoneg)
19098c5ad0daSSasha Neftin hw->fc.requested_mode = igc_fc_default;
19108c5ad0daSSasha Neftin } else {
191195f96a9fSAndre Guedes netdev_info(dev, "Force mode currently not supported\n");
19128c5ad0daSSasha Neftin }
19138c5ad0daSSasha Neftin
19148c5ad0daSSasha Neftin /* MDI-X => 2; MDI => 1; Auto => 3 */
19158c5ad0daSSasha Neftin if (cmd->base.eth_tp_mdix_ctrl) {
19168c5ad0daSSasha Neftin /* fix up the value for auto (3 => 0) as zero is mapped
19178c5ad0daSSasha Neftin * internally to auto
19188c5ad0daSSasha Neftin */
19198c5ad0daSSasha Neftin if (cmd->base.eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
19208c5ad0daSSasha Neftin hw->phy.mdix = AUTO_ALL_MODES;
19218c5ad0daSSasha Neftin else
19228c5ad0daSSasha Neftin hw->phy.mdix = cmd->base.eth_tp_mdix_ctrl;
19238c5ad0daSSasha Neftin }
19248c5ad0daSSasha Neftin
19258c5ad0daSSasha Neftin /* reset the link */
19268c5ad0daSSasha Neftin if (netif_running(adapter->netdev)) {
19278c5ad0daSSasha Neftin igc_down(adapter);
19288c5ad0daSSasha Neftin igc_up(adapter);
19298c5ad0daSSasha Neftin } else {
19308c5ad0daSSasha Neftin igc_reset(adapter);
19318c5ad0daSSasha Neftin }
19328c5ad0daSSasha Neftin
19338c5ad0daSSasha Neftin clear_bit(__IGC_RESETTING, &adapter->state);
19348c5ad0daSSasha Neftin
19358c5ad0daSSasha Neftin return 0;
19368c5ad0daSSasha Neftin }
19378c5ad0daSSasha Neftin
igc_ethtool_diag_test(struct net_device * netdev,struct ethtool_test * eth_test,u64 * data)19387df76bd1SAndre Guedes static void igc_ethtool_diag_test(struct net_device *netdev,
1939f026d8caSVitaly Lifshits struct ethtool_test *eth_test, u64 *data)
1940f026d8caSVitaly Lifshits {
1941f026d8caSVitaly Lifshits struct igc_adapter *adapter = netdev_priv(netdev);
1942f026d8caSVitaly Lifshits bool if_running = netif_running(netdev);
1943f026d8caSVitaly Lifshits
1944f026d8caSVitaly Lifshits if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
194595f96a9fSAndre Guedes netdev_info(adapter->netdev, "Offline testing starting");
1946f026d8caSVitaly Lifshits set_bit(__IGC_TESTING, &adapter->state);
1947f026d8caSVitaly Lifshits
1948f026d8caSVitaly Lifshits /* Link test performed before hardware reset so autoneg doesn't
1949f026d8caSVitaly Lifshits * interfere with test result
1950f026d8caSVitaly Lifshits */
1951f026d8caSVitaly Lifshits if (!igc_link_test(adapter, &data[TEST_LINK]))
1952f026d8caSVitaly Lifshits eth_test->flags |= ETH_TEST_FL_FAILED;
1953f026d8caSVitaly Lifshits
1954f026d8caSVitaly Lifshits if (if_running)
1955f026d8caSVitaly Lifshits igc_close(netdev);
1956f026d8caSVitaly Lifshits else
1957f026d8caSVitaly Lifshits igc_reset(adapter);
1958f026d8caSVitaly Lifshits
195995f96a9fSAndre Guedes netdev_info(adapter->netdev, "Register testing starting");
1960f026d8caSVitaly Lifshits if (!igc_reg_test(adapter, &data[TEST_REG]))
1961f026d8caSVitaly Lifshits eth_test->flags |= ETH_TEST_FL_FAILED;
1962f026d8caSVitaly Lifshits
1963f026d8caSVitaly Lifshits igc_reset(adapter);
1964f026d8caSVitaly Lifshits
196595f96a9fSAndre Guedes netdev_info(adapter->netdev, "EEPROM testing starting");
1966f026d8caSVitaly Lifshits if (!igc_eeprom_test(adapter, &data[TEST_EEP]))
1967f026d8caSVitaly Lifshits eth_test->flags |= ETH_TEST_FL_FAILED;
1968f026d8caSVitaly Lifshits
1969f026d8caSVitaly Lifshits igc_reset(adapter);
1970f026d8caSVitaly Lifshits
1971f026d8caSVitaly Lifshits /* loopback and interrupt tests
1972f026d8caSVitaly Lifshits * will be implemented in the future
1973f026d8caSVitaly Lifshits */
1974f026d8caSVitaly Lifshits data[TEST_LOOP] = 0;
1975f026d8caSVitaly Lifshits data[TEST_IRQ] = 0;
1976f026d8caSVitaly Lifshits
1977f026d8caSVitaly Lifshits clear_bit(__IGC_TESTING, &adapter->state);
1978f026d8caSVitaly Lifshits if (if_running)
1979f026d8caSVitaly Lifshits igc_open(netdev);
1980f026d8caSVitaly Lifshits } else {
198195f96a9fSAndre Guedes netdev_info(adapter->netdev, "Online testing starting");
1982f026d8caSVitaly Lifshits
1983f026d8caSVitaly Lifshits /* register, eeprom, intr and loopback tests not run online */
1984f026d8caSVitaly Lifshits data[TEST_REG] = 0;
1985f026d8caSVitaly Lifshits data[TEST_EEP] = 0;
1986f026d8caSVitaly Lifshits data[TEST_IRQ] = 0;
1987f026d8caSVitaly Lifshits data[TEST_LOOP] = 0;
1988f026d8caSVitaly Lifshits
1989f026d8caSVitaly Lifshits if (!igc_link_test(adapter, &data[TEST_LINK]))
1990f026d8caSVitaly Lifshits eth_test->flags |= ETH_TEST_FL_FAILED;
1991f026d8caSVitaly Lifshits }
1992f026d8caSVitaly Lifshits
1993f026d8caSVitaly Lifshits msleep_interruptible(4 * 1000);
1994f026d8caSVitaly Lifshits }
1995f026d8caSVitaly Lifshits
19968c5ad0daSSasha Neftin static const struct ethtool_ops igc_ethtool_ops = {
1997dbfa497aSJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS,
19987df76bd1SAndre Guedes .get_drvinfo = igc_ethtool_get_drvinfo,
19997df76bd1SAndre Guedes .get_regs_len = igc_ethtool_get_regs_len,
20007df76bd1SAndre Guedes .get_regs = igc_ethtool_get_regs,
20017df76bd1SAndre Guedes .get_wol = igc_ethtool_get_wol,
20027df76bd1SAndre Guedes .set_wol = igc_ethtool_set_wol,
20037df76bd1SAndre Guedes .get_msglevel = igc_ethtool_get_msglevel,
20047df76bd1SAndre Guedes .set_msglevel = igc_ethtool_set_msglevel,
20057df76bd1SAndre Guedes .nway_reset = igc_ethtool_nway_reset,
20067df76bd1SAndre Guedes .get_link = igc_ethtool_get_link,
20077df76bd1SAndre Guedes .get_eeprom_len = igc_ethtool_get_eeprom_len,
20087df76bd1SAndre Guedes .get_eeprom = igc_ethtool_get_eeprom,
20097df76bd1SAndre Guedes .set_eeprom = igc_ethtool_set_eeprom,
20107df76bd1SAndre Guedes .get_ringparam = igc_ethtool_get_ringparam,
20117df76bd1SAndre Guedes .set_ringparam = igc_ethtool_set_ringparam,
20127df76bd1SAndre Guedes .get_pauseparam = igc_ethtool_get_pauseparam,
20137df76bd1SAndre Guedes .set_pauseparam = igc_ethtool_set_pauseparam,
20147df76bd1SAndre Guedes .get_strings = igc_ethtool_get_strings,
20157df76bd1SAndre Guedes .get_sset_count = igc_ethtool_get_sset_count,
20167df76bd1SAndre Guedes .get_ethtool_stats = igc_ethtool_get_stats,
20177df76bd1SAndre Guedes .get_coalesce = igc_ethtool_get_coalesce,
20187df76bd1SAndre Guedes .set_coalesce = igc_ethtool_set_coalesce,
20197df76bd1SAndre Guedes .get_rxnfc = igc_ethtool_get_rxnfc,
20207df76bd1SAndre Guedes .set_rxnfc = igc_ethtool_set_rxnfc,
20217df76bd1SAndre Guedes .get_rxfh_indir_size = igc_ethtool_get_rxfh_indir_size,
20227df76bd1SAndre Guedes .get_rxfh = igc_ethtool_get_rxfh,
20237df76bd1SAndre Guedes .set_rxfh = igc_ethtool_set_rxfh,
20247df76bd1SAndre Guedes .get_ts_info = igc_ethtool_get_ts_info,
20257df76bd1SAndre Guedes .get_channels = igc_ethtool_get_channels,
20267df76bd1SAndre Guedes .set_channels = igc_ethtool_set_channels,
20277df76bd1SAndre Guedes .get_priv_flags = igc_ethtool_get_priv_flags,
20287df76bd1SAndre Guedes .set_priv_flags = igc_ethtool_set_priv_flags,
202993ec439aSSasha Neftin .get_eee = igc_ethtool_get_eee,
203093ec439aSSasha Neftin .set_eee = igc_ethtool_set_eee,
20318c5ad0daSSasha Neftin .begin = igc_ethtool_begin,
20328c5ad0daSSasha Neftin .complete = igc_ethtool_complete,
20337df76bd1SAndre Guedes .get_link_ksettings = igc_ethtool_get_link_ksettings,
20347df76bd1SAndre Guedes .set_link_ksettings = igc_ethtool_set_link_ksettings,
20357df76bd1SAndre Guedes .self_test = igc_ethtool_diag_test,
20368c5ad0daSSasha Neftin };
20378c5ad0daSSasha Neftin
igc_ethtool_set_ops(struct net_device * netdev)20387df76bd1SAndre Guedes void igc_ethtool_set_ops(struct net_device *netdev)
20398c5ad0daSSasha Neftin {
20408c5ad0daSSasha Neftin netdev->ethtool_ops = &igc_ethtool_ops;
20418c5ad0daSSasha Neftin }
2042