162306a36Sopenharmony_ci/**********************************************************************
262306a36Sopenharmony_ci * Author: Cavium, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Contact: support@cavium.com
562306a36Sopenharmony_ci *          Please include "LiquidIO" in the subject.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
1162306a36Sopenharmony_ci * published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1662306a36Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
1762306a36Sopenharmony_ci ***********************************************************************/
1862306a36Sopenharmony_ci#include <linux/ethtool.h>
1962306a36Sopenharmony_ci#include <linux/netdevice.h>
2062306a36Sopenharmony_ci#include <linux/net_tstamp.h>
2162306a36Sopenharmony_ci#include <linux/pci.h>
2262306a36Sopenharmony_ci#include "liquidio_common.h"
2362306a36Sopenharmony_ci#include "octeon_droq.h"
2462306a36Sopenharmony_ci#include "octeon_iq.h"
2562306a36Sopenharmony_ci#include "response_manager.h"
2662306a36Sopenharmony_ci#include "octeon_device.h"
2762306a36Sopenharmony_ci#include "octeon_nic.h"
2862306a36Sopenharmony_ci#include "octeon_main.h"
2962306a36Sopenharmony_ci#include "octeon_network.h"
3062306a36Sopenharmony_ci#include "cn66xx_regs.h"
3162306a36Sopenharmony_ci#include "cn66xx_device.h"
3262306a36Sopenharmony_ci#include "cn23xx_pf_device.h"
3362306a36Sopenharmony_ci#include "cn23xx_vf_device.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic int lio_reset_queues(struct net_device *netdev, uint32_t num_qs);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistruct oct_intrmod_resp {
3862306a36Sopenharmony_ci	u64     rh;
3962306a36Sopenharmony_ci	struct oct_intrmod_cfg intrmod;
4062306a36Sopenharmony_ci	u64     status;
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistruct oct_mdio_cmd_resp {
4462306a36Sopenharmony_ci	u64 rh;
4562306a36Sopenharmony_ci	struct oct_mdio_cmd resp;
4662306a36Sopenharmony_ci	u64 status;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define OCT_MDIO45_RESP_SIZE   (sizeof(struct oct_mdio_cmd_resp))
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* Octeon's interface mode of operation */
5262306a36Sopenharmony_cienum {
5362306a36Sopenharmony_ci	INTERFACE_MODE_DISABLED,
5462306a36Sopenharmony_ci	INTERFACE_MODE_RGMII,
5562306a36Sopenharmony_ci	INTERFACE_MODE_GMII,
5662306a36Sopenharmony_ci	INTERFACE_MODE_SPI,
5762306a36Sopenharmony_ci	INTERFACE_MODE_PCIE,
5862306a36Sopenharmony_ci	INTERFACE_MODE_XAUI,
5962306a36Sopenharmony_ci	INTERFACE_MODE_SGMII,
6062306a36Sopenharmony_ci	INTERFACE_MODE_PICMG,
6162306a36Sopenharmony_ci	INTERFACE_MODE_NPI,
6262306a36Sopenharmony_ci	INTERFACE_MODE_LOOP,
6362306a36Sopenharmony_ci	INTERFACE_MODE_SRIO,
6462306a36Sopenharmony_ci	INTERFACE_MODE_ILK,
6562306a36Sopenharmony_ci	INTERFACE_MODE_RXAUI,
6662306a36Sopenharmony_ci	INTERFACE_MODE_QSGMII,
6762306a36Sopenharmony_ci	INTERFACE_MODE_AGL,
6862306a36Sopenharmony_ci	INTERFACE_MODE_XLAUI,
6962306a36Sopenharmony_ci	INTERFACE_MODE_XFI,
7062306a36Sopenharmony_ci	INTERFACE_MODE_10G_KR,
7162306a36Sopenharmony_ci	INTERFACE_MODE_40G_KR4,
7262306a36Sopenharmony_ci	INTERFACE_MODE_MIXED,
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#define OCT_ETHTOOL_REGDUMP_LEN  4096
7662306a36Sopenharmony_ci#define OCT_ETHTOOL_REGDUMP_LEN_23XX  (4096 * 11)
7762306a36Sopenharmony_ci#define OCT_ETHTOOL_REGDUMP_LEN_23XX_VF  (4096 * 2)
7862306a36Sopenharmony_ci#define OCT_ETHTOOL_REGSVER  1
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/* statistics of PF */
8162306a36Sopenharmony_cistatic const char oct_stats_strings[][ETH_GSTRING_LEN] = {
8262306a36Sopenharmony_ci	"rx_packets",
8362306a36Sopenharmony_ci	"tx_packets",
8462306a36Sopenharmony_ci	"rx_bytes",
8562306a36Sopenharmony_ci	"tx_bytes",
8662306a36Sopenharmony_ci	"rx_errors",
8762306a36Sopenharmony_ci	"tx_errors",
8862306a36Sopenharmony_ci	"rx_dropped",
8962306a36Sopenharmony_ci	"tx_dropped",
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	"tx_total_sent",
9262306a36Sopenharmony_ci	"tx_total_fwd",
9362306a36Sopenharmony_ci	"tx_err_pko",
9462306a36Sopenharmony_ci	"tx_err_pki",
9562306a36Sopenharmony_ci	"tx_err_link",
9662306a36Sopenharmony_ci	"tx_err_drop",
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	"tx_tso",
9962306a36Sopenharmony_ci	"tx_tso_packets",
10062306a36Sopenharmony_ci	"tx_tso_err",
10162306a36Sopenharmony_ci	"tx_vxlan",
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	"tx_mcast",
10462306a36Sopenharmony_ci	"tx_bcast",
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	"mac_tx_total_pkts",
10762306a36Sopenharmony_ci	"mac_tx_total_bytes",
10862306a36Sopenharmony_ci	"mac_tx_mcast_pkts",
10962306a36Sopenharmony_ci	"mac_tx_bcast_pkts",
11062306a36Sopenharmony_ci	"mac_tx_ctl_packets",
11162306a36Sopenharmony_ci	"mac_tx_total_collisions",
11262306a36Sopenharmony_ci	"mac_tx_one_collision",
11362306a36Sopenharmony_ci	"mac_tx_multi_collision",
11462306a36Sopenharmony_ci	"mac_tx_max_collision_fail",
11562306a36Sopenharmony_ci	"mac_tx_max_deferral_fail",
11662306a36Sopenharmony_ci	"mac_tx_fifo_err",
11762306a36Sopenharmony_ci	"mac_tx_runts",
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	"rx_total_rcvd",
12062306a36Sopenharmony_ci	"rx_total_fwd",
12162306a36Sopenharmony_ci	"rx_mcast",
12262306a36Sopenharmony_ci	"rx_bcast",
12362306a36Sopenharmony_ci	"rx_jabber_err",
12462306a36Sopenharmony_ci	"rx_l2_err",
12562306a36Sopenharmony_ci	"rx_frame_err",
12662306a36Sopenharmony_ci	"rx_err_pko",
12762306a36Sopenharmony_ci	"rx_err_link",
12862306a36Sopenharmony_ci	"rx_err_drop",
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	"rx_vxlan",
13162306a36Sopenharmony_ci	"rx_vxlan_err",
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	"rx_lro_pkts",
13462306a36Sopenharmony_ci	"rx_lro_bytes",
13562306a36Sopenharmony_ci	"rx_total_lro",
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	"rx_lro_aborts",
13862306a36Sopenharmony_ci	"rx_lro_aborts_port",
13962306a36Sopenharmony_ci	"rx_lro_aborts_seq",
14062306a36Sopenharmony_ci	"rx_lro_aborts_tsval",
14162306a36Sopenharmony_ci	"rx_lro_aborts_timer",
14262306a36Sopenharmony_ci	"rx_fwd_rate",
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	"mac_rx_total_rcvd",
14562306a36Sopenharmony_ci	"mac_rx_bytes",
14662306a36Sopenharmony_ci	"mac_rx_total_bcst",
14762306a36Sopenharmony_ci	"mac_rx_total_mcst",
14862306a36Sopenharmony_ci	"mac_rx_runts",
14962306a36Sopenharmony_ci	"mac_rx_ctl_packets",
15062306a36Sopenharmony_ci	"mac_rx_fifo_err",
15162306a36Sopenharmony_ci	"mac_rx_dma_drop",
15262306a36Sopenharmony_ci	"mac_rx_fcs_err",
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	"link_state_changes",
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/* statistics of VF */
15862306a36Sopenharmony_cistatic const char oct_vf_stats_strings[][ETH_GSTRING_LEN] = {
15962306a36Sopenharmony_ci	"rx_packets",
16062306a36Sopenharmony_ci	"tx_packets",
16162306a36Sopenharmony_ci	"rx_bytes",
16262306a36Sopenharmony_ci	"tx_bytes",
16362306a36Sopenharmony_ci	"rx_errors",
16462306a36Sopenharmony_ci	"tx_errors",
16562306a36Sopenharmony_ci	"rx_dropped",
16662306a36Sopenharmony_ci	"tx_dropped",
16762306a36Sopenharmony_ci	"rx_mcast",
16862306a36Sopenharmony_ci	"tx_mcast",
16962306a36Sopenharmony_ci	"rx_bcast",
17062306a36Sopenharmony_ci	"tx_bcast",
17162306a36Sopenharmony_ci	"link_state_changes",
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/* statistics of host tx queue */
17562306a36Sopenharmony_cistatic const char oct_iq_stats_strings[][ETH_GSTRING_LEN] = {
17662306a36Sopenharmony_ci	"packets",
17762306a36Sopenharmony_ci	"bytes",
17862306a36Sopenharmony_ci	"dropped",
17962306a36Sopenharmony_ci	"iq_busy",
18062306a36Sopenharmony_ci	"sgentry_sent",
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	"fw_instr_posted",
18362306a36Sopenharmony_ci	"fw_instr_processed",
18462306a36Sopenharmony_ci	"fw_instr_dropped",
18562306a36Sopenharmony_ci	"fw_bytes_sent",
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	"tso",
18862306a36Sopenharmony_ci	"vxlan",
18962306a36Sopenharmony_ci	"txq_restart",
19062306a36Sopenharmony_ci};
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci/* statistics of host rx queue */
19362306a36Sopenharmony_cistatic const char oct_droq_stats_strings[][ETH_GSTRING_LEN] = {
19462306a36Sopenharmony_ci	"packets",
19562306a36Sopenharmony_ci	"bytes",
19662306a36Sopenharmony_ci	"dropped",
19762306a36Sopenharmony_ci	"dropped_nomem",
19862306a36Sopenharmony_ci	"dropped_toomany",
19962306a36Sopenharmony_ci	"fw_dropped",
20062306a36Sopenharmony_ci	"fw_pkts_received",
20162306a36Sopenharmony_ci	"fw_bytes_received",
20262306a36Sopenharmony_ci	"fw_dropped_nodispatch",
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	"vxlan",
20562306a36Sopenharmony_ci	"buffer_alloc_failure",
20662306a36Sopenharmony_ci};
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/* LiquidIO driver private flags */
20962306a36Sopenharmony_cistatic const char oct_priv_flags_strings[][ETH_GSTRING_LEN] = {
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci#define OCTNIC_NCMD_AUTONEG_ON  0x1
21362306a36Sopenharmony_ci#define OCTNIC_NCMD_PHY_ON      0x2
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic int lio_get_link_ksettings(struct net_device *netdev,
21662306a36Sopenharmony_ci				  struct ethtool_link_ksettings *ecmd)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
21962306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
22062306a36Sopenharmony_ci	struct oct_link_info *linfo;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	linfo = &lio->linfo;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	ethtool_link_ksettings_zero_link_mode(ecmd, supported);
22562306a36Sopenharmony_ci	ethtool_link_ksettings_zero_link_mode(ecmd, advertising);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	switch (linfo->link.s.phy_type) {
22862306a36Sopenharmony_ci	case LIO_PHY_PORT_TP:
22962306a36Sopenharmony_ci		ecmd->base.port = PORT_TP;
23062306a36Sopenharmony_ci		ecmd->base.autoneg = AUTONEG_DISABLE;
23162306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, supported, TP);
23262306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, supported, Pause);
23362306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, supported,
23462306a36Sopenharmony_ci						     10000baseT_Full);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, advertising, Pause);
23762306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, advertising,
23862306a36Sopenharmony_ci						     10000baseT_Full);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		break;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	case LIO_PHY_PORT_FIBRE:
24362306a36Sopenharmony_ci		if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI ||
24462306a36Sopenharmony_ci		    linfo->link.s.if_mode == INTERFACE_MODE_RXAUI ||
24562306a36Sopenharmony_ci		    linfo->link.s.if_mode == INTERFACE_MODE_XLAUI ||
24662306a36Sopenharmony_ci		    linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
24762306a36Sopenharmony_ci			dev_dbg(&oct->pci_dev->dev, "ecmd->base.transceiver is XCVR_EXTERNAL\n");
24862306a36Sopenharmony_ci			ecmd->base.transceiver = XCVR_EXTERNAL;
24962306a36Sopenharmony_ci		} else {
25062306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev, "Unknown link interface mode: %d\n",
25162306a36Sopenharmony_ci				linfo->link.s.if_mode);
25262306a36Sopenharmony_ci		}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		ecmd->base.port = PORT_FIBRE;
25562306a36Sopenharmony_ci		ecmd->base.autoneg = AUTONEG_DISABLE;
25662306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, supported, FIBRE);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, supported, Pause);
25962306a36Sopenharmony_ci		ethtool_link_ksettings_add_link_mode(ecmd, advertising, Pause);
26062306a36Sopenharmony_ci		if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
26162306a36Sopenharmony_ci		    oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
26262306a36Sopenharmony_ci			if (OCTEON_CN23XX_PF(oct)) {
26362306a36Sopenharmony_ci				ethtool_link_ksettings_add_link_mode
26462306a36Sopenharmony_ci					(ecmd, supported, 25000baseSR_Full);
26562306a36Sopenharmony_ci				ethtool_link_ksettings_add_link_mode
26662306a36Sopenharmony_ci					(ecmd, supported, 25000baseKR_Full);
26762306a36Sopenharmony_ci				ethtool_link_ksettings_add_link_mode
26862306a36Sopenharmony_ci					(ecmd, supported, 25000baseCR_Full);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci				if (oct->no_speed_setting == 0)  {
27162306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
27262306a36Sopenharmony_ci						(ecmd, supported,
27362306a36Sopenharmony_ci						 10000baseSR_Full);
27462306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
27562306a36Sopenharmony_ci						(ecmd, supported,
27662306a36Sopenharmony_ci						 10000baseKR_Full);
27762306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
27862306a36Sopenharmony_ci						(ecmd, supported,
27962306a36Sopenharmony_ci						 10000baseCR_Full);
28062306a36Sopenharmony_ci				}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci				if (oct->no_speed_setting == 0) {
28362306a36Sopenharmony_ci					liquidio_get_speed(lio);
28462306a36Sopenharmony_ci					liquidio_get_fec(lio);
28562306a36Sopenharmony_ci				} else {
28662306a36Sopenharmony_ci					oct->speed_setting = 25;
28762306a36Sopenharmony_ci				}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci				if (oct->speed_setting == 10) {
29062306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
29162306a36Sopenharmony_ci						(ecmd, advertising,
29262306a36Sopenharmony_ci						 10000baseSR_Full);
29362306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
29462306a36Sopenharmony_ci						(ecmd, advertising,
29562306a36Sopenharmony_ci						 10000baseKR_Full);
29662306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
29762306a36Sopenharmony_ci						(ecmd, advertising,
29862306a36Sopenharmony_ci						 10000baseCR_Full);
29962306a36Sopenharmony_ci				}
30062306a36Sopenharmony_ci				if (oct->speed_setting == 25) {
30162306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
30262306a36Sopenharmony_ci						(ecmd, advertising,
30362306a36Sopenharmony_ci						 25000baseSR_Full);
30462306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
30562306a36Sopenharmony_ci						(ecmd, advertising,
30662306a36Sopenharmony_ci						 25000baseKR_Full);
30762306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
30862306a36Sopenharmony_ci						(ecmd, advertising,
30962306a36Sopenharmony_ci						 25000baseCR_Full);
31062306a36Sopenharmony_ci				}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci				if (oct->no_speed_setting)
31362306a36Sopenharmony_ci					break;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci				ethtool_link_ksettings_add_link_mode
31662306a36Sopenharmony_ci					(ecmd, supported, FEC_RS);
31762306a36Sopenharmony_ci				ethtool_link_ksettings_add_link_mode
31862306a36Sopenharmony_ci					(ecmd, supported, FEC_NONE);
31962306a36Sopenharmony_ci					/*FEC_OFF*/
32062306a36Sopenharmony_ci				if (oct->props[lio->ifidx].fec == 1) {
32162306a36Sopenharmony_ci					/* ETHTOOL_FEC_RS */
32262306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
32362306a36Sopenharmony_ci						(ecmd, advertising, FEC_RS);
32462306a36Sopenharmony_ci				} else {
32562306a36Sopenharmony_ci					/* ETHTOOL_FEC_OFF */
32662306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
32762306a36Sopenharmony_ci						(ecmd, advertising, FEC_NONE);
32862306a36Sopenharmony_ci				}
32962306a36Sopenharmony_ci			} else { /* VF */
33062306a36Sopenharmony_ci				if (linfo->link.s.speed == 10000) {
33162306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
33262306a36Sopenharmony_ci						(ecmd, supported,
33362306a36Sopenharmony_ci						 10000baseSR_Full);
33462306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
33562306a36Sopenharmony_ci						(ecmd, supported,
33662306a36Sopenharmony_ci						 10000baseKR_Full);
33762306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
33862306a36Sopenharmony_ci						(ecmd, supported,
33962306a36Sopenharmony_ci						 10000baseCR_Full);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
34262306a36Sopenharmony_ci						(ecmd, advertising,
34362306a36Sopenharmony_ci						 10000baseSR_Full);
34462306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
34562306a36Sopenharmony_ci						(ecmd, advertising,
34662306a36Sopenharmony_ci						 10000baseKR_Full);
34762306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
34862306a36Sopenharmony_ci						(ecmd, advertising,
34962306a36Sopenharmony_ci						 10000baseCR_Full);
35062306a36Sopenharmony_ci				}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci				if (linfo->link.s.speed == 25000) {
35362306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
35462306a36Sopenharmony_ci						(ecmd, supported,
35562306a36Sopenharmony_ci						 25000baseSR_Full);
35662306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
35762306a36Sopenharmony_ci						(ecmd, supported,
35862306a36Sopenharmony_ci						 25000baseKR_Full);
35962306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
36062306a36Sopenharmony_ci						(ecmd, supported,
36162306a36Sopenharmony_ci						 25000baseCR_Full);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
36462306a36Sopenharmony_ci						(ecmd, advertising,
36562306a36Sopenharmony_ci						 25000baseSR_Full);
36662306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
36762306a36Sopenharmony_ci						(ecmd, advertising,
36862306a36Sopenharmony_ci						 25000baseKR_Full);
36962306a36Sopenharmony_ci					ethtool_link_ksettings_add_link_mode
37062306a36Sopenharmony_ci						(ecmd, advertising,
37162306a36Sopenharmony_ci						 25000baseCR_Full);
37262306a36Sopenharmony_ci				}
37362306a36Sopenharmony_ci			}
37462306a36Sopenharmony_ci		} else {
37562306a36Sopenharmony_ci			ethtool_link_ksettings_add_link_mode(ecmd, supported,
37662306a36Sopenharmony_ci							     10000baseT_Full);
37762306a36Sopenharmony_ci			ethtool_link_ksettings_add_link_mode(ecmd, advertising,
37862306a36Sopenharmony_ci							     10000baseT_Full);
37962306a36Sopenharmony_ci		}
38062306a36Sopenharmony_ci		break;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (linfo->link.s.link_up) {
38462306a36Sopenharmony_ci		ecmd->base.speed = linfo->link.s.speed;
38562306a36Sopenharmony_ci		ecmd->base.duplex = linfo->link.s.duplex;
38662306a36Sopenharmony_ci	} else {
38762306a36Sopenharmony_ci		ecmd->base.speed = SPEED_UNKNOWN;
38862306a36Sopenharmony_ci		ecmd->base.duplex = DUPLEX_UNKNOWN;
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	return 0;
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cistatic int lio_set_link_ksettings(struct net_device *netdev,
39562306a36Sopenharmony_ci				  const struct ethtool_link_ksettings *ecmd)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	const int speed = ecmd->base.speed;
39862306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
39962306a36Sopenharmony_ci	struct oct_link_info *linfo;
40062306a36Sopenharmony_ci	struct octeon_device *oct;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	oct = lio->oct_dev;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	linfo = &lio->linfo;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (!(oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
40762306a36Sopenharmony_ci	      oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID))
40862306a36Sopenharmony_ci		return -EOPNOTSUPP;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (oct->no_speed_setting) {
41162306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Changing speed is not supported\n",
41262306a36Sopenharmony_ci			__func__);
41362306a36Sopenharmony_ci		return -EOPNOTSUPP;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if ((ecmd->base.duplex != DUPLEX_UNKNOWN &&
41762306a36Sopenharmony_ci	     ecmd->base.duplex != linfo->link.s.duplex) ||
41862306a36Sopenharmony_ci	     ecmd->base.autoneg != AUTONEG_DISABLE ||
41962306a36Sopenharmony_ci	    (ecmd->base.speed != 10000 && ecmd->base.speed != 25000 &&
42062306a36Sopenharmony_ci	     ecmd->base.speed != SPEED_UNKNOWN))
42162306a36Sopenharmony_ci		return -EOPNOTSUPP;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if ((oct->speed_boot == speed / 1000) &&
42462306a36Sopenharmony_ci	    oct->speed_boot == oct->speed_setting)
42562306a36Sopenharmony_ci		return 0;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	liquidio_set_speed(lio, speed / 1000);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Port speed is set to %dG\n",
43062306a36Sopenharmony_ci		oct->speed_setting);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	return 0;
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic void
43662306a36Sopenharmony_cilio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	struct lio *lio;
43962306a36Sopenharmony_ci	struct octeon_device *oct;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	lio = GET_LIO(netdev);
44262306a36Sopenharmony_ci	oct = lio->oct_dev;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
44562306a36Sopenharmony_ci	strcpy(drvinfo->driver, "liquidio");
44662306a36Sopenharmony_ci	strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
44762306a36Sopenharmony_ci		ETHTOOL_FWVERS_LEN);
44862306a36Sopenharmony_ci	strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic void
45262306a36Sopenharmony_cilio_get_vf_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
45362306a36Sopenharmony_ci{
45462306a36Sopenharmony_ci	struct octeon_device *oct;
45562306a36Sopenharmony_ci	struct lio *lio;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	lio = GET_LIO(netdev);
45862306a36Sopenharmony_ci	oct = lio->oct_dev;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
46162306a36Sopenharmony_ci	strcpy(drvinfo->driver, "liquidio_vf");
46262306a36Sopenharmony_ci	strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
46362306a36Sopenharmony_ci		ETHTOOL_FWVERS_LEN);
46462306a36Sopenharmony_ci	strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic int
46862306a36Sopenharmony_cilio_send_queue_count_update(struct net_device *netdev, uint32_t num_queues)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
47162306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
47262306a36Sopenharmony_ci	struct octnic_ctrl_pkt nctrl;
47362306a36Sopenharmony_ci	int ret = 0;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	nctrl.ncmd.u64 = 0;
47862306a36Sopenharmony_ci	nctrl.ncmd.s.cmd = OCTNET_CMD_QUEUE_COUNT_CTL;
47962306a36Sopenharmony_ci	nctrl.ncmd.s.param1 = num_queues;
48062306a36Sopenharmony_ci	nctrl.ncmd.s.param2 = num_queues;
48162306a36Sopenharmony_ci	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
48262306a36Sopenharmony_ci	nctrl.netpndev = (u64)netdev;
48362306a36Sopenharmony_ci	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
48662306a36Sopenharmony_ci	if (ret) {
48762306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Failed to send Queue reset command (ret: 0x%x)\n",
48862306a36Sopenharmony_ci			ret);
48962306a36Sopenharmony_ci		return -1;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	return 0;
49362306a36Sopenharmony_ci}
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_cistatic void
49662306a36Sopenharmony_cilio_ethtool_get_channels(struct net_device *dev,
49762306a36Sopenharmony_ci			 struct ethtool_channels *channel)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct lio *lio = GET_LIO(dev);
50062306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
50162306a36Sopenharmony_ci	u32 max_rx = 0, max_tx = 0, tx_count = 0, rx_count = 0;
50262306a36Sopenharmony_ci	u32 combined_count = 0, max_combined = 0;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
50562306a36Sopenharmony_ci		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci		max_rx = CFG_GET_OQ_MAX_Q(conf6x);
50862306a36Sopenharmony_ci		max_tx = CFG_GET_IQ_MAX_Q(conf6x);
50962306a36Sopenharmony_ci		rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf6x, lio->ifidx);
51062306a36Sopenharmony_ci		tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf6x, lio->ifidx);
51162306a36Sopenharmony_ci	} else if (OCTEON_CN23XX_PF(oct)) {
51262306a36Sopenharmony_ci		if (oct->sriov_info.sriov_enabled) {
51362306a36Sopenharmony_ci			max_combined = lio->linfo.num_txpciq;
51462306a36Sopenharmony_ci		} else {
51562306a36Sopenharmony_ci			struct octeon_config *conf23_pf =
51662306a36Sopenharmony_ci				CHIP_CONF(oct, cn23xx_pf);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci			max_combined = CFG_GET_IQ_MAX_Q(conf23_pf);
51962306a36Sopenharmony_ci		}
52062306a36Sopenharmony_ci		combined_count = oct->num_iqs;
52162306a36Sopenharmony_ci	} else if (OCTEON_CN23XX_VF(oct)) {
52262306a36Sopenharmony_ci		u64 reg_val = 0ULL;
52362306a36Sopenharmony_ci		u64 ctrl = CN23XX_VF_SLI_IQ_PKT_CONTROL64(0);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		reg_val = octeon_read_csr64(oct, ctrl);
52662306a36Sopenharmony_ci		reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
52762306a36Sopenharmony_ci		max_combined = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
52862306a36Sopenharmony_ci		combined_count = oct->num_iqs;
52962306a36Sopenharmony_ci	}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	channel->max_rx = max_rx;
53262306a36Sopenharmony_ci	channel->max_tx = max_tx;
53362306a36Sopenharmony_ci	channel->max_combined = max_combined;
53462306a36Sopenharmony_ci	channel->rx_count = rx_count;
53562306a36Sopenharmony_ci	channel->tx_count = tx_count;
53662306a36Sopenharmony_ci	channel->combined_count = combined_count;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic int
54062306a36Sopenharmony_cilio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs)
54162306a36Sopenharmony_ci{
54262306a36Sopenharmony_ci	struct msix_entry *msix_entries;
54362306a36Sopenharmony_ci	int num_msix_irqs = 0;
54462306a36Sopenharmony_ci	int i;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (!oct->msix_on)
54762306a36Sopenharmony_ci		return 0;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	/* Disable the input and output queues now. No more packets will
55062306a36Sopenharmony_ci	 * arrive from Octeon.
55162306a36Sopenharmony_ci	 */
55262306a36Sopenharmony_ci	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	if (oct->msix_on) {
55562306a36Sopenharmony_ci		if (OCTEON_CN23XX_PF(oct))
55662306a36Sopenharmony_ci			num_msix_irqs = oct->num_msix_irqs - 1;
55762306a36Sopenharmony_ci		else if (OCTEON_CN23XX_VF(oct))
55862306a36Sopenharmony_ci			num_msix_irqs = oct->num_msix_irqs;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci		msix_entries = (struct msix_entry *)oct->msix_entries;
56162306a36Sopenharmony_ci		for (i = 0; i < num_msix_irqs; i++) {
56262306a36Sopenharmony_ci			if (oct->ioq_vector[i].vector) {
56362306a36Sopenharmony_ci				/* clear the affinity_cpumask */
56462306a36Sopenharmony_ci				irq_set_affinity_hint(msix_entries[i].vector,
56562306a36Sopenharmony_ci						      NULL);
56662306a36Sopenharmony_ci				free_irq(msix_entries[i].vector,
56762306a36Sopenharmony_ci					 &oct->ioq_vector[i]);
56862306a36Sopenharmony_ci				oct->ioq_vector[i].vector = 0;
56962306a36Sopenharmony_ci			}
57062306a36Sopenharmony_ci		}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		/* non-iov vector's argument is oct struct */
57362306a36Sopenharmony_ci		if (OCTEON_CN23XX_PF(oct))
57462306a36Sopenharmony_ci			free_irq(msix_entries[i].vector, oct);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		pci_disable_msix(oct->pci_dev);
57762306a36Sopenharmony_ci		kfree(oct->msix_entries);
57862306a36Sopenharmony_ci		oct->msix_entries = NULL;
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	kfree(oct->irq_name_storage);
58262306a36Sopenharmony_ci	oct->irq_name_storage = NULL;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	if (octeon_allocate_ioq_vector(oct, num_ioqs)) {
58562306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "OCTEON: ioq vector allocation failed\n");
58662306a36Sopenharmony_ci		return -1;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	if (octeon_setup_interrupt(oct, num_ioqs)) {
59062306a36Sopenharmony_ci		dev_info(&oct->pci_dev->dev, "Setup interrupt failed\n");
59162306a36Sopenharmony_ci		return -1;
59262306a36Sopenharmony_ci	}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	/* Enable Octeon device interrupts */
59562306a36Sopenharmony_ci	oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	return 0;
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic int
60162306a36Sopenharmony_cilio_ethtool_set_channels(struct net_device *dev,
60262306a36Sopenharmony_ci			 struct ethtool_channels *channel)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	u32 combined_count, max_combined;
60562306a36Sopenharmony_ci	struct lio *lio = GET_LIO(dev);
60662306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
60762306a36Sopenharmony_ci	int stopped = 0;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	if (strcmp(oct->fw_info.liquidio_firmware_version, "1.6.1") < 0) {
61062306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Minimum firmware version required is 1.6.1\n");
61162306a36Sopenharmony_ci		return -EINVAL;
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	if (!channel->combined_count || channel->other_count ||
61562306a36Sopenharmony_ci	    channel->rx_count || channel->tx_count)
61662306a36Sopenharmony_ci		return -EINVAL;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	combined_count = channel->combined_count;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	if (OCTEON_CN23XX_PF(oct)) {
62162306a36Sopenharmony_ci		if (oct->sriov_info.sriov_enabled) {
62262306a36Sopenharmony_ci			max_combined = lio->linfo.num_txpciq;
62362306a36Sopenharmony_ci		} else {
62462306a36Sopenharmony_ci			struct octeon_config *conf23_pf =
62562306a36Sopenharmony_ci				CHIP_CONF(oct,
62662306a36Sopenharmony_ci					  cn23xx_pf);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci			max_combined =
62962306a36Sopenharmony_ci				CFG_GET_IQ_MAX_Q(conf23_pf);
63062306a36Sopenharmony_ci		}
63162306a36Sopenharmony_ci	} else if (OCTEON_CN23XX_VF(oct)) {
63262306a36Sopenharmony_ci		u64 reg_val = 0ULL;
63362306a36Sopenharmony_ci		u64 ctrl = CN23XX_VF_SLI_IQ_PKT_CONTROL64(0);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		reg_val = octeon_read_csr64(oct, ctrl);
63662306a36Sopenharmony_ci		reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
63762306a36Sopenharmony_ci		max_combined = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
63862306a36Sopenharmony_ci	} else {
63962306a36Sopenharmony_ci		return -EINVAL;
64062306a36Sopenharmony_ci	}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	if (combined_count > max_combined || combined_count < 1)
64362306a36Sopenharmony_ci		return -EINVAL;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (combined_count == oct->num_iqs)
64662306a36Sopenharmony_ci		return 0;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	ifstate_set(lio, LIO_IFSTATE_RESETTING);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	if (netif_running(dev)) {
65162306a36Sopenharmony_ci		dev->netdev_ops->ndo_stop(dev);
65262306a36Sopenharmony_ci		stopped = 1;
65362306a36Sopenharmony_ci	}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	if (lio_reset_queues(dev, combined_count))
65662306a36Sopenharmony_ci		return -EINVAL;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	if (stopped)
65962306a36Sopenharmony_ci		dev->netdev_ops->ndo_open(dev);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	ifstate_reset(lio, LIO_IFSTATE_RESETTING);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	return 0;
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_cistatic int lio_get_eeprom_len(struct net_device *netdev)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	u8 buf[192];
66962306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
67062306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
67162306a36Sopenharmony_ci	struct octeon_board_info *board_info;
67262306a36Sopenharmony_ci	int len;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	board_info = (struct octeon_board_info *)(&oct_dev->boardinfo);
67562306a36Sopenharmony_ci	len = sprintf(buf, "boardname:%s serialnum:%s maj:%lld min:%lld\n",
67662306a36Sopenharmony_ci		      board_info->name, board_info->serial_number,
67762306a36Sopenharmony_ci		      board_info->major, board_info->minor);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	return len;
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cistatic int
68362306a36Sopenharmony_cilio_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
68462306a36Sopenharmony_ci	       u8 *bytes)
68562306a36Sopenharmony_ci{
68662306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
68762306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
68862306a36Sopenharmony_ci	struct octeon_board_info *board_info;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	if (eeprom->offset)
69162306a36Sopenharmony_ci		return -EINVAL;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	eeprom->magic = oct_dev->pci_dev->vendor;
69462306a36Sopenharmony_ci	board_info = (struct octeon_board_info *)(&oct_dev->boardinfo);
69562306a36Sopenharmony_ci	sprintf((char *)bytes,
69662306a36Sopenharmony_ci		"boardname:%s serialnum:%s maj:%lld min:%lld\n",
69762306a36Sopenharmony_ci		board_info->name, board_info->serial_number,
69862306a36Sopenharmony_ci		board_info->major, board_info->minor);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	return 0;
70162306a36Sopenharmony_ci}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_cistatic int octnet_gpio_access(struct net_device *netdev, int addr, int val)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
70662306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
70762306a36Sopenharmony_ci	struct octnic_ctrl_pkt nctrl;
70862306a36Sopenharmony_ci	int ret = 0;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	nctrl.ncmd.u64 = 0;
71362306a36Sopenharmony_ci	nctrl.ncmd.s.cmd = OCTNET_CMD_GPIO_ACCESS;
71462306a36Sopenharmony_ci	nctrl.ncmd.s.param1 = addr;
71562306a36Sopenharmony_ci	nctrl.ncmd.s.param2 = val;
71662306a36Sopenharmony_ci	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
71762306a36Sopenharmony_ci	nctrl.netpndev = (u64)netdev;
71862306a36Sopenharmony_ci	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
72162306a36Sopenharmony_ci	if (ret) {
72262306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
72362306a36Sopenharmony_ci			"Failed to configure gpio value, ret=%d\n", ret);
72462306a36Sopenharmony_ci		return -EINVAL;
72562306a36Sopenharmony_ci	}
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	return 0;
72862306a36Sopenharmony_ci}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_cistatic int octnet_id_active(struct net_device *netdev, int val)
73162306a36Sopenharmony_ci{
73262306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
73362306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
73462306a36Sopenharmony_ci	struct octnic_ctrl_pkt nctrl;
73562306a36Sopenharmony_ci	int ret = 0;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	nctrl.ncmd.u64 = 0;
74062306a36Sopenharmony_ci	nctrl.ncmd.s.cmd = OCTNET_CMD_ID_ACTIVE;
74162306a36Sopenharmony_ci	nctrl.ncmd.s.param1 = val;
74262306a36Sopenharmony_ci	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
74362306a36Sopenharmony_ci	nctrl.netpndev = (u64)netdev;
74462306a36Sopenharmony_ci	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
74762306a36Sopenharmony_ci	if (ret) {
74862306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
74962306a36Sopenharmony_ci			"Failed to configure gpio value, ret=%d\n", ret);
75062306a36Sopenharmony_ci		return -EINVAL;
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	return 0;
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci/* This routine provides PHY access routines for
75762306a36Sopenharmony_ci * mdio  clause45 .
75862306a36Sopenharmony_ci */
75962306a36Sopenharmony_cistatic int
76062306a36Sopenharmony_cioctnet_mdio45_access(struct lio *lio, int op, int loc, int *value)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
76362306a36Sopenharmony_ci	struct octeon_soft_command *sc;
76462306a36Sopenharmony_ci	struct oct_mdio_cmd_resp *mdio_cmd_rsp;
76562306a36Sopenharmony_ci	struct oct_mdio_cmd *mdio_cmd;
76662306a36Sopenharmony_ci	int retval = 0;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	sc = (struct octeon_soft_command *)
76962306a36Sopenharmony_ci		octeon_alloc_soft_command(oct_dev,
77062306a36Sopenharmony_ci					  sizeof(struct oct_mdio_cmd),
77162306a36Sopenharmony_ci					  sizeof(struct oct_mdio_cmd_resp), 0);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	if (!sc)
77462306a36Sopenharmony_ci		return -ENOMEM;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	mdio_cmd_rsp = (struct oct_mdio_cmd_resp *)sc->virtrptr;
77762306a36Sopenharmony_ci	mdio_cmd = (struct oct_mdio_cmd *)sc->virtdptr;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	mdio_cmd->op = op;
78062306a36Sopenharmony_ci	mdio_cmd->mdio_addr = loc;
78162306a36Sopenharmony_ci	if (op)
78262306a36Sopenharmony_ci		mdio_cmd->value1 = *value;
78362306a36Sopenharmony_ci	octeon_swap_8B_data((u64 *)mdio_cmd, sizeof(struct oct_mdio_cmd) / 8);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC, OPCODE_NIC_MDIO45,
78862306a36Sopenharmony_ci				    0, 0, 0);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	init_completion(&sc->complete);
79162306a36Sopenharmony_ci	sc->sc_status = OCTEON_REQUEST_PENDING;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	retval = octeon_send_soft_command(oct_dev, sc);
79462306a36Sopenharmony_ci	if (retval == IQ_SEND_FAILED) {
79562306a36Sopenharmony_ci		dev_err(&oct_dev->pci_dev->dev,
79662306a36Sopenharmony_ci			"octnet_mdio45_access instruction failed status: %x\n",
79762306a36Sopenharmony_ci			retval);
79862306a36Sopenharmony_ci		octeon_free_soft_command(oct_dev, sc);
79962306a36Sopenharmony_ci		return -EBUSY;
80062306a36Sopenharmony_ci	} else {
80162306a36Sopenharmony_ci		/* Sleep on a wait queue till the cond flag indicates that the
80262306a36Sopenharmony_ci		 * response arrived
80362306a36Sopenharmony_ci		 */
80462306a36Sopenharmony_ci		retval = wait_for_sc_completion_timeout(oct_dev, sc, 0);
80562306a36Sopenharmony_ci		if (retval)
80662306a36Sopenharmony_ci			return retval;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci		retval = mdio_cmd_rsp->status;
80962306a36Sopenharmony_ci		if (retval) {
81062306a36Sopenharmony_ci			dev_err(&oct_dev->pci_dev->dev,
81162306a36Sopenharmony_ci				"octnet mdio45 access failed: %x\n", retval);
81262306a36Sopenharmony_ci			WRITE_ONCE(sc->caller_is_done, true);
81362306a36Sopenharmony_ci			return -EBUSY;
81462306a36Sopenharmony_ci		}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		octeon_swap_8B_data((u64 *)(&mdio_cmd_rsp->resp),
81762306a36Sopenharmony_ci				    sizeof(struct oct_mdio_cmd) / 8);
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci		if (!op)
82062306a36Sopenharmony_ci			*value = mdio_cmd_rsp->resp.value1;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci		WRITE_ONCE(sc->caller_is_done, true);
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	return retval;
82662306a36Sopenharmony_ci}
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_cistatic int lio_set_phys_id(struct net_device *netdev,
82962306a36Sopenharmony_ci			   enum ethtool_phys_id_state state)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
83262306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
83362306a36Sopenharmony_ci	struct oct_link_info *linfo;
83462306a36Sopenharmony_ci	int value, ret;
83562306a36Sopenharmony_ci	u32 cur_ver;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	linfo = &lio->linfo;
83862306a36Sopenharmony_ci	cur_ver = OCT_FW_VER(oct->fw_info.ver.maj,
83962306a36Sopenharmony_ci			     oct->fw_info.ver.min,
84062306a36Sopenharmony_ci			     oct->fw_info.ver.rev);
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	switch (state) {
84362306a36Sopenharmony_ci	case ETHTOOL_ID_ACTIVE:
84462306a36Sopenharmony_ci		if (oct->chip_id == OCTEON_CN66XX) {
84562306a36Sopenharmony_ci			octnet_gpio_access(netdev, VITESSE_PHY_GPIO_CFG,
84662306a36Sopenharmony_ci					   VITESSE_PHY_GPIO_DRIVEON);
84762306a36Sopenharmony_ci			return 2;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN68XX) {
85062306a36Sopenharmony_ci			/* Save the current LED settings */
85162306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 0,
85262306a36Sopenharmony_ci						   LIO68XX_LED_BEACON_ADDR,
85362306a36Sopenharmony_ci						   &lio->phy_beacon_val);
85462306a36Sopenharmony_ci			if (ret)
85562306a36Sopenharmony_ci				return ret;
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 0,
85862306a36Sopenharmony_ci						   LIO68XX_LED_CTRL_ADDR,
85962306a36Sopenharmony_ci						   &lio->led_ctrl_val);
86062306a36Sopenharmony_ci			if (ret)
86162306a36Sopenharmony_ci				return ret;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci			/* Configure Beacon values */
86462306a36Sopenharmony_ci			value = LIO68XX_LED_BEACON_CFGON;
86562306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 1,
86662306a36Sopenharmony_ci						   LIO68XX_LED_BEACON_ADDR,
86762306a36Sopenharmony_ci						   &value);
86862306a36Sopenharmony_ci			if (ret)
86962306a36Sopenharmony_ci				return ret;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci			value = LIO68XX_LED_CTRL_CFGON;
87262306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 1,
87362306a36Sopenharmony_ci						   LIO68XX_LED_CTRL_ADDR,
87462306a36Sopenharmony_ci						   &value);
87562306a36Sopenharmony_ci			if (ret)
87662306a36Sopenharmony_ci				return ret;
87762306a36Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
87862306a36Sopenharmony_ci			octnet_id_active(netdev, LED_IDENTIFICATION_ON);
87962306a36Sopenharmony_ci			if (linfo->link.s.phy_type == LIO_PHY_PORT_TP &&
88062306a36Sopenharmony_ci			    cur_ver > OCT_FW_VER(1, 7, 2))
88162306a36Sopenharmony_ci				return 2;
88262306a36Sopenharmony_ci			else
88362306a36Sopenharmony_ci				return 0;
88462306a36Sopenharmony_ci		} else {
88562306a36Sopenharmony_ci			return -EINVAL;
88662306a36Sopenharmony_ci		}
88762306a36Sopenharmony_ci		break;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	case ETHTOOL_ID_ON:
89062306a36Sopenharmony_ci		if (oct->chip_id == OCTEON_CN23XX_PF_VID &&
89162306a36Sopenharmony_ci		    linfo->link.s.phy_type == LIO_PHY_PORT_TP &&
89262306a36Sopenharmony_ci		    cur_ver > OCT_FW_VER(1, 7, 2))
89362306a36Sopenharmony_ci			octnet_id_active(netdev, LED_IDENTIFICATION_ON);
89462306a36Sopenharmony_ci		else if (oct->chip_id == OCTEON_CN66XX)
89562306a36Sopenharmony_ci			octnet_gpio_access(netdev, VITESSE_PHY_GPIO_CFG,
89662306a36Sopenharmony_ci					   VITESSE_PHY_GPIO_HIGH);
89762306a36Sopenharmony_ci		else
89862306a36Sopenharmony_ci			return -EINVAL;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci		break;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	case ETHTOOL_ID_OFF:
90362306a36Sopenharmony_ci		if (oct->chip_id == OCTEON_CN23XX_PF_VID &&
90462306a36Sopenharmony_ci		    linfo->link.s.phy_type == LIO_PHY_PORT_TP &&
90562306a36Sopenharmony_ci		    cur_ver > OCT_FW_VER(1, 7, 2))
90662306a36Sopenharmony_ci			octnet_id_active(netdev, LED_IDENTIFICATION_OFF);
90762306a36Sopenharmony_ci		else if (oct->chip_id == OCTEON_CN66XX)
90862306a36Sopenharmony_ci			octnet_gpio_access(netdev, VITESSE_PHY_GPIO_CFG,
90962306a36Sopenharmony_ci					   VITESSE_PHY_GPIO_LOW);
91062306a36Sopenharmony_ci		else
91162306a36Sopenharmony_ci			return -EINVAL;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci		break;
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	case ETHTOOL_ID_INACTIVE:
91662306a36Sopenharmony_ci		if (oct->chip_id == OCTEON_CN66XX) {
91762306a36Sopenharmony_ci			octnet_gpio_access(netdev, VITESSE_PHY_GPIO_CFG,
91862306a36Sopenharmony_ci					   VITESSE_PHY_GPIO_DRIVEOFF);
91962306a36Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN68XX) {
92062306a36Sopenharmony_ci			/* Restore LED settings */
92162306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 1,
92262306a36Sopenharmony_ci						   LIO68XX_LED_CTRL_ADDR,
92362306a36Sopenharmony_ci						   &lio->led_ctrl_val);
92462306a36Sopenharmony_ci			if (ret)
92562306a36Sopenharmony_ci				return ret;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci			ret = octnet_mdio45_access(lio, 1,
92862306a36Sopenharmony_ci						   LIO68XX_LED_BEACON_ADDR,
92962306a36Sopenharmony_ci						   &lio->phy_beacon_val);
93062306a36Sopenharmony_ci			if (ret)
93162306a36Sopenharmony_ci				return ret;
93262306a36Sopenharmony_ci		} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
93362306a36Sopenharmony_ci			octnet_id_active(netdev, LED_IDENTIFICATION_OFF);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci			return 0;
93662306a36Sopenharmony_ci		} else {
93762306a36Sopenharmony_ci			return -EINVAL;
93862306a36Sopenharmony_ci		}
93962306a36Sopenharmony_ci		break;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	default:
94262306a36Sopenharmony_ci		return -EINVAL;
94362306a36Sopenharmony_ci	}
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	return 0;
94662306a36Sopenharmony_ci}
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_cistatic void
94962306a36Sopenharmony_cilio_ethtool_get_ringparam(struct net_device *netdev,
95062306a36Sopenharmony_ci			  struct ethtool_ringparam *ering,
95162306a36Sopenharmony_ci			  struct kernel_ethtool_ringparam *kernel_ering,
95262306a36Sopenharmony_ci			  struct netlink_ext_ack *extack)
95362306a36Sopenharmony_ci{
95462306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
95562306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
95662306a36Sopenharmony_ci	u32 tx_max_pending = 0, rx_max_pending = 0, tx_pending = 0,
95762306a36Sopenharmony_ci	    rx_pending = 0;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
96062306a36Sopenharmony_ci		return;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	if (OCTEON_CN6XXX(oct)) {
96362306a36Sopenharmony_ci		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci		tx_max_pending = CN6XXX_MAX_IQ_DESCRIPTORS;
96662306a36Sopenharmony_ci		rx_max_pending = CN6XXX_MAX_OQ_DESCRIPTORS;
96762306a36Sopenharmony_ci		rx_pending = CFG_GET_NUM_RX_DESCS_NIC_IF(conf6x, lio->ifidx);
96862306a36Sopenharmony_ci		tx_pending = CFG_GET_NUM_TX_DESCS_NIC_IF(conf6x, lio->ifidx);
96962306a36Sopenharmony_ci	} else if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
97062306a36Sopenharmony_ci		tx_max_pending = CN23XX_MAX_IQ_DESCRIPTORS;
97162306a36Sopenharmony_ci		rx_max_pending = CN23XX_MAX_OQ_DESCRIPTORS;
97262306a36Sopenharmony_ci		rx_pending = oct->droq[0]->max_count;
97362306a36Sopenharmony_ci		tx_pending = oct->instr_queue[0]->max_count;
97462306a36Sopenharmony_ci	}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	ering->tx_pending = tx_pending;
97762306a36Sopenharmony_ci	ering->tx_max_pending = tx_max_pending;
97862306a36Sopenharmony_ci	ering->rx_pending = rx_pending;
97962306a36Sopenharmony_ci	ering->rx_max_pending = rx_max_pending;
98062306a36Sopenharmony_ci	ering->rx_mini_pending = 0;
98162306a36Sopenharmony_ci	ering->rx_jumbo_pending = 0;
98262306a36Sopenharmony_ci	ering->rx_mini_max_pending = 0;
98362306a36Sopenharmony_ci	ering->rx_jumbo_max_pending = 0;
98462306a36Sopenharmony_ci}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_cistatic int lio_23xx_reconfigure_queue_count(struct lio *lio)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
98962306a36Sopenharmony_ci	u32 resp_size, data_size;
99062306a36Sopenharmony_ci	struct liquidio_if_cfg_resp *resp;
99162306a36Sopenharmony_ci	struct octeon_soft_command *sc;
99262306a36Sopenharmony_ci	union oct_nic_if_cfg if_cfg;
99362306a36Sopenharmony_ci	struct lio_version *vdata;
99462306a36Sopenharmony_ci	u32 ifidx_or_pfnum;
99562306a36Sopenharmony_ci	int retval;
99662306a36Sopenharmony_ci	int j;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	resp_size = sizeof(struct liquidio_if_cfg_resp);
99962306a36Sopenharmony_ci	data_size = sizeof(struct lio_version);
100062306a36Sopenharmony_ci	sc = (struct octeon_soft_command *)
100162306a36Sopenharmony_ci		octeon_alloc_soft_command(oct, data_size,
100262306a36Sopenharmony_ci					  resp_size, 0);
100362306a36Sopenharmony_ci	if (!sc) {
100462306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Failed to allocate soft command\n",
100562306a36Sopenharmony_ci			__func__);
100662306a36Sopenharmony_ci		return -1;
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
101062306a36Sopenharmony_ci	vdata = (struct lio_version *)sc->virtdptr;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	vdata->major = (__force u16)cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION);
101362306a36Sopenharmony_ci	vdata->minor = (__force u16)cpu_to_be16(LIQUIDIO_BASE_MINOR_VERSION);
101462306a36Sopenharmony_ci	vdata->micro = (__force u16)cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION);
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	ifidx_or_pfnum = oct->pf_num;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if_cfg.u64 = 0;
101962306a36Sopenharmony_ci	if_cfg.s.num_iqueues = oct->sriov_info.num_pf_rings;
102062306a36Sopenharmony_ci	if_cfg.s.num_oqueues = oct->sriov_info.num_pf_rings;
102162306a36Sopenharmony_ci	if_cfg.s.base_queue = oct->sriov_info.pf_srn;
102262306a36Sopenharmony_ci	if_cfg.s.gmx_port_id = oct->pf_num;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	sc->iq_no = 0;
102562306a36Sopenharmony_ci	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
102662306a36Sopenharmony_ci				    OPCODE_NIC_QCOUNT_UPDATE, 0,
102762306a36Sopenharmony_ci				    if_cfg.u64, 0);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	init_completion(&sc->complete);
103062306a36Sopenharmony_ci	sc->sc_status = OCTEON_REQUEST_PENDING;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	retval = octeon_send_soft_command(oct, sc);
103362306a36Sopenharmony_ci	if (retval == IQ_SEND_FAILED) {
103462306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
103562306a36Sopenharmony_ci			"Sending iq/oq config failed status: %x\n",
103662306a36Sopenharmony_ci			retval);
103762306a36Sopenharmony_ci		octeon_free_soft_command(oct, sc);
103862306a36Sopenharmony_ci		return -EIO;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	retval = wait_for_sc_completion_timeout(oct, sc, 0);
104262306a36Sopenharmony_ci	if (retval)
104362306a36Sopenharmony_ci		return retval;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	retval = resp->status;
104662306a36Sopenharmony_ci	if (retval) {
104762306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
104862306a36Sopenharmony_ci			"iq/oq config failed: %x\n", retval);
104962306a36Sopenharmony_ci		WRITE_ONCE(sc->caller_is_done, true);
105062306a36Sopenharmony_ci		return -1;
105162306a36Sopenharmony_ci	}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	octeon_swap_8B_data((u64 *)(&resp->cfg_info),
105462306a36Sopenharmony_ci			    (sizeof(struct liquidio_if_cfg_info)) >> 3);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	lio->ifidx = ifidx_or_pfnum;
105762306a36Sopenharmony_ci	lio->linfo.num_rxpciq = hweight64(resp->cfg_info.iqmask);
105862306a36Sopenharmony_ci	lio->linfo.num_txpciq = hweight64(resp->cfg_info.iqmask);
105962306a36Sopenharmony_ci	for (j = 0; j < lio->linfo.num_rxpciq; j++) {
106062306a36Sopenharmony_ci		lio->linfo.rxpciq[j].u64 =
106162306a36Sopenharmony_ci			resp->cfg_info.linfo.rxpciq[j].u64;
106262306a36Sopenharmony_ci	}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	for (j = 0; j < lio->linfo.num_txpciq; j++) {
106562306a36Sopenharmony_ci		lio->linfo.txpciq[j].u64 =
106662306a36Sopenharmony_ci			resp->cfg_info.linfo.txpciq[j].u64;
106762306a36Sopenharmony_ci	}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr;
107062306a36Sopenharmony_ci	lio->linfo.gmxport = resp->cfg_info.linfo.gmxport;
107162306a36Sopenharmony_ci	lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64;
107262306a36Sopenharmony_ci	lio->txq = lio->linfo.txpciq[0].s.q_no;
107362306a36Sopenharmony_ci	lio->rxq = lio->linfo.rxpciq[0].s.q_no;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	dev_info(&oct->pci_dev->dev, "Queue count updated to %d\n",
107662306a36Sopenharmony_ci		 lio->linfo.num_rxpciq);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	WRITE_ONCE(sc->caller_is_done, true);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	return 0;
108162306a36Sopenharmony_ci}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_cistatic int lio_reset_queues(struct net_device *netdev, uint32_t num_qs)
108462306a36Sopenharmony_ci{
108562306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
108662306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
108762306a36Sopenharmony_ci	int i, queue_count_update = 0;
108862306a36Sopenharmony_ci	struct napi_struct *napi, *n;
108962306a36Sopenharmony_ci	int ret;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	schedule_timeout_uninterruptible(msecs_to_jiffies(100));
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	if (wait_for_pending_requests(oct))
109462306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "There were pending requests\n");
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	if (lio_wait_for_instr_fetch(oct))
109762306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	if (octeon_set_io_queues_off(oct)) {
110062306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Setting io queues off failed\n");
110162306a36Sopenharmony_ci		return -1;
110262306a36Sopenharmony_ci	}
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	/* Disable the input and output queues now. No more packets will
110562306a36Sopenharmony_ci	 * arrive from Octeon.
110662306a36Sopenharmony_ci	 */
110762306a36Sopenharmony_ci	oct->fn_list.disable_io_queues(oct);
110862306a36Sopenharmony_ci	/* Delete NAPI */
110962306a36Sopenharmony_ci	list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
111062306a36Sopenharmony_ci		netif_napi_del(napi);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	if (num_qs != oct->num_iqs) {
111362306a36Sopenharmony_ci		ret = netif_set_real_num_rx_queues(netdev, num_qs);
111462306a36Sopenharmony_ci		if (ret) {
111562306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev,
111662306a36Sopenharmony_ci				"Setting real number rx failed\n");
111762306a36Sopenharmony_ci			return ret;
111862306a36Sopenharmony_ci		}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci		ret = netif_set_real_num_tx_queues(netdev, num_qs);
112162306a36Sopenharmony_ci		if (ret) {
112262306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev,
112362306a36Sopenharmony_ci				"Setting real number tx failed\n");
112462306a36Sopenharmony_ci			return ret;
112562306a36Sopenharmony_ci		}
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci		/* The value of queue_count_update decides whether it is the
112862306a36Sopenharmony_ci		 * queue count or the descriptor count that is being
112962306a36Sopenharmony_ci		 * re-configured.
113062306a36Sopenharmony_ci		 */
113162306a36Sopenharmony_ci		queue_count_update = 1;
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	/* Re-configuration of queues can happen in two scenarios, SRIOV enabled
113562306a36Sopenharmony_ci	 * and SRIOV disabled. Few things like recreating queue zero, resetting
113662306a36Sopenharmony_ci	 * glists and IRQs are required for both. For the latter, some more
113762306a36Sopenharmony_ci	 * steps like updating sriov_info for the octeon device need to be done.
113862306a36Sopenharmony_ci	 */
113962306a36Sopenharmony_ci	if (queue_count_update) {
114062306a36Sopenharmony_ci		cleanup_rx_oom_poll_fn(netdev);
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci		lio_delete_glists(lio);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci		/* Delete mbox for PF which is SRIOV disabled because sriov_info
114562306a36Sopenharmony_ci		 * will be now changed.
114662306a36Sopenharmony_ci		 */
114762306a36Sopenharmony_ci		if ((OCTEON_CN23XX_PF(oct)) && !oct->sriov_info.sriov_enabled)
114862306a36Sopenharmony_ci			oct->fn_list.free_mbox(oct);
114962306a36Sopenharmony_ci	}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
115262306a36Sopenharmony_ci		if (!(oct->io_qmask.oq & BIT_ULL(i)))
115362306a36Sopenharmony_ci			continue;
115462306a36Sopenharmony_ci		octeon_delete_droq(oct, i);
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
115862306a36Sopenharmony_ci		if (!(oct->io_qmask.iq & BIT_ULL(i)))
115962306a36Sopenharmony_ci			continue;
116062306a36Sopenharmony_ci		octeon_delete_instr_queue(oct, i);
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	if (queue_count_update) {
116462306a36Sopenharmony_ci		/* For PF re-configure sriov related information */
116562306a36Sopenharmony_ci		if ((OCTEON_CN23XX_PF(oct)) &&
116662306a36Sopenharmony_ci		    !oct->sriov_info.sriov_enabled) {
116762306a36Sopenharmony_ci			oct->sriov_info.num_pf_rings = num_qs;
116862306a36Sopenharmony_ci			if (cn23xx_sriov_config(oct)) {
116962306a36Sopenharmony_ci				dev_err(&oct->pci_dev->dev,
117062306a36Sopenharmony_ci					"Queue reset aborted: SRIOV config failed\n");
117162306a36Sopenharmony_ci				return -1;
117262306a36Sopenharmony_ci			}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci			num_qs = oct->sriov_info.num_pf_rings;
117562306a36Sopenharmony_ci		}
117662306a36Sopenharmony_ci	}
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	if (oct->fn_list.setup_device_regs(oct)) {
117962306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Failed to configure device registers\n");
118062306a36Sopenharmony_ci		return -1;
118162306a36Sopenharmony_ci	}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	/* The following are needed in case of queue count re-configuration and
118462306a36Sopenharmony_ci	 * not for descriptor count re-configuration.
118562306a36Sopenharmony_ci	 */
118662306a36Sopenharmony_ci	if (queue_count_update) {
118762306a36Sopenharmony_ci		if (octeon_setup_instr_queues(oct))
118862306a36Sopenharmony_ci			return -1;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci		if (octeon_setup_output_queues(oct))
119162306a36Sopenharmony_ci			return -1;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci		/* Recreating mbox for PF that is SRIOV disabled */
119462306a36Sopenharmony_ci		if (OCTEON_CN23XX_PF(oct) && !oct->sriov_info.sriov_enabled) {
119562306a36Sopenharmony_ci			if (oct->fn_list.setup_mbox(oct)) {
119662306a36Sopenharmony_ci				dev_err(&oct->pci_dev->dev, "Mailbox setup failed\n");
119762306a36Sopenharmony_ci				return -1;
119862306a36Sopenharmony_ci			}
119962306a36Sopenharmony_ci		}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci		/* Deleting and recreating IRQs whether the interface is SRIOV
120262306a36Sopenharmony_ci		 * enabled or disabled.
120362306a36Sopenharmony_ci		 */
120462306a36Sopenharmony_ci		if (lio_irq_reallocate_irqs(oct, num_qs)) {
120562306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev, "IRQs could not be allocated\n");
120662306a36Sopenharmony_ci			return -1;
120762306a36Sopenharmony_ci		}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci		/* Enable the input and output queues for this Octeon device */
121062306a36Sopenharmony_ci		if (oct->fn_list.enable_io_queues(oct)) {
121162306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev, "Failed to enable input/output queues\n");
121262306a36Sopenharmony_ci			return -1;
121362306a36Sopenharmony_ci		}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci		for (i = 0; i < oct->num_oqs; i++)
121662306a36Sopenharmony_ci			writel(oct->droq[i]->max_count,
121762306a36Sopenharmony_ci			       oct->droq[i]->pkts_credit_reg);
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci		/* Informing firmware about the new queue count. It is required
122062306a36Sopenharmony_ci		 * for firmware to allocate more number of queues than those at
122162306a36Sopenharmony_ci		 * load time.
122262306a36Sopenharmony_ci		 */
122362306a36Sopenharmony_ci		if (OCTEON_CN23XX_PF(oct) && !oct->sriov_info.sriov_enabled) {
122462306a36Sopenharmony_ci			if (lio_23xx_reconfigure_queue_count(lio))
122562306a36Sopenharmony_ci				return -1;
122662306a36Sopenharmony_ci		}
122762306a36Sopenharmony_ci	}
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	/* Once firmware is aware of the new value, queues can be recreated */
123062306a36Sopenharmony_ci	if (liquidio_setup_io_queues(oct, 0, num_qs, num_qs)) {
123162306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "I/O queues creation failed\n");
123262306a36Sopenharmony_ci		return -1;
123362306a36Sopenharmony_ci	}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	if (queue_count_update) {
123662306a36Sopenharmony_ci		if (lio_setup_glists(oct, lio, num_qs)) {
123762306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev, "Gather list allocation failed\n");
123862306a36Sopenharmony_ci			return -1;
123962306a36Sopenharmony_ci		}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci		if (setup_rx_oom_poll_fn(netdev)) {
124262306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev, "lio_setup_rx_oom_poll_fn failed\n");
124362306a36Sopenharmony_ci			return 1;
124462306a36Sopenharmony_ci		}
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci		/* Send firmware the information about new number of queues
124762306a36Sopenharmony_ci		 * if the interface is a VF or a PF that is SRIOV enabled.
124862306a36Sopenharmony_ci		 */
124962306a36Sopenharmony_ci		if (oct->sriov_info.sriov_enabled || OCTEON_CN23XX_VF(oct))
125062306a36Sopenharmony_ci			if (lio_send_queue_count_update(netdev, num_qs))
125162306a36Sopenharmony_ci				return -1;
125262306a36Sopenharmony_ci	}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	return 0;
125562306a36Sopenharmony_ci}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_cistatic int
125862306a36Sopenharmony_cilio_ethtool_set_ringparam(struct net_device *netdev,
125962306a36Sopenharmony_ci			  struct ethtool_ringparam *ering,
126062306a36Sopenharmony_ci			  struct kernel_ethtool_ringparam *kernel_ering,
126162306a36Sopenharmony_ci			  struct netlink_ext_ack *extack)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	u32 rx_count, tx_count, rx_count_old, tx_count_old;
126462306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
126562306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
126662306a36Sopenharmony_ci	int stopped = 0;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	if (!OCTEON_CN23XX_PF(oct) && !OCTEON_CN23XX_VF(oct))
126962306a36Sopenharmony_ci		return -EINVAL;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	if (ering->rx_mini_pending || ering->rx_jumbo_pending)
127262306a36Sopenharmony_ci		return -EINVAL;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	rx_count = clamp_t(u32, ering->rx_pending, CN23XX_MIN_OQ_DESCRIPTORS,
127562306a36Sopenharmony_ci			   CN23XX_MAX_OQ_DESCRIPTORS);
127662306a36Sopenharmony_ci	tx_count = clamp_t(u32, ering->tx_pending, CN23XX_MIN_IQ_DESCRIPTORS,
127762306a36Sopenharmony_ci			   CN23XX_MAX_IQ_DESCRIPTORS);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	rx_count_old = oct->droq[0]->max_count;
128062306a36Sopenharmony_ci	tx_count_old = oct->instr_queue[0]->max_count;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	if (rx_count == rx_count_old && tx_count == tx_count_old)
128362306a36Sopenharmony_ci		return 0;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	ifstate_set(lio, LIO_IFSTATE_RESETTING);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	if (netif_running(netdev)) {
128862306a36Sopenharmony_ci		netdev->netdev_ops->ndo_stop(netdev);
128962306a36Sopenharmony_ci		stopped = 1;
129062306a36Sopenharmony_ci	}
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	/* Change RX/TX DESCS  count */
129362306a36Sopenharmony_ci	if (tx_count != tx_count_old)
129462306a36Sopenharmony_ci		CFG_SET_NUM_TX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
129562306a36Sopenharmony_ci					    tx_count);
129662306a36Sopenharmony_ci	if (rx_count != rx_count_old)
129762306a36Sopenharmony_ci		CFG_SET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
129862306a36Sopenharmony_ci					    rx_count);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	if (lio_reset_queues(netdev, oct->num_iqs))
130162306a36Sopenharmony_ci		goto err_lio_reset_queues;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	if (stopped)
130462306a36Sopenharmony_ci		netdev->netdev_ops->ndo_open(netdev);
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	ifstate_reset(lio, LIO_IFSTATE_RESETTING);
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	return 0;
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_cierr_lio_reset_queues:
131162306a36Sopenharmony_ci	if (tx_count != tx_count_old)
131262306a36Sopenharmony_ci		CFG_SET_NUM_TX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
131362306a36Sopenharmony_ci					    tx_count_old);
131462306a36Sopenharmony_ci	if (rx_count != rx_count_old)
131562306a36Sopenharmony_ci		CFG_SET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
131662306a36Sopenharmony_ci					    rx_count_old);
131762306a36Sopenharmony_ci	return -EINVAL;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cistatic u32 lio_get_msglevel(struct net_device *netdev)
132162306a36Sopenharmony_ci{
132262306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	return lio->msg_enable;
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_cistatic void lio_set_msglevel(struct net_device *netdev, u32 msglvl)
132862306a36Sopenharmony_ci{
132962306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	if ((msglvl ^ lio->msg_enable) & NETIF_MSG_HW) {
133262306a36Sopenharmony_ci		if (msglvl & NETIF_MSG_HW)
133362306a36Sopenharmony_ci			liquidio_set_feature(netdev,
133462306a36Sopenharmony_ci					     OCTNET_CMD_VERBOSE_ENABLE, 0);
133562306a36Sopenharmony_ci		else
133662306a36Sopenharmony_ci			liquidio_set_feature(netdev,
133762306a36Sopenharmony_ci					     OCTNET_CMD_VERBOSE_DISABLE, 0);
133862306a36Sopenharmony_ci	}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	lio->msg_enable = msglvl;
134162306a36Sopenharmony_ci}
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_cistatic void lio_vf_set_msglevel(struct net_device *netdev, u32 msglvl)
134462306a36Sopenharmony_ci{
134562306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	lio->msg_enable = msglvl;
134862306a36Sopenharmony_ci}
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_cistatic void
135162306a36Sopenharmony_cilio_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
135262306a36Sopenharmony_ci{
135362306a36Sopenharmony_ci	/* Notes: Not supporting any auto negotiation in these
135462306a36Sopenharmony_ci	 * drivers. Just report pause frame support.
135562306a36Sopenharmony_ci	 */
135662306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
135762306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	pause->autoneg = 0;
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	pause->tx_pause = oct->tx_pause;
136262306a36Sopenharmony_ci	pause->rx_pause = oct->rx_pause;
136362306a36Sopenharmony_ci}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_cistatic int
136662306a36Sopenharmony_cilio_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
136762306a36Sopenharmony_ci{
136862306a36Sopenharmony_ci	/* Notes: Not supporting any auto negotiation in these
136962306a36Sopenharmony_ci	 * drivers.
137062306a36Sopenharmony_ci	 */
137162306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
137262306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
137362306a36Sopenharmony_ci	struct octnic_ctrl_pkt nctrl;
137462306a36Sopenharmony_ci	struct oct_link_info *linfo = &lio->linfo;
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	int ret = 0;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	if (oct->chip_id != OCTEON_CN23XX_PF_VID)
137962306a36Sopenharmony_ci		return -EINVAL;
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	if (linfo->link.s.duplex == 0) {
138262306a36Sopenharmony_ci		/*no flow control for half duplex*/
138362306a36Sopenharmony_ci		if (pause->rx_pause || pause->tx_pause)
138462306a36Sopenharmony_ci			return -EINVAL;
138562306a36Sopenharmony_ci	}
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	/*do not support autoneg of link flow control*/
138862306a36Sopenharmony_ci	if (pause->autoneg == AUTONEG_ENABLE)
138962306a36Sopenharmony_ci		return -EINVAL;
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	nctrl.ncmd.u64 = 0;
139462306a36Sopenharmony_ci	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_FLOW_CTL;
139562306a36Sopenharmony_ci	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
139662306a36Sopenharmony_ci	nctrl.netpndev = (u64)netdev;
139762306a36Sopenharmony_ci	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	if (pause->rx_pause) {
140062306a36Sopenharmony_ci		/*enable rx pause*/
140162306a36Sopenharmony_ci		nctrl.ncmd.s.param1 = 1;
140262306a36Sopenharmony_ci	} else {
140362306a36Sopenharmony_ci		/*disable rx pause*/
140462306a36Sopenharmony_ci		nctrl.ncmd.s.param1 = 0;
140562306a36Sopenharmony_ci	}
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	if (pause->tx_pause) {
140862306a36Sopenharmony_ci		/*enable tx pause*/
140962306a36Sopenharmony_ci		nctrl.ncmd.s.param2 = 1;
141062306a36Sopenharmony_ci	} else {
141162306a36Sopenharmony_ci		/*disable tx pause*/
141262306a36Sopenharmony_ci		nctrl.ncmd.s.param2 = 0;
141362306a36Sopenharmony_ci	}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
141662306a36Sopenharmony_ci	if (ret) {
141762306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev,
141862306a36Sopenharmony_ci			"Failed to set pause parameter, ret=%d\n", ret);
141962306a36Sopenharmony_ci		return -EINVAL;
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	oct->rx_pause = pause->rx_pause;
142362306a36Sopenharmony_ci	oct->tx_pause = pause->tx_pause;
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	return 0;
142662306a36Sopenharmony_ci}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_cistatic void
142962306a36Sopenharmony_cilio_get_ethtool_stats(struct net_device *netdev,
143062306a36Sopenharmony_ci		      struct ethtool_stats *stats  __attribute__((unused)),
143162306a36Sopenharmony_ci		      u64 *data)
143262306a36Sopenharmony_ci{
143362306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
143462306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
143562306a36Sopenharmony_ci	struct rtnl_link_stats64 lstats;
143662306a36Sopenharmony_ci	int i = 0, j;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
143962306a36Sopenharmony_ci		return;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	netdev->netdev_ops->ndo_get_stats64(netdev, &lstats);
144262306a36Sopenharmony_ci	/*sum of oct->droq[oq_no]->stats->rx_pkts_received */
144362306a36Sopenharmony_ci	data[i++] = lstats.rx_packets;
144462306a36Sopenharmony_ci	/*sum of oct->instr_queue[iq_no]->stats.tx_done */
144562306a36Sopenharmony_ci	data[i++] = lstats.tx_packets;
144662306a36Sopenharmony_ci	/*sum of oct->droq[oq_no]->stats->rx_bytes_received */
144762306a36Sopenharmony_ci	data[i++] = lstats.rx_bytes;
144862306a36Sopenharmony_ci	/*sum of oct->instr_queue[iq_no]->stats.tx_tot_bytes */
144962306a36Sopenharmony_ci	data[i++] = lstats.tx_bytes;
145062306a36Sopenharmony_ci	data[i++] = lstats.rx_errors +
145162306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.fcs_err +
145262306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.jabber_err +
145362306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.l2_err +
145462306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.frame_err;
145562306a36Sopenharmony_ci	data[i++] = lstats.tx_errors;
145662306a36Sopenharmony_ci	/*sum of oct->droq[oq_no]->stats->rx_dropped +
145762306a36Sopenharmony_ci	 *oct->droq[oq_no]->stats->dropped_nodispatch +
145862306a36Sopenharmony_ci	 *oct->droq[oq_no]->stats->dropped_toomany +
145962306a36Sopenharmony_ci	 *oct->droq[oq_no]->stats->dropped_nomem
146062306a36Sopenharmony_ci	 */
146162306a36Sopenharmony_ci	data[i++] = lstats.rx_dropped +
146262306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.fifo_err +
146362306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.dmac_drop +
146462306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.red_drops +
146562306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.fw_err_pko +
146662306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.fw_err_link +
146762306a36Sopenharmony_ci			oct_dev->link_stats.fromwire.fw_err_drop;
146862306a36Sopenharmony_ci	/*sum of oct->instr_queue[iq_no]->stats.tx_dropped */
146962306a36Sopenharmony_ci	data[i++] = lstats.tx_dropped +
147062306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.max_collision_fail +
147162306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.max_deferral_fail +
147262306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.total_collisions +
147362306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.fw_err_pko +
147462306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.fw_err_link +
147562306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.fw_err_drop +
147662306a36Sopenharmony_ci			oct_dev->link_stats.fromhost.fw_err_pki;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	/* firmware tx stats */
147962306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[mdata->from_ifidx].
148062306a36Sopenharmony_ci	 *fromhost.fw_total_sent
148162306a36Sopenharmony_ci	 */
148262306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_total_sent);
148362306a36Sopenharmony_ci	/*per_core_stats[i].link_stats[port].fromwire.fw_total_fwd */
148462306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_total_fwd);
148562306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromhost.fw_err_pko */
148662306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_pko);
148762306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromhost.fw_err_pki */
148862306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_pki);
148962306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromhost.fw_err_link */
149062306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_link);
149162306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
149262306a36Sopenharmony_ci	 *fw_err_drop
149362306a36Sopenharmony_ci	 */
149462306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_drop);
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.fw_tso */
149762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_tso);
149862306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
149962306a36Sopenharmony_ci	 *fw_tso_fwd
150062306a36Sopenharmony_ci	 */
150162306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_tso_fwd);
150262306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
150362306a36Sopenharmony_ci	 *fw_err_tso
150462306a36Sopenharmony_ci	 */
150562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_tso);
150662306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
150762306a36Sopenharmony_ci	 *fw_tx_vxlan
150862306a36Sopenharmony_ci	 */
150962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_tx_vxlan);
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	/* Multicast packets sent by this port */
151262306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromhost.fw_total_mcast_sent;
151362306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromhost.fw_total_bcast_sent;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	/* mac tx statistics */
151662306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT5 */
151762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_pkts_sent);
151862306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT4 */
151962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_bytes_sent);
152062306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT15 */
152162306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.mcast_pkts_sent);
152262306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT14 */
152362306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.bcast_pkts_sent);
152462306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT17 */
152562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.ctl_sent);
152662306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT0 */
152762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_collisions);
152862306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT3 */
152962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.one_collision_sent);
153062306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT2 */
153162306a36Sopenharmony_ci	data[i++] =
153262306a36Sopenharmony_ci		CVM_CAST64(oct_dev->link_stats.fromhost.multi_collision_sent);
153362306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT0 */
153462306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.max_collision_fail);
153562306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT1 */
153662306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.max_deferral_fail);
153762306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT16 */
153862306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fifo_err);
153962306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_TX_STAT6 */
154062306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.runts);
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	/* RX firmware stats */
154362306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
154462306a36Sopenharmony_ci	 *fw_total_rcvd
154562306a36Sopenharmony_ci	 */
154662306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_rcvd);
154762306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
154862306a36Sopenharmony_ci	 *fw_total_fwd
154962306a36Sopenharmony_ci	 */
155062306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_fwd);
155162306a36Sopenharmony_ci	/* Multicast packets received on this port */
155262306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromwire.fw_total_mcast;
155362306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromwire.fw_total_bcast;
155462306a36Sopenharmony_ci	/*per_core_stats[core_id].link_stats[ifidx].fromwire.jabber_err */
155562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.jabber_err);
155662306a36Sopenharmony_ci	/*per_core_stats[core_id].link_stats[ifidx].fromwire.l2_err */
155762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.l2_err);
155862306a36Sopenharmony_ci	/*per_core_stats[core_id].link_stats[ifidx].fromwire.frame_err */
155962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.frame_err);
156062306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
156162306a36Sopenharmony_ci	 *fw_err_pko
156262306a36Sopenharmony_ci	 */
156362306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_pko);
156462306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromwire.fw_err_link */
156562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_link);
156662306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[lro_ctx->ifidx].
156762306a36Sopenharmony_ci	 *fromwire.fw_err_drop
156862306a36Sopenharmony_ci	 */
156962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_drop);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[lro_ctx->ifidx].
157262306a36Sopenharmony_ci	 *fromwire.fw_rx_vxlan
157362306a36Sopenharmony_ci	 */
157462306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_rx_vxlan);
157562306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[lro_ctx->ifidx].
157662306a36Sopenharmony_ci	 *fromwire.fw_rx_vxlan_err
157762306a36Sopenharmony_ci	 */
157862306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_rx_vxlan_err);
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	/* LRO */
158162306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
158262306a36Sopenharmony_ci	 *fw_lro_pkts
158362306a36Sopenharmony_ci	 */
158462306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_pkts);
158562306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
158662306a36Sopenharmony_ci	 *fw_lro_octs
158762306a36Sopenharmony_ci	 */
158862306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_octs);
158962306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromwire.fw_total_lro */
159062306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_lro);
159162306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromwire.fw_lro_aborts */
159262306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts);
159362306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
159462306a36Sopenharmony_ci	 *fw_lro_aborts_port
159562306a36Sopenharmony_ci	 */
159662306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_port);
159762306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
159862306a36Sopenharmony_ci	 *fw_lro_aborts_seq
159962306a36Sopenharmony_ci	 */
160062306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_seq);
160162306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
160262306a36Sopenharmony_ci	 *fw_lro_aborts_tsval
160362306a36Sopenharmony_ci	 */
160462306a36Sopenharmony_ci	data[i++] =
160562306a36Sopenharmony_ci		CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_tsval);
160662306a36Sopenharmony_ci	/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
160762306a36Sopenharmony_ci	 *fw_lro_aborts_timer
160862306a36Sopenharmony_ci	 */
160962306a36Sopenharmony_ci	/* intrmod: packet forward rate */
161062306a36Sopenharmony_ci	data[i++] =
161162306a36Sopenharmony_ci		CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_timer);
161262306a36Sopenharmony_ci	/*per_core_stats[j].link_stats[i].fromwire.fw_lro_aborts */
161362306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fwd_rate);
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	/* mac: link-level stats */
161662306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_RX_STAT0 */
161762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_rcvd);
161862306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_RX_STAT1 */
161962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.bytes_rcvd);
162062306a36Sopenharmony_ci	/*CVMX_PKI_STATX_STAT5 */
162162306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_bcst);
162262306a36Sopenharmony_ci	/*CVMX_PKI_STATX_STAT5 */
162362306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_mcst);
162462306a36Sopenharmony_ci	/*wqe->word2.err_code or wqe->word2.err_level */
162562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.runts);
162662306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_RX_STAT2 */
162762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.ctl_rcvd);
162862306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_RX_STAT6 */
162962306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fifo_err);
163062306a36Sopenharmony_ci	/*CVMX_BGXX_CMRX_RX_STAT4 */
163162306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.dmac_drop);
163262306a36Sopenharmony_ci	/*wqe->word2.err_code or wqe->word2.err_level */
163362306a36Sopenharmony_ci	data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fcs_err);
163462306a36Sopenharmony_ci	/*lio->link_changes*/
163562306a36Sopenharmony_ci	data[i++] = CVM_CAST64(lio->link_changes);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	for (j = 0; j < MAX_OCTEON_INSTR_QUEUES(oct_dev); j++) {
163862306a36Sopenharmony_ci		if (!(oct_dev->io_qmask.iq & BIT_ULL(j)))
163962306a36Sopenharmony_ci			continue;
164062306a36Sopenharmony_ci		/*packets to network port*/
164162306a36Sopenharmony_ci		/*# of packets tx to network */
164262306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
164362306a36Sopenharmony_ci		/*# of bytes tx to network */
164462306a36Sopenharmony_ci		data[i++] =
164562306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_tot_bytes);
164662306a36Sopenharmony_ci		/*# of packets dropped */
164762306a36Sopenharmony_ci		data[i++] =
164862306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_dropped);
164962306a36Sopenharmony_ci		/*# of tx fails due to queue full */
165062306a36Sopenharmony_ci		data[i++] =
165162306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_iq_busy);
165262306a36Sopenharmony_ci		/*XXX gather entries sent */
165362306a36Sopenharmony_ci		data[i++] =
165462306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.sgentry_sent);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci		/*instruction to firmware: data and control */
165762306a36Sopenharmony_ci		/*# of instructions to the queue */
165862306a36Sopenharmony_ci		data[i++] =
165962306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_posted);
166062306a36Sopenharmony_ci		/*# of instructions processed */
166162306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
166262306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.instr_processed);
166362306a36Sopenharmony_ci		/*# of instructions could not be processed */
166462306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
166562306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.instr_dropped);
166662306a36Sopenharmony_ci		/*bytes sent through the queue */
166762306a36Sopenharmony_ci		data[i++] =
166862306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.bytes_sent);
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci		/*tso request*/
167162306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_gso);
167262306a36Sopenharmony_ci		/*vxlan request*/
167362306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_vxlan);
167462306a36Sopenharmony_ci		/*txq restart*/
167562306a36Sopenharmony_ci		data[i++] =
167662306a36Sopenharmony_ci			CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_restart);
167762306a36Sopenharmony_ci	}
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	/* RX */
168062306a36Sopenharmony_ci	for (j = 0; j < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); j++) {
168162306a36Sopenharmony_ci		if (!(oct_dev->io_qmask.oq & BIT_ULL(j)))
168262306a36Sopenharmony_ci			continue;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci		/*packets send to TCP/IP network stack */
168562306a36Sopenharmony_ci		/*# of packets to network stack */
168662306a36Sopenharmony_ci		data[i++] =
168762306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.rx_pkts_received);
168862306a36Sopenharmony_ci		/*# of bytes to network stack */
168962306a36Sopenharmony_ci		data[i++] =
169062306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.rx_bytes_received);
169162306a36Sopenharmony_ci		/*# of packets dropped */
169262306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem +
169362306a36Sopenharmony_ci				       oct_dev->droq[j]->stats.dropped_toomany +
169462306a36Sopenharmony_ci				       oct_dev->droq[j]->stats.rx_dropped);
169562306a36Sopenharmony_ci		data[i++] =
169662306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
169762306a36Sopenharmony_ci		data[i++] =
169862306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
169962306a36Sopenharmony_ci		data[i++] =
170062306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.rx_dropped);
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci		/*control and data path*/
170362306a36Sopenharmony_ci		data[i++] =
170462306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
170562306a36Sopenharmony_ci		data[i++] =
170662306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
170762306a36Sopenharmony_ci		data[i++] =
170862306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci		data[i++] =
171162306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.rx_vxlan);
171262306a36Sopenharmony_ci		data[i++] =
171362306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.rx_alloc_failure);
171462306a36Sopenharmony_ci	}
171562306a36Sopenharmony_ci}
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_cistatic void lio_vf_get_ethtool_stats(struct net_device *netdev,
171862306a36Sopenharmony_ci				     struct ethtool_stats *stats
171962306a36Sopenharmony_ci				     __attribute__((unused)),
172062306a36Sopenharmony_ci				     u64 *data)
172162306a36Sopenharmony_ci{
172262306a36Sopenharmony_ci	struct rtnl_link_stats64 lstats;
172362306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
172462306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
172562306a36Sopenharmony_ci	int i = 0, j, vj;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
172862306a36Sopenharmony_ci		return;
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	netdev->netdev_ops->ndo_get_stats64(netdev, &lstats);
173162306a36Sopenharmony_ci	/* sum of oct->droq[oq_no]->stats->rx_pkts_received */
173262306a36Sopenharmony_ci	data[i++] = lstats.rx_packets;
173362306a36Sopenharmony_ci	/* sum of oct->instr_queue[iq_no]->stats.tx_done */
173462306a36Sopenharmony_ci	data[i++] = lstats.tx_packets;
173562306a36Sopenharmony_ci	/* sum of oct->droq[oq_no]->stats->rx_bytes_received */
173662306a36Sopenharmony_ci	data[i++] = lstats.rx_bytes;
173762306a36Sopenharmony_ci	/* sum of oct->instr_queue[iq_no]->stats.tx_tot_bytes */
173862306a36Sopenharmony_ci	data[i++] = lstats.tx_bytes;
173962306a36Sopenharmony_ci	data[i++] = lstats.rx_errors;
174062306a36Sopenharmony_ci	data[i++] = lstats.tx_errors;
174162306a36Sopenharmony_ci	 /* sum of oct->droq[oq_no]->stats->rx_dropped +
174262306a36Sopenharmony_ci	  * oct->droq[oq_no]->stats->dropped_nodispatch +
174362306a36Sopenharmony_ci	  * oct->droq[oq_no]->stats->dropped_toomany +
174462306a36Sopenharmony_ci	  * oct->droq[oq_no]->stats->dropped_nomem
174562306a36Sopenharmony_ci	  */
174662306a36Sopenharmony_ci	data[i++] = lstats.rx_dropped;
174762306a36Sopenharmony_ci	/* sum of oct->instr_queue[iq_no]->stats.tx_dropped */
174862306a36Sopenharmony_ci	data[i++] = lstats.tx_dropped +
174962306a36Sopenharmony_ci		oct_dev->link_stats.fromhost.fw_err_drop;
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromwire.fw_total_mcast;
175262306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromhost.fw_total_mcast_sent;
175362306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromwire.fw_total_bcast;
175462306a36Sopenharmony_ci	data[i++] = oct_dev->link_stats.fromhost.fw_total_bcast_sent;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	/* lio->link_changes */
175762306a36Sopenharmony_ci	data[i++] = CVM_CAST64(lio->link_changes);
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	for (vj = 0; vj < oct_dev->num_iqs; vj++) {
176062306a36Sopenharmony_ci		j = lio->linfo.txpciq[vj].s.q_no;
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci		/* packets to network port */
176362306a36Sopenharmony_ci		/* # of packets tx to network */
176462306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
176562306a36Sopenharmony_ci		 /* # of bytes tx to network */
176662306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
176762306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.tx_tot_bytes);
176862306a36Sopenharmony_ci		/* # of packets dropped */
176962306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
177062306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.tx_dropped);
177162306a36Sopenharmony_ci		/* # of tx fails due to queue full */
177262306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
177362306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.tx_iq_busy);
177462306a36Sopenharmony_ci		/* XXX gather entries sent */
177562306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
177662306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.sgentry_sent);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		/* instruction to firmware: data and control */
177962306a36Sopenharmony_ci		/* # of instructions to the queue */
178062306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
178162306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.instr_posted);
178262306a36Sopenharmony_ci		/* # of instructions processed */
178362306a36Sopenharmony_ci		data[i++] =
178462306a36Sopenharmony_ci		    CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_processed);
178562306a36Sopenharmony_ci		/* # of instructions could not be processed */
178662306a36Sopenharmony_ci		data[i++] =
178762306a36Sopenharmony_ci		    CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_dropped);
178862306a36Sopenharmony_ci		/* bytes sent through the queue */
178962306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
179062306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.bytes_sent);
179162306a36Sopenharmony_ci		/* tso request */
179262306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_gso);
179362306a36Sopenharmony_ci		/* vxlan request */
179462306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_vxlan);
179562306a36Sopenharmony_ci		/* txq restart */
179662306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
179762306a36Sopenharmony_ci				oct_dev->instr_queue[j]->stats.tx_restart);
179862306a36Sopenharmony_ci	}
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	/* RX */
180162306a36Sopenharmony_ci	for (vj = 0; vj < oct_dev->num_oqs; vj++) {
180262306a36Sopenharmony_ci		j = lio->linfo.rxpciq[vj].s.q_no;
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci		/* packets send to TCP/IP network stack */
180562306a36Sopenharmony_ci		/* # of packets to network stack */
180662306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
180762306a36Sopenharmony_ci				oct_dev->droq[j]->stats.rx_pkts_received);
180862306a36Sopenharmony_ci		/* # of bytes to network stack */
180962306a36Sopenharmony_ci		data[i++] = CVM_CAST64(
181062306a36Sopenharmony_ci				oct_dev->droq[j]->stats.rx_bytes_received);
181162306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem +
181262306a36Sopenharmony_ci				       oct_dev->droq[j]->stats.dropped_toomany +
181362306a36Sopenharmony_ci				       oct_dev->droq[j]->stats.rx_dropped);
181462306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
181562306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
181662306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_dropped);
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci		/* control and data path */
181962306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
182062306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
182162306a36Sopenharmony_ci		data[i++] =
182262306a36Sopenharmony_ci			CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_vxlan);
182562306a36Sopenharmony_ci		data[i++] =
182662306a36Sopenharmony_ci		    CVM_CAST64(oct_dev->droq[j]->stats.rx_alloc_failure);
182762306a36Sopenharmony_ci	}
182862306a36Sopenharmony_ci}
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_cistatic void lio_get_priv_flags_strings(struct lio *lio, u8 *data)
183162306a36Sopenharmony_ci{
183262306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
183362306a36Sopenharmony_ci	int i;
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	switch (oct_dev->chip_id) {
183662306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
183762306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
183862306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(oct_priv_flags_strings); i++) {
183962306a36Sopenharmony_ci			sprintf(data, "%s", oct_priv_flags_strings[i]);
184062306a36Sopenharmony_ci			data += ETH_GSTRING_LEN;
184162306a36Sopenharmony_ci		}
184262306a36Sopenharmony_ci		break;
184362306a36Sopenharmony_ci	case OCTEON_CN68XX:
184462306a36Sopenharmony_ci	case OCTEON_CN66XX:
184562306a36Sopenharmony_ci		break;
184662306a36Sopenharmony_ci	default:
184762306a36Sopenharmony_ci		netif_info(lio, drv, lio->netdev, "Unknown Chip !!\n");
184862306a36Sopenharmony_ci		break;
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci}
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_cistatic void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
185362306a36Sopenharmony_ci{
185462306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
185562306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
185662306a36Sopenharmony_ci	int num_iq_stats, num_oq_stats, i, j;
185762306a36Sopenharmony_ci	int num_stats;
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	switch (stringset) {
186062306a36Sopenharmony_ci	case ETH_SS_STATS:
186162306a36Sopenharmony_ci		num_stats = ARRAY_SIZE(oct_stats_strings);
186262306a36Sopenharmony_ci		for (j = 0; j < num_stats; j++) {
186362306a36Sopenharmony_ci			sprintf(data, "%s", oct_stats_strings[j]);
186462306a36Sopenharmony_ci			data += ETH_GSTRING_LEN;
186562306a36Sopenharmony_ci		}
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci		num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
186862306a36Sopenharmony_ci		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
186962306a36Sopenharmony_ci			if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
187062306a36Sopenharmony_ci				continue;
187162306a36Sopenharmony_ci			for (j = 0; j < num_iq_stats; j++) {
187262306a36Sopenharmony_ci				sprintf(data, "tx-%d-%s", i,
187362306a36Sopenharmony_ci					oct_iq_stats_strings[j]);
187462306a36Sopenharmony_ci				data += ETH_GSTRING_LEN;
187562306a36Sopenharmony_ci			}
187662306a36Sopenharmony_ci		}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci		num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
187962306a36Sopenharmony_ci		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
188062306a36Sopenharmony_ci			if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
188162306a36Sopenharmony_ci				continue;
188262306a36Sopenharmony_ci			for (j = 0; j < num_oq_stats; j++) {
188362306a36Sopenharmony_ci				sprintf(data, "rx-%d-%s", i,
188462306a36Sopenharmony_ci					oct_droq_stats_strings[j]);
188562306a36Sopenharmony_ci				data += ETH_GSTRING_LEN;
188662306a36Sopenharmony_ci			}
188762306a36Sopenharmony_ci		}
188862306a36Sopenharmony_ci		break;
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
189162306a36Sopenharmony_ci		lio_get_priv_flags_strings(lio, data);
189262306a36Sopenharmony_ci		break;
189362306a36Sopenharmony_ci	default:
189462306a36Sopenharmony_ci		netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
189562306a36Sopenharmony_ci		break;
189662306a36Sopenharmony_ci	}
189762306a36Sopenharmony_ci}
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_cistatic void lio_vf_get_strings(struct net_device *netdev, u32 stringset,
190062306a36Sopenharmony_ci			       u8 *data)
190162306a36Sopenharmony_ci{
190262306a36Sopenharmony_ci	int num_iq_stats, num_oq_stats, i, j;
190362306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
190462306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
190562306a36Sopenharmony_ci	int num_stats;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	switch (stringset) {
190862306a36Sopenharmony_ci	case ETH_SS_STATS:
190962306a36Sopenharmony_ci		num_stats = ARRAY_SIZE(oct_vf_stats_strings);
191062306a36Sopenharmony_ci		for (j = 0; j < num_stats; j++) {
191162306a36Sopenharmony_ci			sprintf(data, "%s", oct_vf_stats_strings[j]);
191262306a36Sopenharmony_ci			data += ETH_GSTRING_LEN;
191362306a36Sopenharmony_ci		}
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci		num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
191662306a36Sopenharmony_ci		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
191762306a36Sopenharmony_ci			if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
191862306a36Sopenharmony_ci				continue;
191962306a36Sopenharmony_ci			for (j = 0; j < num_iq_stats; j++) {
192062306a36Sopenharmony_ci				sprintf(data, "tx-%d-%s", i,
192162306a36Sopenharmony_ci					oct_iq_stats_strings[j]);
192262306a36Sopenharmony_ci				data += ETH_GSTRING_LEN;
192362306a36Sopenharmony_ci			}
192462306a36Sopenharmony_ci		}
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci		num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
192762306a36Sopenharmony_ci		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
192862306a36Sopenharmony_ci			if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
192962306a36Sopenharmony_ci				continue;
193062306a36Sopenharmony_ci			for (j = 0; j < num_oq_stats; j++) {
193162306a36Sopenharmony_ci				sprintf(data, "rx-%d-%s", i,
193262306a36Sopenharmony_ci					oct_droq_stats_strings[j]);
193362306a36Sopenharmony_ci				data += ETH_GSTRING_LEN;
193462306a36Sopenharmony_ci			}
193562306a36Sopenharmony_ci		}
193662306a36Sopenharmony_ci		break;
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
193962306a36Sopenharmony_ci		lio_get_priv_flags_strings(lio, data);
194062306a36Sopenharmony_ci		break;
194162306a36Sopenharmony_ci	default:
194262306a36Sopenharmony_ci		netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
194362306a36Sopenharmony_ci		break;
194462306a36Sopenharmony_ci	}
194562306a36Sopenharmony_ci}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_cistatic int lio_get_priv_flags_ss_count(struct lio *lio)
194862306a36Sopenharmony_ci{
194962306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	switch (oct_dev->chip_id) {
195262306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
195362306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
195462306a36Sopenharmony_ci		return ARRAY_SIZE(oct_priv_flags_strings);
195562306a36Sopenharmony_ci	case OCTEON_CN68XX:
195662306a36Sopenharmony_ci	case OCTEON_CN66XX:
195762306a36Sopenharmony_ci		return -EOPNOTSUPP;
195862306a36Sopenharmony_ci	default:
195962306a36Sopenharmony_ci		netif_info(lio, drv, lio->netdev, "Unknown Chip !!\n");
196062306a36Sopenharmony_ci		return -EOPNOTSUPP;
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci}
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_cistatic int lio_get_sset_count(struct net_device *netdev, int sset)
196562306a36Sopenharmony_ci{
196662306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
196762306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci	switch (sset) {
197062306a36Sopenharmony_ci	case ETH_SS_STATS:
197162306a36Sopenharmony_ci		return (ARRAY_SIZE(oct_stats_strings) +
197262306a36Sopenharmony_ci			ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
197362306a36Sopenharmony_ci			ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
197462306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
197562306a36Sopenharmony_ci		return lio_get_priv_flags_ss_count(lio);
197662306a36Sopenharmony_ci	default:
197762306a36Sopenharmony_ci		return -EOPNOTSUPP;
197862306a36Sopenharmony_ci	}
197962306a36Sopenharmony_ci}
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_cistatic int lio_vf_get_sset_count(struct net_device *netdev, int sset)
198262306a36Sopenharmony_ci{
198362306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
198462306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci	switch (sset) {
198762306a36Sopenharmony_ci	case ETH_SS_STATS:
198862306a36Sopenharmony_ci		return (ARRAY_SIZE(oct_vf_stats_strings) +
198962306a36Sopenharmony_ci			ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
199062306a36Sopenharmony_ci			ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
199162306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
199262306a36Sopenharmony_ci		return lio_get_priv_flags_ss_count(lio);
199362306a36Sopenharmony_ci	default:
199462306a36Sopenharmony_ci		return -EOPNOTSUPP;
199562306a36Sopenharmony_ci	}
199662306a36Sopenharmony_ci}
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci/*  get interrupt moderation parameters */
199962306a36Sopenharmony_cistatic int octnet_get_intrmod_cfg(struct lio *lio,
200062306a36Sopenharmony_ci				  struct oct_intrmod_cfg *intr_cfg)
200162306a36Sopenharmony_ci{
200262306a36Sopenharmony_ci	struct octeon_soft_command *sc;
200362306a36Sopenharmony_ci	struct oct_intrmod_resp *resp;
200462306a36Sopenharmony_ci	int retval;
200562306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	/* Alloc soft command */
200862306a36Sopenharmony_ci	sc = (struct octeon_soft_command *)
200962306a36Sopenharmony_ci		octeon_alloc_soft_command(oct_dev,
201062306a36Sopenharmony_ci					  0,
201162306a36Sopenharmony_ci					  sizeof(struct oct_intrmod_resp), 0);
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci	if (!sc)
201462306a36Sopenharmony_ci		return -ENOMEM;
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	resp = (struct oct_intrmod_resp *)sc->virtrptr;
201762306a36Sopenharmony_ci	memset(resp, 0, sizeof(struct oct_intrmod_resp));
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC,
202262306a36Sopenharmony_ci				    OPCODE_NIC_INTRMOD_PARAMS, 0, 0, 0);
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci	init_completion(&sc->complete);
202562306a36Sopenharmony_ci	sc->sc_status = OCTEON_REQUEST_PENDING;
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	retval = octeon_send_soft_command(oct_dev, sc);
202862306a36Sopenharmony_ci	if (retval == IQ_SEND_FAILED) {
202962306a36Sopenharmony_ci		octeon_free_soft_command(oct_dev, sc);
203062306a36Sopenharmony_ci		return -EINVAL;
203162306a36Sopenharmony_ci	}
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	/* Sleep on a wait queue till the cond flag indicates that the
203462306a36Sopenharmony_ci	 * response arrived or timed-out.
203562306a36Sopenharmony_ci	 */
203662306a36Sopenharmony_ci	retval = wait_for_sc_completion_timeout(oct_dev, sc, 0);
203762306a36Sopenharmony_ci	if (retval)
203862306a36Sopenharmony_ci		return -ENODEV;
203962306a36Sopenharmony_ci
204062306a36Sopenharmony_ci	if (resp->status) {
204162306a36Sopenharmony_ci		dev_err(&oct_dev->pci_dev->dev,
204262306a36Sopenharmony_ci			"Get interrupt moderation parameters failed\n");
204362306a36Sopenharmony_ci		WRITE_ONCE(sc->caller_is_done, true);
204462306a36Sopenharmony_ci		return -ENODEV;
204562306a36Sopenharmony_ci	}
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	octeon_swap_8B_data((u64 *)&resp->intrmod,
204862306a36Sopenharmony_ci			    (sizeof(struct oct_intrmod_cfg)) / 8);
204962306a36Sopenharmony_ci	memcpy(intr_cfg, &resp->intrmod, sizeof(struct oct_intrmod_cfg));
205062306a36Sopenharmony_ci	WRITE_ONCE(sc->caller_is_done, true);
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci	return 0;
205362306a36Sopenharmony_ci}
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci/*  Configure interrupt moderation parameters */
205662306a36Sopenharmony_cistatic int octnet_set_intrmod_cfg(struct lio *lio,
205762306a36Sopenharmony_ci				  struct oct_intrmod_cfg *intr_cfg)
205862306a36Sopenharmony_ci{
205962306a36Sopenharmony_ci	struct octeon_soft_command *sc;
206062306a36Sopenharmony_ci	struct oct_intrmod_cfg *cfg;
206162306a36Sopenharmony_ci	int retval;
206262306a36Sopenharmony_ci	struct octeon_device *oct_dev = lio->oct_dev;
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	/* Alloc soft command */
206562306a36Sopenharmony_ci	sc = (struct octeon_soft_command *)
206662306a36Sopenharmony_ci		octeon_alloc_soft_command(oct_dev,
206762306a36Sopenharmony_ci					  sizeof(struct oct_intrmod_cfg),
206862306a36Sopenharmony_ci					  16, 0);
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	if (!sc)
207162306a36Sopenharmony_ci		return -ENOMEM;
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	cfg = (struct oct_intrmod_cfg *)sc->virtdptr;
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	memcpy(cfg, intr_cfg, sizeof(struct oct_intrmod_cfg));
207662306a36Sopenharmony_ci	octeon_swap_8B_data((u64 *)cfg, (sizeof(struct oct_intrmod_cfg)) / 8);
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci	octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC,
208162306a36Sopenharmony_ci				    OPCODE_NIC_INTRMOD_CFG, 0, 0, 0);
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	init_completion(&sc->complete);
208462306a36Sopenharmony_ci	sc->sc_status = OCTEON_REQUEST_PENDING;
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	retval = octeon_send_soft_command(oct_dev, sc);
208762306a36Sopenharmony_ci	if (retval == IQ_SEND_FAILED) {
208862306a36Sopenharmony_ci		octeon_free_soft_command(oct_dev, sc);
208962306a36Sopenharmony_ci		return -EINVAL;
209062306a36Sopenharmony_ci	}
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	/* Sleep on a wait queue till the cond flag indicates that the
209362306a36Sopenharmony_ci	 * response arrived or timed-out.
209462306a36Sopenharmony_ci	 */
209562306a36Sopenharmony_ci	retval = wait_for_sc_completion_timeout(oct_dev, sc, 0);
209662306a36Sopenharmony_ci	if (retval)
209762306a36Sopenharmony_ci		return retval;
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	retval = sc->sc_status;
210062306a36Sopenharmony_ci	if (retval == 0) {
210162306a36Sopenharmony_ci		dev_info(&oct_dev->pci_dev->dev,
210262306a36Sopenharmony_ci			 "Rx-Adaptive Interrupt moderation %s\n",
210362306a36Sopenharmony_ci			 (intr_cfg->rx_enable) ?
210462306a36Sopenharmony_ci			 "enabled" : "disabled");
210562306a36Sopenharmony_ci		WRITE_ONCE(sc->caller_is_done, true);
210662306a36Sopenharmony_ci		return 0;
210762306a36Sopenharmony_ci	}
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	dev_err(&oct_dev->pci_dev->dev,
211062306a36Sopenharmony_ci		"intrmod config failed. Status: %x\n", retval);
211162306a36Sopenharmony_ci	WRITE_ONCE(sc->caller_is_done, true);
211262306a36Sopenharmony_ci	return -ENODEV;
211362306a36Sopenharmony_ci}
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_cistatic int lio_get_intr_coalesce(struct net_device *netdev,
211662306a36Sopenharmony_ci				 struct ethtool_coalesce *intr_coal,
211762306a36Sopenharmony_ci				 struct kernel_ethtool_coalesce *kernel_coal,
211862306a36Sopenharmony_ci				 struct netlink_ext_ack *extack)
211962306a36Sopenharmony_ci{
212062306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
212162306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
212262306a36Sopenharmony_ci	struct octeon_instr_queue *iq;
212362306a36Sopenharmony_ci	struct oct_intrmod_cfg intrmod_cfg;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	if (octnet_get_intrmod_cfg(lio, &intrmod_cfg))
212662306a36Sopenharmony_ci		return -ENODEV;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	switch (oct->chip_id) {
212962306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
213062306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID: {
213162306a36Sopenharmony_ci		if (!intrmod_cfg.rx_enable) {
213262306a36Sopenharmony_ci			intr_coal->rx_coalesce_usecs = oct->rx_coalesce_usecs;
213362306a36Sopenharmony_ci			intr_coal->rx_max_coalesced_frames =
213462306a36Sopenharmony_ci				oct->rx_max_coalesced_frames;
213562306a36Sopenharmony_ci		}
213662306a36Sopenharmony_ci		if (!intrmod_cfg.tx_enable)
213762306a36Sopenharmony_ci			intr_coal->tx_max_coalesced_frames =
213862306a36Sopenharmony_ci				oct->tx_max_coalesced_frames;
213962306a36Sopenharmony_ci		break;
214062306a36Sopenharmony_ci	}
214162306a36Sopenharmony_ci	case OCTEON_CN68XX:
214262306a36Sopenharmony_ci	case OCTEON_CN66XX: {
214362306a36Sopenharmony_ci		struct octeon_cn6xxx *cn6xxx =
214462306a36Sopenharmony_ci			(struct octeon_cn6xxx *)oct->chip;
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci		if (!intrmod_cfg.rx_enable) {
214762306a36Sopenharmony_ci			intr_coal->rx_coalesce_usecs =
214862306a36Sopenharmony_ci				CFG_GET_OQ_INTR_TIME(cn6xxx->conf);
214962306a36Sopenharmony_ci			intr_coal->rx_max_coalesced_frames =
215062306a36Sopenharmony_ci				CFG_GET_OQ_INTR_PKT(cn6xxx->conf);
215162306a36Sopenharmony_ci		}
215262306a36Sopenharmony_ci		iq = oct->instr_queue[lio->linfo.txpciq[0].s.q_no];
215362306a36Sopenharmony_ci		intr_coal->tx_max_coalesced_frames = iq->fill_threshold;
215462306a36Sopenharmony_ci		break;
215562306a36Sopenharmony_ci	}
215662306a36Sopenharmony_ci	default:
215762306a36Sopenharmony_ci		netif_info(lio, drv, lio->netdev, "Unknown Chip !!\n");
215862306a36Sopenharmony_ci		return -EINVAL;
215962306a36Sopenharmony_ci	}
216062306a36Sopenharmony_ci	if (intrmod_cfg.rx_enable) {
216162306a36Sopenharmony_ci		intr_coal->use_adaptive_rx_coalesce =
216262306a36Sopenharmony_ci			intrmod_cfg.rx_enable;
216362306a36Sopenharmony_ci		intr_coal->rate_sample_interval =
216462306a36Sopenharmony_ci			intrmod_cfg.check_intrvl;
216562306a36Sopenharmony_ci		intr_coal->pkt_rate_high =
216662306a36Sopenharmony_ci			intrmod_cfg.maxpkt_ratethr;
216762306a36Sopenharmony_ci		intr_coal->pkt_rate_low =
216862306a36Sopenharmony_ci			intrmod_cfg.minpkt_ratethr;
216962306a36Sopenharmony_ci		intr_coal->rx_max_coalesced_frames_high =
217062306a36Sopenharmony_ci			intrmod_cfg.rx_maxcnt_trigger;
217162306a36Sopenharmony_ci		intr_coal->rx_coalesce_usecs_high =
217262306a36Sopenharmony_ci			intrmod_cfg.rx_maxtmr_trigger;
217362306a36Sopenharmony_ci		intr_coal->rx_coalesce_usecs_low =
217462306a36Sopenharmony_ci			intrmod_cfg.rx_mintmr_trigger;
217562306a36Sopenharmony_ci		intr_coal->rx_max_coalesced_frames_low =
217662306a36Sopenharmony_ci			intrmod_cfg.rx_mincnt_trigger;
217762306a36Sopenharmony_ci	}
217862306a36Sopenharmony_ci	if ((OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) &&
217962306a36Sopenharmony_ci	    (intrmod_cfg.tx_enable)) {
218062306a36Sopenharmony_ci		intr_coal->use_adaptive_tx_coalesce =
218162306a36Sopenharmony_ci			intrmod_cfg.tx_enable;
218262306a36Sopenharmony_ci		intr_coal->tx_max_coalesced_frames_high =
218362306a36Sopenharmony_ci			intrmod_cfg.tx_maxcnt_trigger;
218462306a36Sopenharmony_ci		intr_coal->tx_max_coalesced_frames_low =
218562306a36Sopenharmony_ci			intrmod_cfg.tx_mincnt_trigger;
218662306a36Sopenharmony_ci	}
218762306a36Sopenharmony_ci	return 0;
218862306a36Sopenharmony_ci}
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci/* Enable/Disable auto interrupt Moderation */
219162306a36Sopenharmony_cistatic int oct_cfg_adaptive_intr(struct lio *lio,
219262306a36Sopenharmony_ci				 struct oct_intrmod_cfg *intrmod_cfg,
219362306a36Sopenharmony_ci				 struct ethtool_coalesce *intr_coal)
219462306a36Sopenharmony_ci{
219562306a36Sopenharmony_ci	int ret = 0;
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	if (intrmod_cfg->rx_enable || intrmod_cfg->tx_enable) {
219862306a36Sopenharmony_ci		intrmod_cfg->check_intrvl = intr_coal->rate_sample_interval;
219962306a36Sopenharmony_ci		intrmod_cfg->maxpkt_ratethr = intr_coal->pkt_rate_high;
220062306a36Sopenharmony_ci		intrmod_cfg->minpkt_ratethr = intr_coal->pkt_rate_low;
220162306a36Sopenharmony_ci	}
220262306a36Sopenharmony_ci	if (intrmod_cfg->rx_enable) {
220362306a36Sopenharmony_ci		intrmod_cfg->rx_maxcnt_trigger =
220462306a36Sopenharmony_ci			intr_coal->rx_max_coalesced_frames_high;
220562306a36Sopenharmony_ci		intrmod_cfg->rx_maxtmr_trigger =
220662306a36Sopenharmony_ci			intr_coal->rx_coalesce_usecs_high;
220762306a36Sopenharmony_ci		intrmod_cfg->rx_mintmr_trigger =
220862306a36Sopenharmony_ci			intr_coal->rx_coalesce_usecs_low;
220962306a36Sopenharmony_ci		intrmod_cfg->rx_mincnt_trigger =
221062306a36Sopenharmony_ci			intr_coal->rx_max_coalesced_frames_low;
221162306a36Sopenharmony_ci	}
221262306a36Sopenharmony_ci	if (intrmod_cfg->tx_enable) {
221362306a36Sopenharmony_ci		intrmod_cfg->tx_maxcnt_trigger =
221462306a36Sopenharmony_ci			intr_coal->tx_max_coalesced_frames_high;
221562306a36Sopenharmony_ci		intrmod_cfg->tx_mincnt_trigger =
221662306a36Sopenharmony_ci			intr_coal->tx_max_coalesced_frames_low;
221762306a36Sopenharmony_ci	}
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci	ret = octnet_set_intrmod_cfg(lio, intrmod_cfg);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	return ret;
222262306a36Sopenharmony_ci}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_cistatic int
222562306a36Sopenharmony_cioct_cfg_rx_intrcnt(struct lio *lio,
222662306a36Sopenharmony_ci		   struct oct_intrmod_cfg *intrmod,
222762306a36Sopenharmony_ci		   struct ethtool_coalesce *intr_coal)
222862306a36Sopenharmony_ci{
222962306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
223062306a36Sopenharmony_ci	u32 rx_max_coalesced_frames;
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	/* Config Cnt based interrupt values */
223362306a36Sopenharmony_ci	switch (oct->chip_id) {
223462306a36Sopenharmony_ci	case OCTEON_CN68XX:
223562306a36Sopenharmony_ci	case OCTEON_CN66XX: {
223662306a36Sopenharmony_ci		struct octeon_cn6xxx *cn6xxx =
223762306a36Sopenharmony_ci			(struct octeon_cn6xxx *)oct->chip;
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci		if (!intr_coal->rx_max_coalesced_frames)
224062306a36Sopenharmony_ci			rx_max_coalesced_frames = CN6XXX_OQ_INTR_PKT;
224162306a36Sopenharmony_ci		else
224262306a36Sopenharmony_ci			rx_max_coalesced_frames =
224362306a36Sopenharmony_ci				intr_coal->rx_max_coalesced_frames;
224462306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_OQ_INT_LEVEL_PKTS,
224562306a36Sopenharmony_ci				 rx_max_coalesced_frames);
224662306a36Sopenharmony_ci		CFG_SET_OQ_INTR_PKT(cn6xxx->conf, rx_max_coalesced_frames);
224762306a36Sopenharmony_ci		break;
224862306a36Sopenharmony_ci	}
224962306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID: {
225062306a36Sopenharmony_ci		int q_no;
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci		if (!intr_coal->rx_max_coalesced_frames)
225362306a36Sopenharmony_ci			rx_max_coalesced_frames = intrmod->rx_frames;
225462306a36Sopenharmony_ci		else
225562306a36Sopenharmony_ci			rx_max_coalesced_frames =
225662306a36Sopenharmony_ci			    intr_coal->rx_max_coalesced_frames;
225762306a36Sopenharmony_ci		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
225862306a36Sopenharmony_ci			q_no += oct->sriov_info.pf_srn;
225962306a36Sopenharmony_ci			octeon_write_csr64(
226062306a36Sopenharmony_ci			    oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
226162306a36Sopenharmony_ci			    (octeon_read_csr64(
226262306a36Sopenharmony_ci				 oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no)) &
226362306a36Sopenharmony_ci			     (0x3fffff00000000UL)) |
226462306a36Sopenharmony_ci				(rx_max_coalesced_frames - 1));
226562306a36Sopenharmony_ci			/*consider setting resend bit*/
226662306a36Sopenharmony_ci		}
226762306a36Sopenharmony_ci		intrmod->rx_frames = rx_max_coalesced_frames;
226862306a36Sopenharmony_ci		oct->rx_max_coalesced_frames = rx_max_coalesced_frames;
226962306a36Sopenharmony_ci		break;
227062306a36Sopenharmony_ci	}
227162306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID: {
227262306a36Sopenharmony_ci		int q_no;
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci		if (!intr_coal->rx_max_coalesced_frames)
227562306a36Sopenharmony_ci			rx_max_coalesced_frames = intrmod->rx_frames;
227662306a36Sopenharmony_ci		else
227762306a36Sopenharmony_ci			rx_max_coalesced_frames =
227862306a36Sopenharmony_ci			    intr_coal->rx_max_coalesced_frames;
227962306a36Sopenharmony_ci		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
228062306a36Sopenharmony_ci			octeon_write_csr64(
228162306a36Sopenharmony_ci			    oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
228262306a36Sopenharmony_ci			    (octeon_read_csr64(
228362306a36Sopenharmony_ci				 oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no)) &
228462306a36Sopenharmony_ci			     (0x3fffff00000000UL)) |
228562306a36Sopenharmony_ci				(rx_max_coalesced_frames - 1));
228662306a36Sopenharmony_ci			/*consider writing to resend bit here*/
228762306a36Sopenharmony_ci		}
228862306a36Sopenharmony_ci		intrmod->rx_frames = rx_max_coalesced_frames;
228962306a36Sopenharmony_ci		oct->rx_max_coalesced_frames = rx_max_coalesced_frames;
229062306a36Sopenharmony_ci		break;
229162306a36Sopenharmony_ci	}
229262306a36Sopenharmony_ci	default:
229362306a36Sopenharmony_ci		return -EINVAL;
229462306a36Sopenharmony_ci	}
229562306a36Sopenharmony_ci	return 0;
229662306a36Sopenharmony_ci}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_cistatic int oct_cfg_rx_intrtime(struct lio *lio,
229962306a36Sopenharmony_ci			       struct oct_intrmod_cfg *intrmod,
230062306a36Sopenharmony_ci			       struct ethtool_coalesce *intr_coal)
230162306a36Sopenharmony_ci{
230262306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
230362306a36Sopenharmony_ci	u32 time_threshold, rx_coalesce_usecs;
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	/* Config Time based interrupt values */
230662306a36Sopenharmony_ci	switch (oct->chip_id) {
230762306a36Sopenharmony_ci	case OCTEON_CN68XX:
230862306a36Sopenharmony_ci	case OCTEON_CN66XX: {
230962306a36Sopenharmony_ci		struct octeon_cn6xxx *cn6xxx =
231062306a36Sopenharmony_ci			(struct octeon_cn6xxx *)oct->chip;
231162306a36Sopenharmony_ci		if (!intr_coal->rx_coalesce_usecs)
231262306a36Sopenharmony_ci			rx_coalesce_usecs = CN6XXX_OQ_INTR_TIME;
231362306a36Sopenharmony_ci		else
231462306a36Sopenharmony_ci			rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci		time_threshold = lio_cn6xxx_get_oq_ticks(oct,
231762306a36Sopenharmony_ci							 rx_coalesce_usecs);
231862306a36Sopenharmony_ci		octeon_write_csr(oct,
231962306a36Sopenharmony_ci				 CN6XXX_SLI_OQ_INT_LEVEL_TIME,
232062306a36Sopenharmony_ci				 time_threshold);
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci		CFG_SET_OQ_INTR_TIME(cn6xxx->conf, rx_coalesce_usecs);
232362306a36Sopenharmony_ci		break;
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID: {
232662306a36Sopenharmony_ci		u64 time_threshold;
232762306a36Sopenharmony_ci		int q_no;
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci		if (!intr_coal->rx_coalesce_usecs)
233062306a36Sopenharmony_ci			rx_coalesce_usecs = intrmod->rx_usecs;
233162306a36Sopenharmony_ci		else
233262306a36Sopenharmony_ci			rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
233362306a36Sopenharmony_ci		time_threshold =
233462306a36Sopenharmony_ci		    cn23xx_pf_get_oq_ticks(oct, (u32)rx_coalesce_usecs);
233562306a36Sopenharmony_ci		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
233662306a36Sopenharmony_ci			q_no += oct->sriov_info.pf_srn;
233762306a36Sopenharmony_ci			octeon_write_csr64(oct,
233862306a36Sopenharmony_ci					   CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
233962306a36Sopenharmony_ci					   (intrmod->rx_frames |
234062306a36Sopenharmony_ci					    ((u64)time_threshold << 32)));
234162306a36Sopenharmony_ci			/*consider writing to resend bit here*/
234262306a36Sopenharmony_ci		}
234362306a36Sopenharmony_ci		intrmod->rx_usecs = rx_coalesce_usecs;
234462306a36Sopenharmony_ci		oct->rx_coalesce_usecs = rx_coalesce_usecs;
234562306a36Sopenharmony_ci		break;
234662306a36Sopenharmony_ci	}
234762306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID: {
234862306a36Sopenharmony_ci		u64 time_threshold;
234962306a36Sopenharmony_ci		int q_no;
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci		if (!intr_coal->rx_coalesce_usecs)
235262306a36Sopenharmony_ci			rx_coalesce_usecs = intrmod->rx_usecs;
235362306a36Sopenharmony_ci		else
235462306a36Sopenharmony_ci			rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci		time_threshold =
235762306a36Sopenharmony_ci		    cn23xx_vf_get_oq_ticks(oct, (u32)rx_coalesce_usecs);
235862306a36Sopenharmony_ci		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
235962306a36Sopenharmony_ci			octeon_write_csr64(
236062306a36Sopenharmony_ci				oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
236162306a36Sopenharmony_ci				(intrmod->rx_frames |
236262306a36Sopenharmony_ci				 ((u64)time_threshold << 32)));
236362306a36Sopenharmony_ci			/*consider setting resend bit*/
236462306a36Sopenharmony_ci		}
236562306a36Sopenharmony_ci		intrmod->rx_usecs = rx_coalesce_usecs;
236662306a36Sopenharmony_ci		oct->rx_coalesce_usecs = rx_coalesce_usecs;
236762306a36Sopenharmony_ci		break;
236862306a36Sopenharmony_ci	}
236962306a36Sopenharmony_ci	default:
237062306a36Sopenharmony_ci		return -EINVAL;
237162306a36Sopenharmony_ci	}
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_ci	return 0;
237462306a36Sopenharmony_ci}
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_cistatic int
237762306a36Sopenharmony_cioct_cfg_tx_intrcnt(struct lio *lio,
237862306a36Sopenharmony_ci		   struct oct_intrmod_cfg *intrmod,
237962306a36Sopenharmony_ci		   struct ethtool_coalesce *intr_coal)
238062306a36Sopenharmony_ci{
238162306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
238262306a36Sopenharmony_ci	u32 iq_intr_pkt;
238362306a36Sopenharmony_ci	void __iomem *inst_cnt_reg;
238462306a36Sopenharmony_ci	u64 val;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	/* Config Cnt based interrupt values */
238762306a36Sopenharmony_ci	switch (oct->chip_id) {
238862306a36Sopenharmony_ci	case OCTEON_CN68XX:
238962306a36Sopenharmony_ci	case OCTEON_CN66XX:
239062306a36Sopenharmony_ci		break;
239162306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
239262306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID: {
239362306a36Sopenharmony_ci		int q_no;
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci		if (!intr_coal->tx_max_coalesced_frames)
239662306a36Sopenharmony_ci			iq_intr_pkt = CN23XX_DEF_IQ_INTR_THRESHOLD &
239762306a36Sopenharmony_ci				      CN23XX_PKT_IN_DONE_WMARK_MASK;
239862306a36Sopenharmony_ci		else
239962306a36Sopenharmony_ci			iq_intr_pkt = intr_coal->tx_max_coalesced_frames &
240062306a36Sopenharmony_ci				      CN23XX_PKT_IN_DONE_WMARK_MASK;
240162306a36Sopenharmony_ci		for (q_no = 0; q_no < oct->num_iqs; q_no++) {
240262306a36Sopenharmony_ci			inst_cnt_reg = (oct->instr_queue[q_no])->inst_cnt_reg;
240362306a36Sopenharmony_ci			val = readq(inst_cnt_reg);
240462306a36Sopenharmony_ci			/*clear wmark and count.dont want to write count back*/
240562306a36Sopenharmony_ci			val = (val & 0xFFFF000000000000ULL) |
240662306a36Sopenharmony_ci			      ((u64)(iq_intr_pkt - 1)
240762306a36Sopenharmony_ci			       << CN23XX_PKT_IN_DONE_WMARK_BIT_POS);
240862306a36Sopenharmony_ci			writeq(val, inst_cnt_reg);
240962306a36Sopenharmony_ci			/*consider setting resend bit*/
241062306a36Sopenharmony_ci		}
241162306a36Sopenharmony_ci		intrmod->tx_frames = iq_intr_pkt;
241262306a36Sopenharmony_ci		oct->tx_max_coalesced_frames = iq_intr_pkt;
241362306a36Sopenharmony_ci		break;
241462306a36Sopenharmony_ci	}
241562306a36Sopenharmony_ci	default:
241662306a36Sopenharmony_ci		return -EINVAL;
241762306a36Sopenharmony_ci	}
241862306a36Sopenharmony_ci	return 0;
241962306a36Sopenharmony_ci}
242062306a36Sopenharmony_ci
242162306a36Sopenharmony_cistatic int lio_set_intr_coalesce(struct net_device *netdev,
242262306a36Sopenharmony_ci				 struct ethtool_coalesce *intr_coal,
242362306a36Sopenharmony_ci				 struct kernel_ethtool_coalesce *kernel_coal,
242462306a36Sopenharmony_ci				 struct netlink_ext_ack *extack)
242562306a36Sopenharmony_ci{
242662306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
242762306a36Sopenharmony_ci	int ret;
242862306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
242962306a36Sopenharmony_ci	struct oct_intrmod_cfg intrmod = {0};
243062306a36Sopenharmony_ci	u32 j, q_no;
243162306a36Sopenharmony_ci	int db_max, db_min;
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	switch (oct->chip_id) {
243462306a36Sopenharmony_ci	case OCTEON_CN68XX:
243562306a36Sopenharmony_ci	case OCTEON_CN66XX:
243662306a36Sopenharmony_ci		db_min = CN6XXX_DB_MIN;
243762306a36Sopenharmony_ci		db_max = CN6XXX_DB_MAX;
243862306a36Sopenharmony_ci		if ((intr_coal->tx_max_coalesced_frames >= db_min) &&
243962306a36Sopenharmony_ci		    (intr_coal->tx_max_coalesced_frames <= db_max)) {
244062306a36Sopenharmony_ci			for (j = 0; j < lio->linfo.num_txpciq; j++) {
244162306a36Sopenharmony_ci				q_no = lio->linfo.txpciq[j].s.q_no;
244262306a36Sopenharmony_ci				oct->instr_queue[q_no]->fill_threshold =
244362306a36Sopenharmony_ci					intr_coal->tx_max_coalesced_frames;
244462306a36Sopenharmony_ci			}
244562306a36Sopenharmony_ci		} else {
244662306a36Sopenharmony_ci			dev_err(&oct->pci_dev->dev,
244762306a36Sopenharmony_ci				"LIQUIDIO: Invalid tx-frames:%d. Range is min:%d max:%d\n",
244862306a36Sopenharmony_ci				intr_coal->tx_max_coalesced_frames,
244962306a36Sopenharmony_ci				db_min, db_max);
245062306a36Sopenharmony_ci			return -EINVAL;
245162306a36Sopenharmony_ci		}
245262306a36Sopenharmony_ci		break;
245362306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
245462306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
245562306a36Sopenharmony_ci		break;
245662306a36Sopenharmony_ci	default:
245762306a36Sopenharmony_ci		return -EINVAL;
245862306a36Sopenharmony_ci	}
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci	intrmod.rx_enable = intr_coal->use_adaptive_rx_coalesce ? 1 : 0;
246162306a36Sopenharmony_ci	intrmod.tx_enable = intr_coal->use_adaptive_tx_coalesce ? 1 : 0;
246262306a36Sopenharmony_ci	intrmod.rx_frames = CFG_GET_OQ_INTR_PKT(octeon_get_conf(oct));
246362306a36Sopenharmony_ci	intrmod.rx_usecs = CFG_GET_OQ_INTR_TIME(octeon_get_conf(oct));
246462306a36Sopenharmony_ci	intrmod.tx_frames = CFG_GET_IQ_INTR_PKT(octeon_get_conf(oct));
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci	ret = oct_cfg_adaptive_intr(lio, &intrmod, intr_coal);
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	if (!intr_coal->use_adaptive_rx_coalesce) {
246962306a36Sopenharmony_ci		ret = oct_cfg_rx_intrtime(lio, &intrmod, intr_coal);
247062306a36Sopenharmony_ci		if (ret)
247162306a36Sopenharmony_ci			goto ret_intrmod;
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci		ret = oct_cfg_rx_intrcnt(lio, &intrmod, intr_coal);
247462306a36Sopenharmony_ci		if (ret)
247562306a36Sopenharmony_ci			goto ret_intrmod;
247662306a36Sopenharmony_ci	} else {
247762306a36Sopenharmony_ci		oct->rx_coalesce_usecs =
247862306a36Sopenharmony_ci			CFG_GET_OQ_INTR_TIME(octeon_get_conf(oct));
247962306a36Sopenharmony_ci		oct->rx_max_coalesced_frames =
248062306a36Sopenharmony_ci			CFG_GET_OQ_INTR_PKT(octeon_get_conf(oct));
248162306a36Sopenharmony_ci	}
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci	if (!intr_coal->use_adaptive_tx_coalesce) {
248462306a36Sopenharmony_ci		ret = oct_cfg_tx_intrcnt(lio, &intrmod, intr_coal);
248562306a36Sopenharmony_ci		if (ret)
248662306a36Sopenharmony_ci			goto ret_intrmod;
248762306a36Sopenharmony_ci	} else {
248862306a36Sopenharmony_ci		oct->tx_max_coalesced_frames =
248962306a36Sopenharmony_ci			CFG_GET_IQ_INTR_PKT(octeon_get_conf(oct));
249062306a36Sopenharmony_ci	}
249162306a36Sopenharmony_ci
249262306a36Sopenharmony_ci	return 0;
249362306a36Sopenharmony_ciret_intrmod:
249462306a36Sopenharmony_ci	return ret;
249562306a36Sopenharmony_ci}
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_cistatic int lio_get_ts_info(struct net_device *netdev,
249862306a36Sopenharmony_ci			   struct ethtool_ts_info *info)
249962306a36Sopenharmony_ci{
250062306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci	info->so_timestamping =
250362306a36Sopenharmony_ci#ifdef PTP_HARDWARE_TIMESTAMPING
250462306a36Sopenharmony_ci		SOF_TIMESTAMPING_TX_HARDWARE |
250562306a36Sopenharmony_ci		SOF_TIMESTAMPING_RX_HARDWARE |
250662306a36Sopenharmony_ci		SOF_TIMESTAMPING_RAW_HARDWARE |
250762306a36Sopenharmony_ci		SOF_TIMESTAMPING_TX_SOFTWARE |
250862306a36Sopenharmony_ci#endif
250962306a36Sopenharmony_ci		SOF_TIMESTAMPING_RX_SOFTWARE |
251062306a36Sopenharmony_ci		SOF_TIMESTAMPING_SOFTWARE;
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	if (lio->ptp_clock)
251362306a36Sopenharmony_ci		info->phc_index = ptp_clock_index(lio->ptp_clock);
251462306a36Sopenharmony_ci	else
251562306a36Sopenharmony_ci		info->phc_index = -1;
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_ci#ifdef PTP_HARDWARE_TIMESTAMPING
251862306a36Sopenharmony_ci	info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
251962306a36Sopenharmony_ci
252062306a36Sopenharmony_ci	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
252162306a36Sopenharmony_ci			   (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
252262306a36Sopenharmony_ci			   (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
252362306a36Sopenharmony_ci			   (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
252462306a36Sopenharmony_ci#endif
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci	return 0;
252762306a36Sopenharmony_ci}
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_ci/* Return register dump len. */
253062306a36Sopenharmony_cistatic int lio_get_regs_len(struct net_device *dev)
253162306a36Sopenharmony_ci{
253262306a36Sopenharmony_ci	struct lio *lio = GET_LIO(dev);
253362306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	switch (oct->chip_id) {
253662306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
253762306a36Sopenharmony_ci		return OCT_ETHTOOL_REGDUMP_LEN_23XX;
253862306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
253962306a36Sopenharmony_ci		return OCT_ETHTOOL_REGDUMP_LEN_23XX_VF;
254062306a36Sopenharmony_ci	default:
254162306a36Sopenharmony_ci		return OCT_ETHTOOL_REGDUMP_LEN;
254262306a36Sopenharmony_ci	}
254362306a36Sopenharmony_ci}
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_cistatic int cn23xx_read_csr_reg(char *s, struct octeon_device *oct)
254662306a36Sopenharmony_ci{
254762306a36Sopenharmony_ci	u32 reg;
254862306a36Sopenharmony_ci	u8 pf_num = oct->pf_num;
254962306a36Sopenharmony_ci	int len = 0;
255062306a36Sopenharmony_ci	int i;
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	/* PCI  Window Registers */
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci	len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	/*0x29030 or 0x29040*/
255762306a36Sopenharmony_ci	reg = CN23XX_SLI_PKT_MAC_RINFO64(oct->pcie_port, oct->pf_num);
255862306a36Sopenharmony_ci	len += sprintf(s + len,
255962306a36Sopenharmony_ci		       "\n[%08x] (SLI_PKT_MAC%d_PF%d_RINFO): %016llx\n",
256062306a36Sopenharmony_ci		       reg, oct->pcie_port, oct->pf_num,
256162306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	/*0x27080 or 0x27090*/
256462306a36Sopenharmony_ci	reg = CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
256562306a36Sopenharmony_ci	len +=
256662306a36Sopenharmony_ci	    sprintf(s + len, "\n[%08x] (SLI_MAC%d_PF%d_INT_ENB): %016llx\n",
256762306a36Sopenharmony_ci		    reg, oct->pcie_port, oct->pf_num,
256862306a36Sopenharmony_ci		    (u64)octeon_read_csr64(oct, reg));
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci	/*0x27000 or 0x27010*/
257162306a36Sopenharmony_ci	reg = CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
257262306a36Sopenharmony_ci	len +=
257362306a36Sopenharmony_ci	    sprintf(s + len, "\n[%08x] (SLI_MAC%d_PF%d_INT_SUM): %016llx\n",
257462306a36Sopenharmony_ci		    reg, oct->pcie_port, oct->pf_num,
257562306a36Sopenharmony_ci		    (u64)octeon_read_csr64(oct, reg));
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	/*0x29120*/
257862306a36Sopenharmony_ci	reg = 0x29120;
257962306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_MEM_CTL): %016llx\n", reg,
258062306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
258162306a36Sopenharmony_ci
258262306a36Sopenharmony_ci	/*0x27300*/
258362306a36Sopenharmony_ci	reg = 0x27300 + oct->pcie_port * CN23XX_MAC_INT_OFFSET +
258462306a36Sopenharmony_ci	      (oct->pf_num) * CN23XX_PF_INT_OFFSET;
258562306a36Sopenharmony_ci	len += sprintf(
258662306a36Sopenharmony_ci	    s + len, "\n[%08x] (SLI_MAC%d_PF%d_PKT_VF_INT): %016llx\n", reg,
258762306a36Sopenharmony_ci	    oct->pcie_port, oct->pf_num, (u64)octeon_read_csr64(oct, reg));
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	/*0x27200*/
259062306a36Sopenharmony_ci	reg = 0x27200 + oct->pcie_port * CN23XX_MAC_INT_OFFSET +
259162306a36Sopenharmony_ci	      (oct->pf_num) * CN23XX_PF_INT_OFFSET;
259262306a36Sopenharmony_ci	len += sprintf(s + len,
259362306a36Sopenharmony_ci		       "\n[%08x] (SLI_MAC%d_PF%d_PP_VF_INT): %016llx\n",
259462306a36Sopenharmony_ci		       reg, oct->pcie_port, oct->pf_num,
259562306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
259662306a36Sopenharmony_ci
259762306a36Sopenharmony_ci	/*29130*/
259862306a36Sopenharmony_ci	reg = CN23XX_SLI_PKT_CNT_INT;
259962306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_CNT_INT): %016llx\n", reg,
260062306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_ci	/*0x29140*/
260362306a36Sopenharmony_ci	reg = CN23XX_SLI_PKT_TIME_INT;
260462306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_TIME_INT): %016llx\n", reg,
260562306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci	/*0x29160*/
260862306a36Sopenharmony_ci	reg = 0x29160;
260962306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_INT): %016llx\n", reg,
261062306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	/*0x29180*/
261362306a36Sopenharmony_ci	reg = CN23XX_SLI_OQ_WMARK;
261462306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_OUTPUT_WMARK): %016llx\n",
261562306a36Sopenharmony_ci		       reg, (u64)octeon_read_csr64(oct, reg));
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci	/*0x291E0*/
261862306a36Sopenharmony_ci	reg = CN23XX_SLI_PKT_IOQ_RING_RST;
261962306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_RING_RST): %016llx\n", reg,
262062306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci	/*0x29210*/
262362306a36Sopenharmony_ci	reg = CN23XX_SLI_GBL_CONTROL;
262462306a36Sopenharmony_ci	len += sprintf(s + len,
262562306a36Sopenharmony_ci		       "\n[%08x] (SLI_PKT_GBL_CONTROL): %016llx\n", reg,
262662306a36Sopenharmony_ci		       (u64)octeon_read_csr64(oct, reg));
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	/*0x29220*/
262962306a36Sopenharmony_ci	reg = 0x29220;
263062306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%08x] (SLI_PKT_BIST_STATUS): %016llx\n",
263162306a36Sopenharmony_ci		       reg, (u64)octeon_read_csr64(oct, reg));
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci	/*PF only*/
263462306a36Sopenharmony_ci	if (pf_num == 0) {
263562306a36Sopenharmony_ci		/*0x29260*/
263662306a36Sopenharmony_ci		reg = CN23XX_SLI_OUT_BP_EN_W1S;
263762306a36Sopenharmony_ci		len += sprintf(s + len,
263862306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_OUT_BP_EN_W1S):  %016llx\n",
263962306a36Sopenharmony_ci			       reg, (u64)octeon_read_csr64(oct, reg));
264062306a36Sopenharmony_ci	} else if (pf_num == 1) {
264162306a36Sopenharmony_ci		/*0x29270*/
264262306a36Sopenharmony_ci		reg = CN23XX_SLI_OUT_BP_EN2_W1S;
264362306a36Sopenharmony_ci		len += sprintf(s + len,
264462306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_OUT_BP_EN2_W1S): %016llx\n",
264562306a36Sopenharmony_ci			       reg, (u64)octeon_read_csr64(oct, reg));
264662306a36Sopenharmony_ci	}
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
264962306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_BUFF_INFO_SIZE(i);
265062306a36Sopenharmony_ci		len +=
265162306a36Sopenharmony_ci		    sprintf(s + len, "\n[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
265262306a36Sopenharmony_ci			    reg, i, (u64)octeon_read_csr64(oct, reg));
265362306a36Sopenharmony_ci	}
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci	/*0x10040*/
265662306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
265762306a36Sopenharmony_ci		reg = CN23XX_SLI_IQ_INSTR_COUNT64(i);
265862306a36Sopenharmony_ci		len += sprintf(s + len,
265962306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
266062306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
266162306a36Sopenharmony_ci	}
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci	/*0x10080*/
266462306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
266562306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_PKTS_CREDIT(i);
266662306a36Sopenharmony_ci		len += sprintf(s + len,
266762306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
266862306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
266962306a36Sopenharmony_ci	}
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci	/*0x10090*/
267262306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
267362306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_SIZE(i);
267462306a36Sopenharmony_ci		len += sprintf(
267562306a36Sopenharmony_ci		    s + len, "\n[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
267662306a36Sopenharmony_ci		    reg, i, (u64)octeon_read_csr64(oct, reg));
267762306a36Sopenharmony_ci	}
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci	/*0x10050*/
268062306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
268162306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_PKT_CONTROL(i);
268262306a36Sopenharmony_ci		len += sprintf(
268362306a36Sopenharmony_ci			s + len,
268462306a36Sopenharmony_ci			"\n[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
268562306a36Sopenharmony_ci			reg, i, (u64)octeon_read_csr64(oct, reg));
268662306a36Sopenharmony_ci	}
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	/*0x10070*/
268962306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
269062306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_BASE_ADDR64(i);
269162306a36Sopenharmony_ci		len += sprintf(s + len,
269262306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
269362306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
269462306a36Sopenharmony_ci	}
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	/*0x100a0*/
269762306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
269862306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_PKT_INT_LEVELS(i);
269962306a36Sopenharmony_ci		len += sprintf(s + len,
270062306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
270162306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
270262306a36Sopenharmony_ci	}
270362306a36Sopenharmony_ci
270462306a36Sopenharmony_ci	/*0x100b0*/
270562306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
270662306a36Sopenharmony_ci		reg = CN23XX_SLI_OQ_PKTS_SENT(i);
270762306a36Sopenharmony_ci		len += sprintf(s + len, "\n[%08x] (SLI_PKT%d_CNTS): %016llx\n",
270862306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
270962306a36Sopenharmony_ci	}
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	/*0x100c0*/
271262306a36Sopenharmony_ci	for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
271362306a36Sopenharmony_ci		reg = 0x100c0 + i * CN23XX_OQ_OFFSET;
271462306a36Sopenharmony_ci		len += sprintf(s + len,
271562306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
271662306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci		/*0x10000*/
271962306a36Sopenharmony_ci		for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
272062306a36Sopenharmony_ci			reg = CN23XX_SLI_IQ_PKT_CONTROL64(i);
272162306a36Sopenharmony_ci			len += sprintf(
272262306a36Sopenharmony_ci				s + len,
272362306a36Sopenharmony_ci				"\n[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
272462306a36Sopenharmony_ci				reg, i, (u64)octeon_read_csr64(oct, reg));
272562306a36Sopenharmony_ci		}
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci		/*0x10010*/
272862306a36Sopenharmony_ci		for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
272962306a36Sopenharmony_ci			reg = CN23XX_SLI_IQ_BASE_ADDR64(i);
273062306a36Sopenharmony_ci			len += sprintf(
273162306a36Sopenharmony_ci			    s + len,
273262306a36Sopenharmony_ci			    "\n[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n", reg,
273362306a36Sopenharmony_ci			    i, (u64)octeon_read_csr64(oct, reg));
273462306a36Sopenharmony_ci		}
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci		/*0x10020*/
273762306a36Sopenharmony_ci		for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
273862306a36Sopenharmony_ci			reg = CN23XX_SLI_IQ_DOORBELL(i);
273962306a36Sopenharmony_ci			len += sprintf(
274062306a36Sopenharmony_ci			    s + len,
274162306a36Sopenharmony_ci			    "\n[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
274262306a36Sopenharmony_ci			    reg, i, (u64)octeon_read_csr64(oct, reg));
274362306a36Sopenharmony_ci		}
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci		/*0x10030*/
274662306a36Sopenharmony_ci		for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
274762306a36Sopenharmony_ci			reg = CN23XX_SLI_IQ_SIZE(i);
274862306a36Sopenharmony_ci			len += sprintf(
274962306a36Sopenharmony_ci			    s + len,
275062306a36Sopenharmony_ci			    "\n[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
275162306a36Sopenharmony_ci			    reg, i, (u64)octeon_read_csr64(oct, reg));
275262306a36Sopenharmony_ci		}
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci		/*0x10040*/
275562306a36Sopenharmony_ci		for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++)
275662306a36Sopenharmony_ci			reg = CN23XX_SLI_IQ_INSTR_COUNT64(i);
275762306a36Sopenharmony_ci		len += sprintf(s + len,
275862306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
275962306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
276062306a36Sopenharmony_ci	}
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci	return len;
276362306a36Sopenharmony_ci}
276462306a36Sopenharmony_ci
276562306a36Sopenharmony_cistatic int cn23xx_vf_read_csr_reg(char *s, struct octeon_device *oct)
276662306a36Sopenharmony_ci{
276762306a36Sopenharmony_ci	int len = 0;
276862306a36Sopenharmony_ci	u32 reg;
276962306a36Sopenharmony_ci	int i;
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	/* PCI  Window Registers */
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
277662306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(i);
277762306a36Sopenharmony_ci		len += sprintf(s + len,
277862306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
277962306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
278062306a36Sopenharmony_ci	}
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
278362306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
278462306a36Sopenharmony_ci		len += sprintf(s + len,
278562306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
278662306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
278762306a36Sopenharmony_ci	}
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
279062306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_PKTS_CREDIT(i);
279162306a36Sopenharmony_ci		len += sprintf(s + len,
279262306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
279362306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
279462306a36Sopenharmony_ci	}
279562306a36Sopenharmony_ci
279662306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
279762306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_SIZE(i);
279862306a36Sopenharmony_ci		len += sprintf(s + len,
279962306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
280062306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
280162306a36Sopenharmony_ci	}
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
280462306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_PKT_CONTROL(i);
280562306a36Sopenharmony_ci		len += sprintf(s + len,
280662306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
280762306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
280862306a36Sopenharmony_ci	}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
281162306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_BASE_ADDR64(i);
281262306a36Sopenharmony_ci		len += sprintf(s + len,
281362306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
281462306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
281562306a36Sopenharmony_ci	}
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
281862306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(i);
281962306a36Sopenharmony_ci		len += sprintf(s + len,
282062306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
282162306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
282262306a36Sopenharmony_ci	}
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
282562306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_OQ_PKTS_SENT(i);
282662306a36Sopenharmony_ci		len += sprintf(s + len, "\n[%08x] (SLI_PKT%d_CNTS): %016llx\n",
282762306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
282862306a36Sopenharmony_ci	}
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
283162306a36Sopenharmony_ci		reg = 0x100c0 + i * CN23XX_VF_OQ_OFFSET;
283262306a36Sopenharmony_ci		len += sprintf(s + len,
283362306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
283462306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
283562306a36Sopenharmony_ci	}
283662306a36Sopenharmony_ci
283762306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
283862306a36Sopenharmony_ci		reg = 0x100d0 + i * CN23XX_VF_IQ_OFFSET;
283962306a36Sopenharmony_ci		len += sprintf(s + len,
284062306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_VF_INT_SUM): %016llx\n",
284162306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
284262306a36Sopenharmony_ci	}
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
284562306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_PKT_CONTROL64(i);
284662306a36Sopenharmony_ci		len += sprintf(s + len,
284762306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
284862306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
284962306a36Sopenharmony_ci	}
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
285262306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_BASE_ADDR64(i);
285362306a36Sopenharmony_ci		len += sprintf(s + len,
285462306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
285562306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
285662306a36Sopenharmony_ci	}
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
285962306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_DOORBELL(i);
286062306a36Sopenharmony_ci		len += sprintf(s + len,
286162306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
286262306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
286362306a36Sopenharmony_ci	}
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
286662306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_SIZE(i);
286762306a36Sopenharmony_ci		len += sprintf(s + len,
286862306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
286962306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
287062306a36Sopenharmony_ci	}
287162306a36Sopenharmony_ci
287262306a36Sopenharmony_ci	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
287362306a36Sopenharmony_ci		reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
287462306a36Sopenharmony_ci		len += sprintf(s + len,
287562306a36Sopenharmony_ci			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
287662306a36Sopenharmony_ci			       reg, i, (u64)octeon_read_csr64(oct, reg));
287762306a36Sopenharmony_ci	}
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_ci	return len;
288062306a36Sopenharmony_ci}
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_cistatic int cn6xxx_read_csr_reg(char *s, struct octeon_device *oct)
288362306a36Sopenharmony_ci{
288462306a36Sopenharmony_ci	u32 reg;
288562306a36Sopenharmony_ci	int i, len = 0;
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci	/* PCI  Window Registers */
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci	len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
289062306a36Sopenharmony_ci	reg = CN6XXX_WIN_WR_ADDR_LO;
289162306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%02x] (WIN_WR_ADDR_LO): %08x\n",
289262306a36Sopenharmony_ci		       CN6XXX_WIN_WR_ADDR_LO, octeon_read_csr(oct, reg));
289362306a36Sopenharmony_ci	reg = CN6XXX_WIN_WR_ADDR_HI;
289462306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_WR_ADDR_HI): %08x\n",
289562306a36Sopenharmony_ci		       CN6XXX_WIN_WR_ADDR_HI, octeon_read_csr(oct, reg));
289662306a36Sopenharmony_ci	reg = CN6XXX_WIN_RD_ADDR_LO;
289762306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_RD_ADDR_LO): %08x\n",
289862306a36Sopenharmony_ci		       CN6XXX_WIN_RD_ADDR_LO, octeon_read_csr(oct, reg));
289962306a36Sopenharmony_ci	reg = CN6XXX_WIN_RD_ADDR_HI;
290062306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_RD_ADDR_HI): %08x\n",
290162306a36Sopenharmony_ci		       CN6XXX_WIN_RD_ADDR_HI, octeon_read_csr(oct, reg));
290262306a36Sopenharmony_ci	reg = CN6XXX_WIN_WR_DATA_LO;
290362306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_WR_DATA_LO): %08x\n",
290462306a36Sopenharmony_ci		       CN6XXX_WIN_WR_DATA_LO, octeon_read_csr(oct, reg));
290562306a36Sopenharmony_ci	reg = CN6XXX_WIN_WR_DATA_HI;
290662306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_WR_DATA_HI): %08x\n",
290762306a36Sopenharmony_ci		       CN6XXX_WIN_WR_DATA_HI, octeon_read_csr(oct, reg));
290862306a36Sopenharmony_ci	len += sprintf(s + len, "[%02x] (WIN_WR_MASK_REG): %08x\n",
290962306a36Sopenharmony_ci		       CN6XXX_WIN_WR_MASK_REG,
291062306a36Sopenharmony_ci		       octeon_read_csr(oct, CN6XXX_WIN_WR_MASK_REG));
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci	/* PCI  Interrupt Register */
291362306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%x] (INT_ENABLE PORT 0): %08x\n",
291462306a36Sopenharmony_ci		       CN6XXX_SLI_INT_ENB64_PORT0, octeon_read_csr(oct,
291562306a36Sopenharmony_ci						CN6XXX_SLI_INT_ENB64_PORT0));
291662306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%x] (INT_ENABLE PORT 1): %08x\n",
291762306a36Sopenharmony_ci		       CN6XXX_SLI_INT_ENB64_PORT1,
291862306a36Sopenharmony_ci		       octeon_read_csr(oct, CN6XXX_SLI_INT_ENB64_PORT1));
291962306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (INT_SUM): %08x\n", CN6XXX_SLI_INT_SUM64,
292062306a36Sopenharmony_ci		       octeon_read_csr(oct, CN6XXX_SLI_INT_SUM64));
292162306a36Sopenharmony_ci
292262306a36Sopenharmony_ci	/* PCI  Output queue registers */
292362306a36Sopenharmony_ci	for (i = 0; i < oct->num_oqs; i++) {
292462306a36Sopenharmony_ci		reg = CN6XXX_SLI_OQ_PKTS_SENT(i);
292562306a36Sopenharmony_ci		len += sprintf(s + len, "\n[%x] (PKTS_SENT_%d): %08x\n",
292662306a36Sopenharmony_ci			       reg, i, octeon_read_csr(oct, reg));
292762306a36Sopenharmony_ci		reg = CN6XXX_SLI_OQ_PKTS_CREDIT(i);
292862306a36Sopenharmony_ci		len += sprintf(s + len, "[%x] (PKT_CREDITS_%d): %08x\n",
292962306a36Sopenharmony_ci			       reg, i, octeon_read_csr(oct, reg));
293062306a36Sopenharmony_ci	}
293162306a36Sopenharmony_ci	reg = CN6XXX_SLI_OQ_INT_LEVEL_PKTS;
293262306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%x] (PKTS_SENT_INT_LEVEL): %08x\n",
293362306a36Sopenharmony_ci		       reg, octeon_read_csr(oct, reg));
293462306a36Sopenharmony_ci	reg = CN6XXX_SLI_OQ_INT_LEVEL_TIME;
293562306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (PKTS_SENT_TIME): %08x\n",
293662306a36Sopenharmony_ci		       reg, octeon_read_csr(oct, reg));
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	/* PCI  Input queue registers */
293962306a36Sopenharmony_ci	for (i = 0; i <= 3; i++) {
294062306a36Sopenharmony_ci		u32 reg;
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci		reg = CN6XXX_SLI_IQ_DOORBELL(i);
294362306a36Sopenharmony_ci		len += sprintf(s + len, "\n[%x] (INSTR_DOORBELL_%d): %08x\n",
294462306a36Sopenharmony_ci			       reg, i, octeon_read_csr(oct, reg));
294562306a36Sopenharmony_ci		reg = CN6XXX_SLI_IQ_INSTR_COUNT(i);
294662306a36Sopenharmony_ci		len += sprintf(s + len, "[%x] (INSTR_COUNT_%d): %08x\n",
294762306a36Sopenharmony_ci			       reg, i, octeon_read_csr(oct, reg));
294862306a36Sopenharmony_ci	}
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci	/* PCI  DMA registers */
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%x] (DMA_CNT_0): %08x\n",
295362306a36Sopenharmony_ci		       CN6XXX_DMA_CNT(0),
295462306a36Sopenharmony_ci		       octeon_read_csr(oct, CN6XXX_DMA_CNT(0)));
295562306a36Sopenharmony_ci	reg = CN6XXX_DMA_PKT_INT_LEVEL(0);
295662306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (DMA_INT_LEV_0): %08x\n",
295762306a36Sopenharmony_ci		       CN6XXX_DMA_PKT_INT_LEVEL(0), octeon_read_csr(oct, reg));
295862306a36Sopenharmony_ci	reg = CN6XXX_DMA_TIME_INT_LEVEL(0);
295962306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (DMA_TIME_0): %08x\n",
296062306a36Sopenharmony_ci		       CN6XXX_DMA_TIME_INT_LEVEL(0),
296162306a36Sopenharmony_ci		       octeon_read_csr(oct, reg));
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci	len += sprintf(s + len, "\n[%x] (DMA_CNT_1): %08x\n",
296462306a36Sopenharmony_ci		       CN6XXX_DMA_CNT(1),
296562306a36Sopenharmony_ci		       octeon_read_csr(oct, CN6XXX_DMA_CNT(1)));
296662306a36Sopenharmony_ci	reg = CN6XXX_DMA_PKT_INT_LEVEL(1);
296762306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (DMA_INT_LEV_1): %08x\n",
296862306a36Sopenharmony_ci		       CN6XXX_DMA_PKT_INT_LEVEL(1),
296962306a36Sopenharmony_ci		       octeon_read_csr(oct, reg));
297062306a36Sopenharmony_ci	reg = CN6XXX_DMA_PKT_INT_LEVEL(1);
297162306a36Sopenharmony_ci	len += sprintf(s + len, "[%x] (DMA_TIME_1): %08x\n",
297262306a36Sopenharmony_ci		       CN6XXX_DMA_TIME_INT_LEVEL(1),
297362306a36Sopenharmony_ci		       octeon_read_csr(oct, reg));
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	/* PCI  Index registers */
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	len += sprintf(s + len, "\n");
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
298062306a36Sopenharmony_ci		reg = lio_pci_readq(oct, CN6XXX_BAR1_REG(i, oct->pcie_port));
298162306a36Sopenharmony_ci		len += sprintf(s + len, "[%llx] (BAR1_INDEX_%02d): %08x\n",
298262306a36Sopenharmony_ci			       CN6XXX_BAR1_REG(i, oct->pcie_port), i, reg);
298362306a36Sopenharmony_ci	}
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci	return len;
298662306a36Sopenharmony_ci}
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_cistatic int cn6xxx_read_config_reg(char *s, struct octeon_device *oct)
298962306a36Sopenharmony_ci{
299062306a36Sopenharmony_ci	u32 val;
299162306a36Sopenharmony_ci	int i, len = 0;
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci	/* PCI CONFIG Registers */
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci	len += sprintf(s + len,
299662306a36Sopenharmony_ci		       "\n\t Octeon Config space Registers\n\n");
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	for (i = 0; i <= 13; i++) {
299962306a36Sopenharmony_ci		pci_read_config_dword(oct->pci_dev, (i * 4), &val);
300062306a36Sopenharmony_ci		len += sprintf(s + len, "[0x%x] (Config[%d]): 0x%08x\n",
300162306a36Sopenharmony_ci			       (i * 4), i, val);
300262306a36Sopenharmony_ci	}
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	for (i = 30; i <= 34; i++) {
300562306a36Sopenharmony_ci		pci_read_config_dword(oct->pci_dev, (i * 4), &val);
300662306a36Sopenharmony_ci		len += sprintf(s + len, "[0x%x] (Config[%d]): 0x%08x\n",
300762306a36Sopenharmony_ci			       (i * 4), i, val);
300862306a36Sopenharmony_ci	}
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	return len;
301162306a36Sopenharmony_ci}
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci/*  Return register dump user app.  */
301462306a36Sopenharmony_cistatic void lio_get_regs(struct net_device *dev,
301562306a36Sopenharmony_ci			 struct ethtool_regs *regs, void *regbuf)
301662306a36Sopenharmony_ci{
301762306a36Sopenharmony_ci	struct lio *lio = GET_LIO(dev);
301862306a36Sopenharmony_ci	int len = 0;
301962306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_ci	regs->version = OCT_ETHTOOL_REGSVER;
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_ci	switch (oct->chip_id) {
302462306a36Sopenharmony_ci	case OCTEON_CN23XX_PF_VID:
302562306a36Sopenharmony_ci		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX);
302662306a36Sopenharmony_ci		len += cn23xx_read_csr_reg(regbuf + len, oct);
302762306a36Sopenharmony_ci		break;
302862306a36Sopenharmony_ci	case OCTEON_CN23XX_VF_VID:
302962306a36Sopenharmony_ci		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX_VF);
303062306a36Sopenharmony_ci		len += cn23xx_vf_read_csr_reg(regbuf + len, oct);
303162306a36Sopenharmony_ci		break;
303262306a36Sopenharmony_ci	case OCTEON_CN68XX:
303362306a36Sopenharmony_ci	case OCTEON_CN66XX:
303462306a36Sopenharmony_ci		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN);
303562306a36Sopenharmony_ci		len += cn6xxx_read_csr_reg(regbuf + len, oct);
303662306a36Sopenharmony_ci		len += cn6xxx_read_config_reg(regbuf + len, oct);
303762306a36Sopenharmony_ci		break;
303862306a36Sopenharmony_ci	default:
303962306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s Unknown chipid: %d\n",
304062306a36Sopenharmony_ci			__func__, oct->chip_id);
304162306a36Sopenharmony_ci	}
304262306a36Sopenharmony_ci}
304362306a36Sopenharmony_ci
304462306a36Sopenharmony_cistatic u32 lio_get_priv_flags(struct net_device *netdev)
304562306a36Sopenharmony_ci{
304662306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_ci	return lio->oct_dev->priv_flags;
304962306a36Sopenharmony_ci}
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_cistatic int lio_set_priv_flags(struct net_device *netdev, u32 flags)
305262306a36Sopenharmony_ci{
305362306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
305462306a36Sopenharmony_ci	bool intr_by_tx_bytes = !!(flags & (0x1 << OCT_PRIV_FLAG_TX_BYTES));
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci	lio_set_priv_flag(lio->oct_dev, OCT_PRIV_FLAG_TX_BYTES,
305762306a36Sopenharmony_ci			  intr_by_tx_bytes);
305862306a36Sopenharmony_ci	return 0;
305962306a36Sopenharmony_ci}
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_cistatic int lio_get_fecparam(struct net_device *netdev,
306262306a36Sopenharmony_ci			    struct ethtool_fecparam *fec)
306362306a36Sopenharmony_ci{
306462306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
306562306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	fec->active_fec = ETHTOOL_FEC_NONE;
306862306a36Sopenharmony_ci	fec->fec = ETHTOOL_FEC_NONE;
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci	if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
307162306a36Sopenharmony_ci	    oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
307262306a36Sopenharmony_ci		if (oct->no_speed_setting == 1)
307362306a36Sopenharmony_ci			return 0;
307462306a36Sopenharmony_ci
307562306a36Sopenharmony_ci		liquidio_get_fec(lio);
307662306a36Sopenharmony_ci		fec->fec = (ETHTOOL_FEC_RS | ETHTOOL_FEC_OFF);
307762306a36Sopenharmony_ci		if (oct->props[lio->ifidx].fec == 1)
307862306a36Sopenharmony_ci			fec->active_fec = ETHTOOL_FEC_RS;
307962306a36Sopenharmony_ci		else
308062306a36Sopenharmony_ci			fec->active_fec = ETHTOOL_FEC_OFF;
308162306a36Sopenharmony_ci	}
308262306a36Sopenharmony_ci
308362306a36Sopenharmony_ci	return 0;
308462306a36Sopenharmony_ci}
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_cistatic int lio_set_fecparam(struct net_device *netdev,
308762306a36Sopenharmony_ci			    struct ethtool_fecparam *fec)
308862306a36Sopenharmony_ci{
308962306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
309062306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci	if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
309362306a36Sopenharmony_ci	    oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
309462306a36Sopenharmony_ci		if (oct->no_speed_setting == 1)
309562306a36Sopenharmony_ci			return -EOPNOTSUPP;
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci		if (fec->fec & ETHTOOL_FEC_OFF)
309862306a36Sopenharmony_ci			liquidio_set_fec(lio, 0);
309962306a36Sopenharmony_ci		else if (fec->fec & ETHTOOL_FEC_RS)
310062306a36Sopenharmony_ci			liquidio_set_fec(lio, 1);
310162306a36Sopenharmony_ci		else
310262306a36Sopenharmony_ci			return -EOPNOTSUPP;
310362306a36Sopenharmony_ci	} else {
310462306a36Sopenharmony_ci		return -EOPNOTSUPP;
310562306a36Sopenharmony_ci	}
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_ci	return 0;
310862306a36Sopenharmony_ci}
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci#define LIO_ETHTOOL_COALESCE	(ETHTOOL_COALESCE_RX_USECS |		\
311162306a36Sopenharmony_ci				 ETHTOOL_COALESCE_MAX_FRAMES |		\
311262306a36Sopenharmony_ci				 ETHTOOL_COALESCE_USE_ADAPTIVE |	\
311362306a36Sopenharmony_ci				 ETHTOOL_COALESCE_RX_MAX_FRAMES_LOW |	\
311462306a36Sopenharmony_ci				 ETHTOOL_COALESCE_TX_MAX_FRAMES_LOW |	\
311562306a36Sopenharmony_ci				 ETHTOOL_COALESCE_RX_MAX_FRAMES_HIGH |	\
311662306a36Sopenharmony_ci				 ETHTOOL_COALESCE_TX_MAX_FRAMES_HIGH |	\
311762306a36Sopenharmony_ci				 ETHTOOL_COALESCE_PKT_RATE_RX_USECS)
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_cistatic const struct ethtool_ops lio_ethtool_ops = {
312062306a36Sopenharmony_ci	.supported_coalesce_params = LIO_ETHTOOL_COALESCE,
312162306a36Sopenharmony_ci	.get_link_ksettings	= lio_get_link_ksettings,
312262306a36Sopenharmony_ci	.set_link_ksettings	= lio_set_link_ksettings,
312362306a36Sopenharmony_ci	.get_fecparam		= lio_get_fecparam,
312462306a36Sopenharmony_ci	.set_fecparam		= lio_set_fecparam,
312562306a36Sopenharmony_ci	.get_link		= ethtool_op_get_link,
312662306a36Sopenharmony_ci	.get_drvinfo		= lio_get_drvinfo,
312762306a36Sopenharmony_ci	.get_ringparam		= lio_ethtool_get_ringparam,
312862306a36Sopenharmony_ci	.set_ringparam		= lio_ethtool_set_ringparam,
312962306a36Sopenharmony_ci	.get_channels		= lio_ethtool_get_channels,
313062306a36Sopenharmony_ci	.set_channels		= lio_ethtool_set_channels,
313162306a36Sopenharmony_ci	.set_phys_id		= lio_set_phys_id,
313262306a36Sopenharmony_ci	.get_eeprom_len		= lio_get_eeprom_len,
313362306a36Sopenharmony_ci	.get_eeprom		= lio_get_eeprom,
313462306a36Sopenharmony_ci	.get_strings		= lio_get_strings,
313562306a36Sopenharmony_ci	.get_ethtool_stats	= lio_get_ethtool_stats,
313662306a36Sopenharmony_ci	.get_pauseparam		= lio_get_pauseparam,
313762306a36Sopenharmony_ci	.set_pauseparam		= lio_set_pauseparam,
313862306a36Sopenharmony_ci	.get_regs_len		= lio_get_regs_len,
313962306a36Sopenharmony_ci	.get_regs		= lio_get_regs,
314062306a36Sopenharmony_ci	.get_msglevel		= lio_get_msglevel,
314162306a36Sopenharmony_ci	.set_msglevel		= lio_set_msglevel,
314262306a36Sopenharmony_ci	.get_sset_count		= lio_get_sset_count,
314362306a36Sopenharmony_ci	.get_coalesce		= lio_get_intr_coalesce,
314462306a36Sopenharmony_ci	.set_coalesce		= lio_set_intr_coalesce,
314562306a36Sopenharmony_ci	.get_priv_flags		= lio_get_priv_flags,
314662306a36Sopenharmony_ci	.set_priv_flags		= lio_set_priv_flags,
314762306a36Sopenharmony_ci	.get_ts_info		= lio_get_ts_info,
314862306a36Sopenharmony_ci};
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_cistatic const struct ethtool_ops lio_vf_ethtool_ops = {
315162306a36Sopenharmony_ci	.supported_coalesce_params = LIO_ETHTOOL_COALESCE,
315262306a36Sopenharmony_ci	.get_link_ksettings	= lio_get_link_ksettings,
315362306a36Sopenharmony_ci	.get_link		= ethtool_op_get_link,
315462306a36Sopenharmony_ci	.get_drvinfo		= lio_get_vf_drvinfo,
315562306a36Sopenharmony_ci	.get_ringparam		= lio_ethtool_get_ringparam,
315662306a36Sopenharmony_ci	.set_ringparam          = lio_ethtool_set_ringparam,
315762306a36Sopenharmony_ci	.get_channels		= lio_ethtool_get_channels,
315862306a36Sopenharmony_ci	.set_channels		= lio_ethtool_set_channels,
315962306a36Sopenharmony_ci	.get_strings		= lio_vf_get_strings,
316062306a36Sopenharmony_ci	.get_ethtool_stats	= lio_vf_get_ethtool_stats,
316162306a36Sopenharmony_ci	.get_regs_len		= lio_get_regs_len,
316262306a36Sopenharmony_ci	.get_regs		= lio_get_regs,
316362306a36Sopenharmony_ci	.get_msglevel		= lio_get_msglevel,
316462306a36Sopenharmony_ci	.set_msglevel		= lio_vf_set_msglevel,
316562306a36Sopenharmony_ci	.get_sset_count		= lio_vf_get_sset_count,
316662306a36Sopenharmony_ci	.get_coalesce		= lio_get_intr_coalesce,
316762306a36Sopenharmony_ci	.set_coalesce		= lio_set_intr_coalesce,
316862306a36Sopenharmony_ci	.get_priv_flags		= lio_get_priv_flags,
316962306a36Sopenharmony_ci	.set_priv_flags		= lio_set_priv_flags,
317062306a36Sopenharmony_ci	.get_ts_info		= lio_get_ts_info,
317162306a36Sopenharmony_ci};
317262306a36Sopenharmony_ci
317362306a36Sopenharmony_civoid liquidio_set_ethtool_ops(struct net_device *netdev)
317462306a36Sopenharmony_ci{
317562306a36Sopenharmony_ci	struct lio *lio = GET_LIO(netdev);
317662306a36Sopenharmony_ci	struct octeon_device *oct = lio->oct_dev;
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci	if (OCTEON_CN23XX_VF(oct))
317962306a36Sopenharmony_ci		netdev->ethtool_ops = &lio_vf_ethtool_ops;
318062306a36Sopenharmony_ci	else
318162306a36Sopenharmony_ci		netdev->ethtool_ops = &lio_ethtool_ops;
318262306a36Sopenharmony_ci}
318362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(liquidio_set_ethtool_ops);
3184