brintos

brintos / linux-shallow public Read only

0
0
Text · 25.4 KiB · 8c4cb91 Raw
946 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2003 - 2009 NetXen, Inc.4 * Copyright (C) 2009 - QLogic Corporation.5 * All rights reserved.6 */7 8#include <linux/types.h>9#include <linux/delay.h>10#include <linux/pci.h>11#include <asm/io.h>12#include <linux/netdevice.h>13#include <linux/ethtool.h>14 15#include "netxen_nic.h"16#include "netxen_nic_hw.h"17 18struct netxen_nic_stats {19	char stat_string[ETH_GSTRING_LEN];20	int sizeof_stat;21	int stat_offset;22};23 24#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \25			offsetof(struct netxen_adapter, m)26 27#define NETXEN_NIC_PORT_WINDOW 0x1000028#define NETXEN_NIC_INVALID_DATA 0xDEADBEEF29 30static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {31	{"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},32	{"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},33	{"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},34	{"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},35	{"csummed", NETXEN_NIC_STAT(stats.csummed)},36	{"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},37	{"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},38	{"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},39	{"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},40};41 42#define NETXEN_NIC_STATS_LEN	ARRAY_SIZE(netxen_nic_gstrings_stats)43 44static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {45	"Register_Test_on_offline",46	"Link_Test_on_offline"47};48 49#define NETXEN_NIC_TEST_LEN	ARRAY_SIZE(netxen_nic_gstrings_test)50 51#define NETXEN_NIC_REGS_COUNT 3052#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))53#define NETXEN_MAX_EEPROM_LEN   102454 55static int netxen_nic_get_eeprom_len(struct net_device *dev)56{57	return NETXEN_FLASH_TOTAL_SIZE;58}59 60static void61netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)62{63	struct netxen_adapter *adapter = netdev_priv(dev);64	u32 fw_major = 0;65	u32 fw_minor = 0;66	u32 fw_build = 0;67 68	strscpy(drvinfo->driver, netxen_nic_driver_name,69		sizeof(drvinfo->driver));70	strscpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,71		sizeof(drvinfo->version));72	fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);73	fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);74	fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);75	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),76		"%d.%d.%d", fw_major, fw_minor, fw_build);77 78	strscpy(drvinfo->bus_info, pci_name(adapter->pdev),79		sizeof(drvinfo->bus_info));80}81 82static int83netxen_nic_get_link_ksettings(struct net_device *dev,84			      struct ethtool_link_ksettings *cmd)85{86	struct netxen_adapter *adapter = netdev_priv(dev);87	int check_sfp_module = 0;88	u32 supported, advertising;89 90	/* read which mode */91	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {92		supported = (SUPPORTED_10baseT_Half |93				   SUPPORTED_10baseT_Full |94				   SUPPORTED_100baseT_Half |95				   SUPPORTED_100baseT_Full |96				   SUPPORTED_1000baseT_Half |97				   SUPPORTED_1000baseT_Full);98 99		advertising = (ADVERTISED_100baseT_Half |100				     ADVERTISED_100baseT_Full |101				     ADVERTISED_1000baseT_Half |102				     ADVERTISED_1000baseT_Full);103 104		cmd->base.port = PORT_TP;105 106		cmd->base.speed = adapter->link_speed;107		cmd->base.duplex = adapter->link_duplex;108		cmd->base.autoneg = adapter->link_autoneg;109 110	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {111		u32 val;112 113		val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);114		if (val == NETXEN_PORT_MODE_802_3_AP) {115			supported = SUPPORTED_1000baseT_Full;116			advertising = ADVERTISED_1000baseT_Full;117		} else {118			supported = SUPPORTED_10000baseT_Full;119			advertising = ADVERTISED_10000baseT_Full;120		}121 122		if (netif_running(dev) && adapter->has_link_events) {123			cmd->base.speed = adapter->link_speed;124			cmd->base.autoneg = adapter->link_autoneg;125			cmd->base.duplex = adapter->link_duplex;126			goto skip;127		}128 129		cmd->base.port = PORT_TP;130 131		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {132			u16 pcifn = adapter->ahw.pci_func;133 134			val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));135			cmd->base.speed = P3_LINK_SPEED_MHZ *136				P3_LINK_SPEED_VAL(pcifn, val);137		} else138			cmd->base.speed = SPEED_10000;139 140		cmd->base.duplex = DUPLEX_FULL;141		cmd->base.autoneg = AUTONEG_DISABLE;142	} else143		return -EIO;144 145skip:146	cmd->base.phy_address = adapter->physical_port;147 148	switch (adapter->ahw.board_type) {149	case NETXEN_BRDTYPE_P2_SB35_4G:150	case NETXEN_BRDTYPE_P2_SB31_2G:151	case NETXEN_BRDTYPE_P3_REF_QG:152	case NETXEN_BRDTYPE_P3_4_GB:153	case NETXEN_BRDTYPE_P3_4_GB_MM:154		supported |= SUPPORTED_Autoneg;155		advertising |= ADVERTISED_Autoneg;156		fallthrough;157	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:158	case NETXEN_BRDTYPE_P3_10G_CX4:159	case NETXEN_BRDTYPE_P3_10G_CX4_LP:160	case NETXEN_BRDTYPE_P3_10000_BASE_T:161		supported |= SUPPORTED_TP;162		advertising |= ADVERTISED_TP;163		cmd->base.port = PORT_TP;164		cmd->base.autoneg = (adapter->ahw.board_type ==165				 NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?166		    (AUTONEG_DISABLE) : (adapter->link_autoneg);167		break;168	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:169	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:170	case NETXEN_BRDTYPE_P3_IMEZ:171	case NETXEN_BRDTYPE_P3_XG_LOM:172	case NETXEN_BRDTYPE_P3_HMEZ:173		supported |= SUPPORTED_MII;174		advertising |= ADVERTISED_MII;175		cmd->base.port = PORT_MII;176		cmd->base.autoneg = AUTONEG_DISABLE;177		break;178	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:179	case NETXEN_BRDTYPE_P3_10G_SFP_CT:180	case NETXEN_BRDTYPE_P3_10G_SFP_QT:181		advertising |= ADVERTISED_TP;182		supported |= SUPPORTED_TP;183		check_sfp_module = netif_running(dev) &&184			adapter->has_link_events;185		fallthrough;186	case NETXEN_BRDTYPE_P2_SB31_10G:187	case NETXEN_BRDTYPE_P3_10G_XFP:188		supported |= SUPPORTED_FIBRE;189		advertising |= ADVERTISED_FIBRE;190		cmd->base.port = PORT_FIBRE;191		cmd->base.autoneg = AUTONEG_DISABLE;192		break;193	case NETXEN_BRDTYPE_P3_10G_TP:194		if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {195			cmd->base.autoneg = AUTONEG_DISABLE;196			supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);197			advertising |=198				(ADVERTISED_FIBRE | ADVERTISED_TP);199			cmd->base.port = PORT_FIBRE;200			check_sfp_module = netif_running(dev) &&201				adapter->has_link_events;202		} else {203			supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);204			advertising |=205				(ADVERTISED_TP | ADVERTISED_Autoneg);206			cmd->base.port = PORT_TP;207		}208		break;209	default:210		printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",211				adapter->ahw.board_type);212		return -EIO;213	}214 215	if (check_sfp_module) {216		switch (adapter->module_type) {217		case LINKEVENT_MODULE_OPTICAL_UNKNOWN:218		case LINKEVENT_MODULE_OPTICAL_SRLR:219		case LINKEVENT_MODULE_OPTICAL_LRM:220		case LINKEVENT_MODULE_OPTICAL_SFP_1G:221			cmd->base.port = PORT_FIBRE;222			break;223		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:224		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:225		case LINKEVENT_MODULE_TWINAX:226			cmd->base.port = PORT_TP;227			break;228		default:229			cmd->base.port = -1;230		}231	}232 233	if (!netif_running(dev) || !adapter->ahw.linkup) {234		cmd->base.duplex = DUPLEX_UNKNOWN;235		cmd->base.speed = SPEED_UNKNOWN;236	}237 238	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,239						supported);240	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,241						advertising);242 243	return 0;244}245 246static int247netxen_nic_set_link_ksettings(struct net_device *dev,248			      const struct ethtool_link_ksettings *cmd)249{250	struct netxen_adapter *adapter = netdev_priv(dev);251	u32 speed = cmd->base.speed;252	int ret;253 254	if (adapter->ahw.port_type != NETXEN_NIC_GBE)255		return -EOPNOTSUPP;256 257	if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))258		return -EOPNOTSUPP;259 260	ret = nx_fw_cmd_set_gbe_port(adapter, speed, cmd->base.duplex,261				     cmd->base.autoneg);262	if (ret == NX_RCODE_NOT_SUPPORTED)263		return -EOPNOTSUPP;264	else if (ret)265		return -EIO;266 267	adapter->link_speed = speed;268	adapter->link_duplex = cmd->base.duplex;269	adapter->link_autoneg = cmd->base.autoneg;270 271	if (!netif_running(dev))272		return 0;273 274	dev->netdev_ops->ndo_stop(dev);275	return dev->netdev_ops->ndo_open(dev);276}277 278static int netxen_nic_get_regs_len(struct net_device *dev)279{280	return NETXEN_NIC_REGS_LEN;281}282 283static void284netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)285{286	struct netxen_adapter *adapter = netdev_priv(dev);287	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;288	struct nx_host_sds_ring *sds_ring;289	u32 *regs_buff = p;290	int ring, i = 0;291	int port = adapter->physical_port;292 293	memset(p, 0, NETXEN_NIC_REGS_LEN);294 295	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |296	    (adapter->pdev)->device;297 298	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)299		return;300 301	regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);302	regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);303	regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);304	regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);305	regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);306	regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);307	regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);308	regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);309	regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);310 311	regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);312	regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);313	regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);314	regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);315 316	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {317 318		regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);319		i += 2;320 321		regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);322		regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));323 324	} else {325		i++;326 327		regs_buff[i++] = NXRD32(adapter,328					NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));329		regs_buff[i++] = NXRD32(adapter,330					NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));331 332		regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);333		regs_buff[i++] = NXRDIO(adapter,334				 adapter->tx_ring->crb_cmd_consumer);335	}336 337	regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);338 339	regs_buff[i++] = NXRDIO(adapter,340			 recv_ctx->rds_rings[0].crb_rcv_producer);341	regs_buff[i++] = NXRDIO(adapter,342			 recv_ctx->rds_rings[1].crb_rcv_producer);343 344	regs_buff[i++] = adapter->max_sds_rings;345 346	for (ring = 0; ring < adapter->max_sds_rings; ring++) {347		sds_ring = &(recv_ctx->sds_rings[ring]);348		regs_buff[i++] = NXRDIO(adapter,349					sds_ring->crb_sts_consumer);350	}351}352 353static u32 netxen_nic_test_link(struct net_device *dev)354{355	struct netxen_adapter *adapter = netdev_priv(dev);356	u32 val, port;357 358	port = adapter->physical_port;359	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {360		val = NXRD32(adapter, CRB_XG_STATE_P3);361		val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);362		return (val == XG_LINK_UP_P3) ? 0 : 1;363	} else {364		val = NXRD32(adapter, CRB_XG_STATE);365		val = (val >> port*8) & 0xff;366		return (val == XG_LINK_UP) ? 0 : 1;367	}368}369 370static int371netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,372		      u8 *bytes)373{374	struct netxen_adapter *adapter = netdev_priv(dev);375	int offset;376	int ret;377 378	if (eeprom->len == 0)379		return -EINVAL;380 381	eeprom->magic = (adapter->pdev)->vendor |382			((adapter->pdev)->device << 16);383	offset = eeprom->offset;384 385	ret = netxen_rom_fast_read_words(adapter, offset, bytes,386						eeprom->len);387	if (ret < 0)388		return ret;389 390	return 0;391}392 393static void394netxen_nic_get_ringparam(struct net_device *dev,395			 struct ethtool_ringparam *ring,396			 struct kernel_ethtool_ringparam *kernel_ring,397			 struct netlink_ext_ack *extack)398{399	struct netxen_adapter *adapter = netdev_priv(dev);400 401	ring->rx_pending = adapter->num_rxd;402	ring->rx_jumbo_pending = adapter->num_jumbo_rxd;403	ring->rx_jumbo_pending += adapter->num_lro_rxd;404	ring->tx_pending = adapter->num_txd;405 406	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {407		ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;408		ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;409	} else {410		ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;411		ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;412	}413 414	ring->tx_max_pending = MAX_CMD_DESCRIPTORS;415}416 417static u32418netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)419{420	u32 num_desc;421	num_desc = max(val, min);422	num_desc = min(num_desc, max);423	num_desc = roundup_pow_of_two(num_desc);424 425	if (val != num_desc) {426		printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",427		       netxen_nic_driver_name, r_name, num_desc, val);428	}429 430	return num_desc;431}432 433static int434netxen_nic_set_ringparam(struct net_device *dev,435			 struct ethtool_ringparam *ring,436			 struct kernel_ethtool_ringparam *kernel_ring,437			 struct netlink_ext_ack *extack)438{439	struct netxen_adapter *adapter = netdev_priv(dev);440	u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;441	u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;442	u16 num_rxd, num_jumbo_rxd, num_txd;443 444	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))445		return -EOPNOTSUPP;446 447	if (ring->rx_mini_pending)448		return -EOPNOTSUPP;449 450	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {451		max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;452		max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;453	}454 455	num_rxd = netxen_validate_ringparam(ring->rx_pending,456			MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");457 458	num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,459			MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");460 461	num_txd = netxen_validate_ringparam(ring->tx_pending,462			MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");463 464	if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&465			num_jumbo_rxd == adapter->num_jumbo_rxd)466		return 0;467 468	adapter->num_rxd = num_rxd;469	adapter->num_jumbo_rxd = num_jumbo_rxd;470	adapter->num_txd = num_txd;471 472	return netxen_nic_reset_context(adapter);473}474 475static void476netxen_nic_get_pauseparam(struct net_device *dev,477			  struct ethtool_pauseparam *pause)478{479	struct netxen_adapter *adapter = netdev_priv(dev);480	__u32 val;481	int port = adapter->physical_port;482 483	pause->autoneg = 0;484 485	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {486		if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))487			return;488		/* get flow control settings */489		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));490		pause->rx_pause = netxen_gb_get_rx_flowctl(val);491		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);492		switch (port) {493		case 0:494			pause->tx_pause = !(netxen_gb_get_gb0_mask(val));495			break;496		case 1:497			pause->tx_pause = !(netxen_gb_get_gb1_mask(val));498			break;499		case 2:500			pause->tx_pause = !(netxen_gb_get_gb2_mask(val));501			break;502		case 3:503		default:504			pause->tx_pause = !(netxen_gb_get_gb3_mask(val));505			break;506		}507	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {508		if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))509			return;510		pause->rx_pause = 1;511		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);512		if (port == 0)513			pause->tx_pause = !(netxen_xg_get_xg0_mask(val));514		else515			pause->tx_pause = !(netxen_xg_get_xg1_mask(val));516	} else {517		printk(KERN_ERR"%s: Unknown board type: %x\n",518				netxen_nic_driver_name, adapter->ahw.port_type);519	}520}521 522static int523netxen_nic_set_pauseparam(struct net_device *dev,524			  struct ethtool_pauseparam *pause)525{526	struct netxen_adapter *adapter = netdev_priv(dev);527	__u32 val;528	int port = adapter->physical_port;529 530	/* not supported */531	if (pause->autoneg)532		return -EINVAL;533 534	/* read mode */535	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {536		if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))537			return -EIO;538		/* set flow control */539		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));540 541		if (pause->rx_pause)542			netxen_gb_rx_flowctl(val);543		else544			netxen_gb_unset_rx_flowctl(val);545 546		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),547				val);548		/* set autoneg */549		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);550		switch (port) {551		case 0:552			if (pause->tx_pause)553				netxen_gb_unset_gb0_mask(val);554			else555				netxen_gb_set_gb0_mask(val);556			break;557		case 1:558			if (pause->tx_pause)559				netxen_gb_unset_gb1_mask(val);560			else561				netxen_gb_set_gb1_mask(val);562			break;563		case 2:564			if (pause->tx_pause)565				netxen_gb_unset_gb2_mask(val);566			else567				netxen_gb_set_gb2_mask(val);568			break;569		case 3:570		default:571			if (pause->tx_pause)572				netxen_gb_unset_gb3_mask(val);573			else574				netxen_gb_set_gb3_mask(val);575			break;576		}577		NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);578	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {579		if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))580			return -EIO;581		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);582		if (port == 0) {583			if (pause->tx_pause)584				netxen_xg_unset_xg0_mask(val);585			else586				netxen_xg_set_xg0_mask(val);587		} else {588			if (pause->tx_pause)589				netxen_xg_unset_xg1_mask(val);590			else591				netxen_xg_set_xg1_mask(val);592		}593		NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);594	} else {595		printk(KERN_ERR "%s: Unknown board type: %x\n",596				netxen_nic_driver_name,597				adapter->ahw.port_type);598	}599	return 0;600}601 602static int netxen_nic_reg_test(struct net_device *dev)603{604	struct netxen_adapter *adapter = netdev_priv(dev);605	u32 data_read, data_written;606 607	data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));608	if ((data_read & 0xffff) != adapter->pdev->vendor)609		return 1;610 611	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))612		return 0;613 614	data_written = (u32)0xa5a5a5a5;615 616	NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);617	data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);618	if (data_written != data_read)619		return 1;620 621	return 0;622}623 624static int netxen_get_sset_count(struct net_device *dev, int sset)625{626	switch (sset) {627	case ETH_SS_TEST:628		return NETXEN_NIC_TEST_LEN;629	case ETH_SS_STATS:630		return NETXEN_NIC_STATS_LEN;631	default:632		return -EOPNOTSUPP;633	}634}635 636static void637netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,638		     u64 *data)639{640	memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);641	if ((data[0] = netxen_nic_reg_test(dev)))642		eth_test->flags |= ETH_TEST_FL_FAILED;643	/* link test */644	if ((data[1] = (u64) netxen_nic_test_link(dev)))645		eth_test->flags |= ETH_TEST_FL_FAILED;646}647 648static void649netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)650{651	int index;652 653	switch (stringset) {654	case ETH_SS_TEST:655		memcpy(data, *netxen_nic_gstrings_test,656		       NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);657		break;658	case ETH_SS_STATS:659		for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {660			memcpy(data + index * ETH_GSTRING_LEN,661			       netxen_nic_gstrings_stats[index].stat_string,662			       ETH_GSTRING_LEN);663		}664		break;665	}666}667 668static void669netxen_nic_get_ethtool_stats(struct net_device *dev,670			     struct ethtool_stats *stats, u64 *data)671{672	struct netxen_adapter *adapter = netdev_priv(dev);673	int index;674 675	for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {676		char *p =677		    (char *)adapter +678		    netxen_nic_gstrings_stats[index].stat_offset;679		data[index] =680		    (netxen_nic_gstrings_stats[index].sizeof_stat ==681		     sizeof(u64)) ? *(u64 *) p : *(u32 *) p;682	}683}684 685static void686netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)687{688	struct netxen_adapter *adapter = netdev_priv(dev);689	u32 wol_cfg = 0;690 691	wol->supported = 0;692	wol->wolopts = 0;693 694	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))695		return;696 697	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);698	if (wol_cfg & (1UL << adapter->portnum))699		wol->supported |= WAKE_MAGIC;700 701	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);702	if (wol_cfg & (1UL << adapter->portnum))703		wol->wolopts |= WAKE_MAGIC;704}705 706static int707netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)708{709	struct netxen_adapter *adapter = netdev_priv(dev);710	u32 wol_cfg = 0;711 712	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))713		return -EOPNOTSUPP;714 715	if (wol->wolopts & ~WAKE_MAGIC)716		return -EOPNOTSUPP;717 718	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);719	if (!(wol_cfg & (1 << adapter->portnum)))720		return -EOPNOTSUPP;721 722	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);723	if (wol->wolopts & WAKE_MAGIC)724		wol_cfg |= 1UL << adapter->portnum;725	else726		wol_cfg &= ~(1UL << adapter->portnum);727	NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);728 729	return 0;730}731 732/*733 * Set the coalescing parameters. Currently only normal is supported.734 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the735 * firmware coalescing to default.736 */737static int netxen_set_intr_coalesce(struct net_device *netdev,738				    struct ethtool_coalesce *ethcoal,739				    struct kernel_ethtool_coalesce *kernel_coal,740				    struct netlink_ext_ack *extack)741{742	struct netxen_adapter *adapter = netdev_priv(netdev);743 744	if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))745		return -EINVAL;746 747	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)748		return -EINVAL;749 750	/*751	* Return Error if unsupported values or752	* unsupported parameters are set.753	*/754	if (ethcoal->rx_coalesce_usecs > 0xffff ||755		ethcoal->rx_max_coalesced_frames > 0xffff ||756		ethcoal->tx_coalesce_usecs > 0xffff ||757		ethcoal->tx_max_coalesced_frames > 0xffff)758		return -EINVAL;759 760	if (!ethcoal->rx_coalesce_usecs ||761		!ethcoal->rx_max_coalesced_frames) {762		adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;763		adapter->coal.normal.data.rx_time_us =764			NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;765		adapter->coal.normal.data.rx_packets =766			NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;767	} else {768		adapter->coal.flags = 0;769		adapter->coal.normal.data.rx_time_us =770		ethcoal->rx_coalesce_usecs;771		adapter->coal.normal.data.rx_packets =772		ethcoal->rx_max_coalesced_frames;773	}774	adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;775	adapter->coal.normal.data.tx_packets =776	ethcoal->tx_max_coalesced_frames;777 778	netxen_config_intr_coalesce(adapter);779 780	return 0;781}782 783static int netxen_get_intr_coalesce(struct net_device *netdev,784				    struct ethtool_coalesce *ethcoal,785				    struct kernel_ethtool_coalesce *kernel_coal,786				    struct netlink_ext_ack *extack)787{788	struct netxen_adapter *adapter = netdev_priv(netdev);789 790	if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))791		return -EINVAL;792 793	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)794		return -EINVAL;795 796	ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;797	ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;798	ethcoal->rx_max_coalesced_frames =799		adapter->coal.normal.data.rx_packets;800	ethcoal->tx_max_coalesced_frames =801		adapter->coal.normal.data.tx_packets;802 803	return 0;804}805 806static int807netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)808{809	struct netxen_adapter *adapter = netdev_priv(netdev);810	struct netxen_minidump *mdump = &adapter->mdump;811	if (adapter->fw_mdump_rdy)812		dump->len = mdump->md_dump_size;813	else814		dump->len = 0;815 816	if (!mdump->md_enabled)817		dump->flag = ETH_FW_DUMP_DISABLE;818	else819		dump->flag = mdump->md_capture_mask;820 821	dump->version = adapter->fw_version;822	return 0;823}824 825/* Fw dump levels */826static const u32 FW_DUMP_LEVELS[] = { 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };827 828static int829netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)830{831	int i;832	struct netxen_adapter *adapter = netdev_priv(netdev);833	struct netxen_minidump *mdump = &adapter->mdump;834 835	switch (val->flag) {836	case NX_FORCE_FW_DUMP_KEY:837		if (!mdump->md_enabled) {838			netdev_info(netdev, "FW dump not enabled\n");839			return 0;840		}841		if (adapter->fw_mdump_rdy) {842			netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");843			return 0;844		}845		netdev_info(netdev, "Forcing a fw dump\n");846		nx_dev_request_reset(adapter);847		break;848	case NX_DISABLE_FW_DUMP:849		if (mdump->md_enabled) {850			netdev_info(netdev, "Disabling FW Dump\n");851			mdump->md_enabled = 0;852		}853		break;854	case NX_ENABLE_FW_DUMP:855		if (!mdump->md_enabled) {856			netdev_info(netdev, "Enabling FW dump\n");857			mdump->md_enabled = 1;858		}859		break;860	case NX_FORCE_FW_RESET:861		netdev_info(netdev, "Forcing FW reset\n");862		nx_dev_request_reset(adapter);863		adapter->flags &= ~NETXEN_FW_RESET_OWNER;864		break;865	default:866		for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {867			if (val->flag == FW_DUMP_LEVELS[i]) {868				mdump->md_capture_mask = val->flag;869				netdev_info(netdev,870					"Driver mask changed to: 0x%x\n",871					mdump->md_capture_mask);872				return 0;873			}874		}875		netdev_info(netdev,876			"Invalid dump level: 0x%x\n", val->flag);877		return -EINVAL;878	}879 880	return 0;881}882 883static int884netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,885			void *buffer)886{887	int i, copy_sz;888	u32 *hdr_ptr, *data;889	struct netxen_adapter *adapter = netdev_priv(netdev);890	struct netxen_minidump *mdump = &adapter->mdump;891 892 893	if (!adapter->fw_mdump_rdy) {894		netdev_info(netdev, "Dump not available\n");895		return -EINVAL;896	}897	/* Copy template header first */898	copy_sz = mdump->md_template_size;899	hdr_ptr = (u32 *) mdump->md_template;900	data = buffer;901	for (i = 0; i < copy_sz/sizeof(u32); i++)902		*data++ = cpu_to_le32(*hdr_ptr++);903 904	/* Copy captured dump data */905	memcpy(buffer + copy_sz,906		mdump->md_capture_buff + mdump->md_template_size,907			mdump->md_capture_size);908	dump->len = copy_sz + mdump->md_capture_size;909	dump->flag = mdump->md_capture_mask;910 911	/* Free dump area once data has been captured */912	vfree(mdump->md_capture_buff);913	mdump->md_capture_buff = NULL;914	adapter->fw_mdump_rdy = 0;915	netdev_info(netdev, "extracted the fw dump Successfully\n");916	return 0;917}918 919const struct ethtool_ops netxen_nic_ethtool_ops = {920	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |921				     ETHTOOL_COALESCE_MAX_FRAMES,922	.get_drvinfo = netxen_nic_get_drvinfo,923	.get_regs_len = netxen_nic_get_regs_len,924	.get_regs = netxen_nic_get_regs,925	.get_link = ethtool_op_get_link,926	.get_eeprom_len = netxen_nic_get_eeprom_len,927	.get_eeprom = netxen_nic_get_eeprom,928	.get_ringparam = netxen_nic_get_ringparam,929	.set_ringparam = netxen_nic_set_ringparam,930	.get_pauseparam = netxen_nic_get_pauseparam,931	.set_pauseparam = netxen_nic_set_pauseparam,932	.get_wol = netxen_nic_get_wol,933	.set_wol = netxen_nic_set_wol,934	.self_test = netxen_nic_diag_test,935	.get_strings = netxen_nic_get_strings,936	.get_ethtool_stats = netxen_nic_get_ethtool_stats,937	.get_sset_count = netxen_get_sset_count,938	.get_coalesce = netxen_get_intr_coalesce,939	.set_coalesce = netxen_set_intr_coalesce,940	.get_dump_flag = netxen_get_dump_flag,941	.get_dump_data = netxen_get_dump_data,942	.set_dump = netxen_set_dump,943	.get_link_ksettings = netxen_nic_get_link_ksettings,944	.set_link_ksettings = netxen_nic_set_link_ksettings,945};946