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