brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · 19c9952 Raw
299 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  FUJITSU Extended Socket Network Device driver4 *  Copyright (c) 2015 FUJITSU LIMITED5 */6 7/* ethtool support for fjes */8 9#include <linux/vmalloc.h>10#include <linux/netdevice.h>11#include <linux/ethtool.h>12#include <linux/platform_device.h>13 14#include "fjes.h"15 16struct fjes_stats {17	char stat_string[ETH_GSTRING_LEN];18	int sizeof_stat;19	int stat_offset;20};21 22#define FJES_STAT(name, stat) { \23	.stat_string = name, \24	.sizeof_stat = sizeof_field(struct fjes_adapter, stat), \25	.stat_offset = offsetof(struct fjes_adapter, stat) \26}27 28static const struct fjes_stats fjes_gstrings_stats[] = {29	FJES_STAT("rx_packets", stats64.rx_packets),30	FJES_STAT("tx_packets", stats64.tx_packets),31	FJES_STAT("rx_bytes", stats64.rx_bytes),32	FJES_STAT("tx_bytes", stats64.rx_bytes),33	FJES_STAT("rx_dropped", stats64.rx_dropped),34	FJES_STAT("tx_dropped", stats64.tx_dropped),35};36 37#define FJES_EP_STATS_LEN 1438#define FJES_STATS_LEN \39	(ARRAY_SIZE(fjes_gstrings_stats) + \40	 ((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \41	 FJES_EP_STATS_LEN)42 43static void fjes_get_ethtool_stats(struct net_device *netdev,44				   struct ethtool_stats *stats, u64 *data)45{46	struct fjes_adapter *adapter = netdev_priv(netdev);47	struct fjes_hw *hw = &adapter->hw;48	int epidx;49	char *p;50	int i;51 52	for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) {53		p = (char *)adapter + fjes_gstrings_stats[i].stat_offset;54		data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))55			? *(u64 *)p : *(u32 *)p;56	}57	for (epidx = 0; epidx < hw->max_epid; epidx++) {58		if (epidx == hw->my_epid)59			continue;60		data[i++] = hw->ep_shm_info[epidx].ep_stats61				.com_regist_buf_exec;62		data[i++] = hw->ep_shm_info[epidx].ep_stats63				.com_unregist_buf_exec;64		data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx;65		data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare;66		data[i++] = hw->ep_shm_info[epidx].ep_stats67				.send_intr_zoneupdate;68		data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx;69		data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare;70		data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop;71		data[i++] = hw->ep_shm_info[epidx].ep_stats72				.recv_intr_zoneupdate;73		data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full;74		data[i++] = hw->ep_shm_info[epidx].ep_stats75				.tx_dropped_not_shared;76		data[i++] = hw->ep_shm_info[epidx].ep_stats77				.tx_dropped_ver_mismatch;78		data[i++] = hw->ep_shm_info[epidx].ep_stats79				.tx_dropped_buf_size_mismatch;80		data[i++] = hw->ep_shm_info[epidx].ep_stats81				.tx_dropped_vlanid_mismatch;82	}83}84 85static void fjes_get_strings(struct net_device *netdev,86			     u32 stringset, u8 *data)87{88	struct fjes_adapter *adapter = netdev_priv(netdev);89	struct fjes_hw *hw = &adapter->hw;90	u8 *p = data;91	int i;92 93	switch (stringset) {94	case ETH_SS_STATS:95		for (i = 0; i < ARRAY_SIZE(fjes_gstrings_stats); i++) {96			memcpy(p, fjes_gstrings_stats[i].stat_string,97			       ETH_GSTRING_LEN);98			p += ETH_GSTRING_LEN;99		}100		for (i = 0; i < hw->max_epid; i++) {101			if (i == hw->my_epid)102				continue;103			sprintf(p, "ep%u_com_regist_buf_exec", i);104			p += ETH_GSTRING_LEN;105			sprintf(p, "ep%u_com_unregist_buf_exec", i);106			p += ETH_GSTRING_LEN;107			sprintf(p, "ep%u_send_intr_rx", i);108			p += ETH_GSTRING_LEN;109			sprintf(p, "ep%u_send_intr_unshare", i);110			p += ETH_GSTRING_LEN;111			sprintf(p, "ep%u_send_intr_zoneupdate", i);112			p += ETH_GSTRING_LEN;113			sprintf(p, "ep%u_recv_intr_rx", i);114			p += ETH_GSTRING_LEN;115			sprintf(p, "ep%u_recv_intr_unshare", i);116			p += ETH_GSTRING_LEN;117			sprintf(p, "ep%u_recv_intr_stop", i);118			p += ETH_GSTRING_LEN;119			sprintf(p, "ep%u_recv_intr_zoneupdate", i);120			p += ETH_GSTRING_LEN;121			sprintf(p, "ep%u_tx_buffer_full", i);122			p += ETH_GSTRING_LEN;123			sprintf(p, "ep%u_tx_dropped_not_shared", i);124			p += ETH_GSTRING_LEN;125			sprintf(p, "ep%u_tx_dropped_ver_mismatch", i);126			p += ETH_GSTRING_LEN;127			sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i);128			p += ETH_GSTRING_LEN;129			sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i);130			p += ETH_GSTRING_LEN;131		}132		break;133	}134}135 136static int fjes_get_sset_count(struct net_device *netdev, int sset)137{138	switch (sset) {139	case ETH_SS_STATS:140		return FJES_STATS_LEN;141	default:142		return -EOPNOTSUPP;143	}144}145 146static void fjes_get_drvinfo(struct net_device *netdev,147			     struct ethtool_drvinfo *drvinfo)148{149	struct fjes_adapter *adapter = netdev_priv(netdev);150	struct platform_device *plat_dev;151 152	plat_dev = adapter->plat_dev;153 154	strscpy(drvinfo->driver, fjes_driver_name, sizeof(drvinfo->driver));155	strscpy(drvinfo->version, fjes_driver_version,156		sizeof(drvinfo->version));157 158	strscpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version));159	snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),160		 "platform:%s", plat_dev->name);161}162 163static int fjes_get_link_ksettings(struct net_device *netdev,164				   struct ethtool_link_ksettings *ecmd)165{166	ethtool_link_ksettings_zero_link_mode(ecmd, supported);167	ethtool_link_ksettings_zero_link_mode(ecmd, advertising);168	ecmd->base.duplex = DUPLEX_FULL;169	ecmd->base.autoneg = AUTONEG_DISABLE;170	ecmd->base.port = PORT_NONE;171	ecmd->base.speed = 20000;	/* 20Gb/s */172 173	return 0;174}175 176static int fjes_get_regs_len(struct net_device *netdev)177{178#define FJES_REGS_LEN	37179	return FJES_REGS_LEN * sizeof(u32);180}181 182static void fjes_get_regs(struct net_device *netdev,183			  struct ethtool_regs *regs, void *p)184{185	struct fjes_adapter *adapter = netdev_priv(netdev);186	struct fjes_hw *hw = &adapter->hw;187	u32 *regs_buff = p;188 189	memset(p, 0, FJES_REGS_LEN * sizeof(u32));190 191	regs->version = 1;192 193	/* Information registers */194	regs_buff[0] = rd32(XSCT_OWNER_EPID);195	regs_buff[1] = rd32(XSCT_MAX_EP);196 197	/* Device Control registers */198	regs_buff[4] = rd32(XSCT_DCTL);199 200	/* Command Control registers */201	regs_buff[8] = rd32(XSCT_CR);202	regs_buff[9] = rd32(XSCT_CS);203	regs_buff[10] = rd32(XSCT_SHSTSAL);204	regs_buff[11] = rd32(XSCT_SHSTSAH);205 206	regs_buff[13] = rd32(XSCT_REQBL);207	regs_buff[14] = rd32(XSCT_REQBAL);208	regs_buff[15] = rd32(XSCT_REQBAH);209 210	regs_buff[17] = rd32(XSCT_RESPBL);211	regs_buff[18] = rd32(XSCT_RESPBAL);212	regs_buff[19] = rd32(XSCT_RESPBAH);213 214	/* Interrupt Control registers */215	regs_buff[32] = rd32(XSCT_IS);216	regs_buff[33] = rd32(XSCT_IMS);217	regs_buff[34] = rd32(XSCT_IMC);218	regs_buff[35] = rd32(XSCT_IG);219	regs_buff[36] = rd32(XSCT_ICTL);220}221 222static int fjes_set_dump(struct net_device *netdev, struct ethtool_dump *dump)223{224	struct fjes_adapter *adapter = netdev_priv(netdev);225	struct fjes_hw *hw = &adapter->hw;226	int ret = 0;227 228	if (dump->flag) {229		if (hw->debug_mode)230			return -EPERM;231 232		hw->debug_mode = dump->flag;233 234		/* enable debug mode */235		mutex_lock(&hw->hw_info.lock);236		ret = fjes_hw_start_debug(hw);237		mutex_unlock(&hw->hw_info.lock);238 239		if (ret)240			hw->debug_mode = 0;241	} else {242		if (!hw->debug_mode)243			return -EPERM;244 245		/* disable debug mode */246		mutex_lock(&hw->hw_info.lock);247		ret = fjes_hw_stop_debug(hw);248		mutex_unlock(&hw->hw_info.lock);249	}250 251	return ret;252}253 254static int fjes_get_dump_flag(struct net_device *netdev,255			      struct ethtool_dump *dump)256{257	struct fjes_adapter *adapter = netdev_priv(netdev);258	struct fjes_hw *hw = &adapter->hw;259 260	dump->len = hw->hw_info.trace_size;261	dump->version = 1;262	dump->flag = hw->debug_mode;263 264	return 0;265}266 267static int fjes_get_dump_data(struct net_device *netdev,268			      struct ethtool_dump *dump, void *buf)269{270	struct fjes_adapter *adapter = netdev_priv(netdev);271	struct fjes_hw *hw = &adapter->hw;272	int ret = 0;273 274	if (hw->hw_info.trace)275		memcpy(buf, hw->hw_info.trace, hw->hw_info.trace_size);276	else277		ret = -EPERM;278 279	return ret;280}281 282static const struct ethtool_ops fjes_ethtool_ops = {283		.get_drvinfo		= fjes_get_drvinfo,284		.get_ethtool_stats = fjes_get_ethtool_stats,285		.get_strings      = fjes_get_strings,286		.get_sset_count   = fjes_get_sset_count,287		.get_regs		= fjes_get_regs,288		.get_regs_len		= fjes_get_regs_len,289		.set_dump		= fjes_set_dump,290		.get_dump_flag		= fjes_get_dump_flag,291		.get_dump_data		= fjes_get_dump_data,292		.get_link_ksettings	= fjes_get_link_ksettings,293};294 295void fjes_set_ethtool_ops(struct net_device *netdev)296{297	netdev->ethtool_ops = &fjes_ethtool_ops;298}299