1138 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */3 4#include <linux/module.h>5#include <linux/netdevice.h>6#include <linux/sfp.h>7 8#include "ionic.h"9#include "ionic_bus.h"10#include "ionic_lif.h"11#include "ionic_ethtool.h"12#include "ionic_stats.h"13 14#define IONIC_MAX_RX_COPYBREAK min(U16_MAX, IONIC_MAX_BUF_LEN)15 16static void ionic_get_stats_strings(struct ionic_lif *lif, u8 *buf)17{18 u32 i;19 20 for (i = 0; i < ionic_num_stats_grps; i++)21 ionic_stats_groups[i].get_strings(lif, &buf);22}23 24static void ionic_get_stats(struct net_device *netdev,25 struct ethtool_stats *stats, u64 *buf)26{27 struct ionic_lif *lif = netdev_priv(netdev);28 u32 i;29 30 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))31 return;32 33 memset(buf, 0, stats->n_stats * sizeof(*buf));34 for (i = 0; i < ionic_num_stats_grps; i++)35 ionic_stats_groups[i].get_values(lif, &buf);36}37 38static int ionic_get_stats_count(struct ionic_lif *lif)39{40 int i, num_stats = 0;41 42 for (i = 0; i < ionic_num_stats_grps; i++)43 num_stats += ionic_stats_groups[i].get_count(lif);44 45 return num_stats;46}47 48static int ionic_get_sset_count(struct net_device *netdev, int sset)49{50 struct ionic_lif *lif = netdev_priv(netdev);51 int count = 0;52 53 switch (sset) {54 case ETH_SS_STATS:55 count = ionic_get_stats_count(lif);56 break;57 }58 return count;59}60 61static void ionic_get_strings(struct net_device *netdev,62 u32 sset, u8 *buf)63{64 struct ionic_lif *lif = netdev_priv(netdev);65 66 switch (sset) {67 case ETH_SS_STATS:68 ionic_get_stats_strings(lif, buf);69 break;70 }71}72 73static void ionic_get_drvinfo(struct net_device *netdev,74 struct ethtool_drvinfo *drvinfo)75{76 struct ionic_lif *lif = netdev_priv(netdev);77 struct ionic *ionic = lif->ionic;78 79 strscpy(drvinfo->driver, IONIC_DRV_NAME, sizeof(drvinfo->driver));80 strscpy(drvinfo->fw_version, ionic->idev.dev_info.fw_version,81 sizeof(drvinfo->fw_version));82 strscpy(drvinfo->bus_info, ionic_bus_info(ionic),83 sizeof(drvinfo->bus_info));84}85 86static int ionic_get_regs_len(struct net_device *netdev)87{88 return (IONIC_DEV_INFO_REG_COUNT + IONIC_DEV_CMD_REG_COUNT) * sizeof(u32);89}90 91static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,92 void *p)93{94 struct ionic_lif *lif = netdev_priv(netdev);95 struct ionic_dev *idev;96 unsigned int offset;97 unsigned int size;98 99 regs->version = IONIC_DEV_CMD_REG_VERSION;100 101 idev = &lif->ionic->idev;102 if (!idev->dev_info_regs)103 return;104 105 offset = 0;106 size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);107 memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);108 109 offset += size;110 size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);111 memcpy_fromio(p + offset, idev->dev_cmd_regs->words, size);112}113 114static void ionic_get_link_ext_stats(struct net_device *netdev,115 struct ethtool_link_ext_stats *stats)116{117 struct ionic_lif *lif = netdev_priv(netdev);118 119 if (lif->ionic->pdev->is_physfn)120 stats->link_down_events = lif->link_down_count;121}122 123static int ionic_get_link_ksettings(struct net_device *netdev,124 struct ethtool_link_ksettings *ks)125{126 struct ionic_lif *lif = netdev_priv(netdev);127 struct ionic_dev *idev = &lif->ionic->idev;128 int copper_seen = 0;129 130 ethtool_link_ksettings_zero_link_mode(ks, supported);131 132 if (!idev->port_info) {133 netdev_err(netdev, "port_info not initialized\n");134 return -EOPNOTSUPP;135 }136 137 /* The port_info data is found in a DMA space that the NIC keeps138 * up-to-date, so there's no need to request the data from the139 * NIC, we already have it in our memory space.140 */141 142 switch (le16_to_cpu(idev->port_info->status.xcvr.pid)) {143 /* Copper */144 case IONIC_XCVR_PID_QSFP_100G_CR4:145 ethtool_link_ksettings_add_link_mode(ks, supported,146 100000baseCR4_Full);147 copper_seen++;148 break;149 case IONIC_XCVR_PID_QSFP_40GBASE_CR4:150 ethtool_link_ksettings_add_link_mode(ks, supported,151 40000baseCR4_Full);152 copper_seen++;153 break;154 case IONIC_XCVR_PID_SFP_25GBASE_CR_S:155 case IONIC_XCVR_PID_SFP_25GBASE_CR_L:156 case IONIC_XCVR_PID_SFP_25GBASE_CR_N:157 ethtool_link_ksettings_add_link_mode(ks, supported,158 25000baseCR_Full);159 copper_seen++;160 break;161 case IONIC_XCVR_PID_SFP_10GBASE_AOC:162 case IONIC_XCVR_PID_SFP_10GBASE_CU:163 ethtool_link_ksettings_add_link_mode(ks, supported,164 10000baseCR_Full);165 copper_seen++;166 break;167 168 /* Fibre */169 case IONIC_XCVR_PID_QSFP_100G_SR4:170 case IONIC_XCVR_PID_QSFP_100G_AOC:171 ethtool_link_ksettings_add_link_mode(ks, supported,172 100000baseSR4_Full);173 break;174 case IONIC_XCVR_PID_QSFP_100G_CWDM4:175 case IONIC_XCVR_PID_QSFP_100G_PSM4:176 case IONIC_XCVR_PID_QSFP_100G_LR4:177 ethtool_link_ksettings_add_link_mode(ks, supported,178 100000baseLR4_ER4_Full);179 break;180 case IONIC_XCVR_PID_QSFP_100G_ER4:181 ethtool_link_ksettings_add_link_mode(ks, supported,182 100000baseLR4_ER4_Full);183 break;184 case IONIC_XCVR_PID_QSFP_40GBASE_SR4:185 case IONIC_XCVR_PID_QSFP_40GBASE_AOC:186 ethtool_link_ksettings_add_link_mode(ks, supported,187 40000baseSR4_Full);188 break;189 case IONIC_XCVR_PID_QSFP_40GBASE_LR4:190 ethtool_link_ksettings_add_link_mode(ks, supported,191 40000baseLR4_Full);192 break;193 case IONIC_XCVR_PID_SFP_25GBASE_SR:194 case IONIC_XCVR_PID_SFP_25GBASE_AOC:195 case IONIC_XCVR_PID_SFP_25GBASE_ACC:196 ethtool_link_ksettings_add_link_mode(ks, supported,197 25000baseSR_Full);198 break;199 case IONIC_XCVR_PID_SFP_10GBASE_SR:200 ethtool_link_ksettings_add_link_mode(ks, supported,201 10000baseSR_Full);202 break;203 case IONIC_XCVR_PID_SFP_10GBASE_LR:204 ethtool_link_ksettings_add_link_mode(ks, supported,205 10000baseLR_Full);206 break;207 case IONIC_XCVR_PID_SFP_10GBASE_LRM:208 ethtool_link_ksettings_add_link_mode(ks, supported,209 10000baseLRM_Full);210 break;211 case IONIC_XCVR_PID_SFP_10GBASE_ER:212 ethtool_link_ksettings_add_link_mode(ks, supported,213 10000baseER_Full);214 break;215 case IONIC_XCVR_PID_SFP_10GBASE_T:216 ethtool_link_ksettings_add_link_mode(ks, supported,217 10000baseT_Full);218 break;219 case IONIC_XCVR_PID_SFP_1000BASE_T:220 ethtool_link_ksettings_add_link_mode(ks, supported,221 1000baseT_Full);222 break;223 case IONIC_XCVR_PID_UNKNOWN:224 /* This means there's no module plugged in */225 break;226 default:227 dev_info(lif->ionic->dev, "unknown xcvr type pid=%d / 0x%x\n",228 idev->port_info->status.xcvr.pid,229 idev->port_info->status.xcvr.pid);230 break;231 }232 233 linkmode_copy(ks->link_modes.advertising, ks->link_modes.supported);234 235 ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);236 ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);237 if (idev->port_info->config.fec_type == IONIC_PORT_FEC_TYPE_FC)238 ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_BASER);239 else if (idev->port_info->config.fec_type == IONIC_PORT_FEC_TYPE_RS)240 ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);241 242 ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE);243 ethtool_link_ksettings_add_link_mode(ks, supported, Pause);244 245 if (idev->port_info->status.xcvr.phy == IONIC_PHY_TYPE_COPPER ||246 copper_seen)247 ks->base.port = PORT_DA;248 else if (idev->port_info->status.xcvr.phy == IONIC_PHY_TYPE_FIBER)249 ks->base.port = PORT_FIBRE;250 else251 ks->base.port = PORT_NONE;252 253 if (ks->base.port != PORT_NONE) {254 ks->base.speed = le32_to_cpu(lif->info->status.link_speed);255 256 if (le16_to_cpu(lif->info->status.link_status))257 ks->base.duplex = DUPLEX_FULL;258 else259 ks->base.duplex = DUPLEX_UNKNOWN;260 261 ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);262 263 if (idev->port_info->config.an_enable) {264 ethtool_link_ksettings_add_link_mode(ks, advertising,265 Autoneg);266 ks->base.autoneg = AUTONEG_ENABLE;267 }268 }269 270 return 0;271}272 273static int ionic_set_link_ksettings(struct net_device *netdev,274 const struct ethtool_link_ksettings *ks)275{276 struct ionic_lif *lif = netdev_priv(netdev);277 struct ionic_dev *idev = &lif->ionic->idev;278 struct ionic *ionic = lif->ionic;279 int err = 0;280 281 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))282 return -EBUSY;283 284 /* set autoneg */285 if (ks->base.autoneg != idev->port_info->config.an_enable) {286 mutex_lock(&ionic->dev_cmd_lock);287 ionic_dev_cmd_port_autoneg(idev, ks->base.autoneg);288 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);289 mutex_unlock(&ionic->dev_cmd_lock);290 if (err)291 return err;292 }293 294 /* set speed */295 if (ks->base.speed != le32_to_cpu(idev->port_info->config.speed)) {296 mutex_lock(&ionic->dev_cmd_lock);297 ionic_dev_cmd_port_speed(idev, ks->base.speed);298 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);299 mutex_unlock(&ionic->dev_cmd_lock);300 if (err)301 return err;302 }303 304 return 0;305}306 307static void ionic_get_pauseparam(struct net_device *netdev,308 struct ethtool_pauseparam *pause)309{310 struct ionic_lif *lif = netdev_priv(netdev);311 u8 pause_type;312 313 pause->autoneg = 0;314 315 pause_type = lif->ionic->idev.port_info->config.pause_type;316 if (pause_type) {317 pause->rx_pause = (pause_type & IONIC_PAUSE_F_RX) ? 1 : 0;318 pause->tx_pause = (pause_type & IONIC_PAUSE_F_TX) ? 1 : 0;319 }320}321 322static int ionic_set_pauseparam(struct net_device *netdev,323 struct ethtool_pauseparam *pause)324{325 struct ionic_lif *lif = netdev_priv(netdev);326 struct ionic *ionic = lif->ionic;327 u32 requested_pause;328 int err;329 330 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))331 return -EBUSY;332 333 if (pause->autoneg)334 return -EOPNOTSUPP;335 336 /* change both at the same time */337 requested_pause = IONIC_PORT_PAUSE_TYPE_LINK;338 if (pause->rx_pause)339 requested_pause |= IONIC_PAUSE_F_RX;340 if (pause->tx_pause)341 requested_pause |= IONIC_PAUSE_F_TX;342 343 if (requested_pause == lif->ionic->idev.port_info->config.pause_type)344 return 0;345 346 mutex_lock(&ionic->dev_cmd_lock);347 ionic_dev_cmd_port_pause(&lif->ionic->idev, requested_pause);348 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);349 mutex_unlock(&ionic->dev_cmd_lock);350 if (err)351 return err;352 353 return 0;354}355 356static int ionic_get_fecparam(struct net_device *netdev,357 struct ethtool_fecparam *fec)358{359 struct ionic_lif *lif = netdev_priv(netdev);360 361 switch (lif->ionic->idev.port_info->config.fec_type) {362 case IONIC_PORT_FEC_TYPE_NONE:363 fec->active_fec = ETHTOOL_FEC_OFF;364 break;365 case IONIC_PORT_FEC_TYPE_RS:366 fec->active_fec = ETHTOOL_FEC_RS;367 break;368 case IONIC_PORT_FEC_TYPE_FC:369 fec->active_fec = ETHTOOL_FEC_BASER;370 break;371 }372 373 fec->fec = ETHTOOL_FEC_OFF | ETHTOOL_FEC_RS | ETHTOOL_FEC_BASER;374 375 return 0;376}377 378static int ionic_set_fecparam(struct net_device *netdev,379 struct ethtool_fecparam *fec)380{381 struct ionic_lif *lif = netdev_priv(netdev);382 u8 fec_type;383 int ret = 0;384 385 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))386 return -EBUSY;387 388 if (lif->ionic->idev.port_info->config.an_enable) {389 netdev_err(netdev, "FEC request not allowed while autoneg is enabled\n");390 return -EINVAL;391 }392 393 switch (fec->fec) {394 case ETHTOOL_FEC_NONE:395 fec_type = IONIC_PORT_FEC_TYPE_NONE;396 break;397 case ETHTOOL_FEC_OFF:398 fec_type = IONIC_PORT_FEC_TYPE_NONE;399 break;400 case ETHTOOL_FEC_RS:401 fec_type = IONIC_PORT_FEC_TYPE_RS;402 break;403 case ETHTOOL_FEC_BASER:404 fec_type = IONIC_PORT_FEC_TYPE_FC;405 break;406 case ETHTOOL_FEC_AUTO:407 default:408 netdev_err(netdev, "FEC request 0x%04x not supported\n",409 fec->fec);410 return -EINVAL;411 }412 413 if (fec_type != lif->ionic->idev.port_info->config.fec_type) {414 mutex_lock(&lif->ionic->dev_cmd_lock);415 ionic_dev_cmd_port_fec(&lif->ionic->idev, fec_type);416 ret = ionic_dev_cmd_wait(lif->ionic, DEVCMD_TIMEOUT);417 mutex_unlock(&lif->ionic->dev_cmd_lock);418 }419 420 return ret;421}422 423static int ionic_get_coalesce(struct net_device *netdev,424 struct ethtool_coalesce *coalesce,425 struct kernel_ethtool_coalesce *kernel_coal,426 struct netlink_ext_ack *extack)427{428 struct ionic_lif *lif = netdev_priv(netdev);429 430 coalesce->tx_coalesce_usecs = lif->tx_coalesce_usecs;431 coalesce->rx_coalesce_usecs = lif->rx_coalesce_usecs;432 433 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))434 coalesce->use_adaptive_tx_coalesce = test_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);435 else436 coalesce->use_adaptive_tx_coalesce = 0;437 438 coalesce->use_adaptive_rx_coalesce = test_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);439 440 return 0;441}442 443static int ionic_set_coalesce(struct net_device *netdev,444 struct ethtool_coalesce *coalesce,445 struct kernel_ethtool_coalesce *kernel_coal,446 struct netlink_ext_ack *extack)447{448 struct ionic_lif *lif = netdev_priv(netdev);449 struct ionic_identity *ident;450 u32 rx_coal, rx_dim;451 u32 tx_coal, tx_dim;452 unsigned int i;453 454 ident = &lif->ionic->ident;455 if (ident->dev.intr_coal_div == 0) {456 netdev_warn(netdev, "bad HW value in dev.intr_coal_div = %d\n",457 ident->dev.intr_coal_div);458 return -EIO;459 }460 461 /* Tx normally shares Rx interrupt, so only change Rx if not split */462 if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state) &&463 (coalesce->tx_coalesce_usecs != lif->rx_coalesce_usecs ||464 coalesce->use_adaptive_tx_coalesce)) {465 netdev_warn(netdev, "only rx parameters can be changed\n");466 return -EINVAL;467 }468 469 /* Convert the usec request to a HW usable value. If they asked470 * for non-zero and it resolved to zero, bump it up471 */472 rx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->rx_coalesce_usecs);473 if (!rx_coal && coalesce->rx_coalesce_usecs)474 rx_coal = 1;475 tx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->tx_coalesce_usecs);476 if (!tx_coal && coalesce->tx_coalesce_usecs)477 tx_coal = 1;478 479 if (rx_coal > IONIC_INTR_CTRL_COAL_MAX ||480 tx_coal > IONIC_INTR_CTRL_COAL_MAX)481 return -ERANGE;482 483 /* Save the new values */484 lif->rx_coalesce_usecs = coalesce->rx_coalesce_usecs;485 lif->rx_coalesce_hw = rx_coal;486 487 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))488 lif->tx_coalesce_usecs = coalesce->tx_coalesce_usecs;489 else490 lif->tx_coalesce_usecs = coalesce->rx_coalesce_usecs;491 lif->tx_coalesce_hw = tx_coal;492 493 if (coalesce->use_adaptive_rx_coalesce) {494 set_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);495 rx_dim = rx_coal;496 } else {497 clear_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);498 rx_dim = 0;499 }500 501 if (coalesce->use_adaptive_tx_coalesce) {502 set_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);503 tx_dim = tx_coal;504 } else {505 clear_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);506 tx_dim = 0;507 }508 509 if (test_bit(IONIC_LIF_F_UP, lif->state)) {510 for (i = 0; i < lif->nxqs; i++) {511 if (lif->rxqcqs[i]->flags & IONIC_QCQ_F_INTR) {512 ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,513 lif->rxqcqs[i]->intr.index,514 lif->rx_coalesce_hw);515 lif->rxqcqs[i]->intr.dim_coal_hw = rx_dim;516 }517 518 if (lif->txqcqs[i]->flags & IONIC_QCQ_F_INTR) {519 ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,520 lif->txqcqs[i]->intr.index,521 lif->tx_coalesce_hw);522 lif->txqcqs[i]->intr.dim_coal_hw = tx_dim;523 }524 }525 }526 527 return 0;528}529 530static int ionic_validate_cmb_config(struct ionic_lif *lif,531 struct ionic_queue_params *qparam)532{533 int pages_have, pages_required = 0;534 unsigned long sz;535 536 if (!lif->ionic->idev.cmb_inuse &&537 (qparam->cmb_tx || qparam->cmb_rx)) {538 netdev_info(lif->netdev, "CMB rings are not supported on this device\n");539 return -EOPNOTSUPP;540 }541 542 if (qparam->cmb_tx) {543 if (!(lif->qtype_info[IONIC_QTYPE_TXQ].features & IONIC_QIDENT_F_CMB)) {544 netdev_info(lif->netdev,545 "CMB rings for tx-push are not supported on this device\n");546 return -EOPNOTSUPP;547 }548 549 sz = sizeof(struct ionic_txq_desc) * qparam->ntxq_descs * qparam->nxqs;550 pages_required += ALIGN(sz, PAGE_SIZE) / PAGE_SIZE;551 }552 553 if (qparam->cmb_rx) {554 if (!(lif->qtype_info[IONIC_QTYPE_RXQ].features & IONIC_QIDENT_F_CMB)) {555 netdev_info(lif->netdev,556 "CMB rings for rx-push are not supported on this device\n");557 return -EOPNOTSUPP;558 }559 560 sz = sizeof(struct ionic_rxq_desc) * qparam->nrxq_descs * qparam->nxqs;561 pages_required += ALIGN(sz, PAGE_SIZE) / PAGE_SIZE;562 }563 564 pages_have = lif->ionic->bars[IONIC_PCI_BAR_CMB].len / PAGE_SIZE;565 if (pages_required > pages_have) {566 netdev_info(lif->netdev,567 "Not enough CMB pages for number of queues and size of descriptor rings, need %d have %d",568 pages_required, pages_have);569 return -ENOMEM;570 }571 572 return pages_required;573}574 575static int ionic_cmb_rings_toggle(struct ionic_lif *lif, bool cmb_tx, bool cmb_rx)576{577 struct ionic_queue_params qparam;578 int pages_used;579 580 if (netif_running(lif->netdev)) {581 netdev_info(lif->netdev, "Please stop device to toggle CMB for tx/rx-push\n");582 return -EBUSY;583 }584 585 ionic_init_queue_params(lif, &qparam);586 qparam.cmb_tx = cmb_tx;587 qparam.cmb_rx = cmb_rx;588 pages_used = ionic_validate_cmb_config(lif, &qparam);589 if (pages_used < 0)590 return pages_used;591 592 if (cmb_tx)593 set_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);594 else595 clear_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);596 597 if (cmb_rx)598 set_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);599 else600 clear_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);601 602 if (cmb_tx || cmb_rx)603 netdev_info(lif->netdev, "Enabling CMB %s %s rings - %d pages\n",604 cmb_tx ? "TX" : "", cmb_rx ? "RX" : "", pages_used);605 else606 netdev_info(lif->netdev, "Disabling CMB rings\n");607 608 return 0;609}610 611static void ionic_get_ringparam(struct net_device *netdev,612 struct ethtool_ringparam *ring,613 struct kernel_ethtool_ringparam *kernel_ring,614 struct netlink_ext_ack *extack)615{616 struct ionic_lif *lif = netdev_priv(netdev);617 618 ring->tx_max_pending = IONIC_MAX_TX_DESC;619 ring->tx_pending = lif->ntxq_descs;620 ring->rx_max_pending = IONIC_MAX_RX_DESC;621 ring->rx_pending = lif->nrxq_descs;622 kernel_ring->tx_push = test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);623 kernel_ring->rx_push = test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);624}625 626static int ionic_set_ringparam(struct net_device *netdev,627 struct ethtool_ringparam *ring,628 struct kernel_ethtool_ringparam *kernel_ring,629 struct netlink_ext_ack *extack)630{631 struct ionic_lif *lif = netdev_priv(netdev);632 struct ionic_queue_params qparam;633 int err;634 635 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))636 return -EBUSY;637 638 ionic_init_queue_params(lif, &qparam);639 640 if (ring->rx_mini_pending || ring->rx_jumbo_pending) {641 netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n");642 return -EINVAL;643 }644 645 if (!is_power_of_2(ring->tx_pending) ||646 !is_power_of_2(ring->rx_pending)) {647 netdev_info(netdev, "Descriptor count must be a power of 2\n");648 return -EINVAL;649 }650 651 /* if nothing to do return success */652 if (ring->tx_pending == lif->ntxq_descs &&653 ring->rx_pending == lif->nrxq_descs &&654 kernel_ring->tx_push == test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state) &&655 kernel_ring->rx_push == test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state))656 return 0;657 658 qparam.ntxq_descs = ring->tx_pending;659 qparam.nrxq_descs = ring->rx_pending;660 qparam.cmb_tx = kernel_ring->tx_push;661 qparam.cmb_rx = kernel_ring->rx_push;662 663 err = ionic_validate_cmb_config(lif, &qparam);664 if (err < 0)665 return err;666 667 if (kernel_ring->tx_push != test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state) ||668 kernel_ring->rx_push != test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state)) {669 err = ionic_cmb_rings_toggle(lif, kernel_ring->tx_push,670 kernel_ring->rx_push);671 if (err < 0)672 return err;673 }674 675 if (ring->tx_pending != lif->ntxq_descs)676 netdev_info(netdev, "Changing Tx ring size from %d to %d\n",677 lif->ntxq_descs, ring->tx_pending);678 679 if (ring->rx_pending != lif->nrxq_descs)680 netdev_info(netdev, "Changing Rx ring size from %d to %d\n",681 lif->nrxq_descs, ring->rx_pending);682 683 /* if we're not running, just set the values and return */684 if (!netif_running(lif->netdev)) {685 lif->ntxq_descs = ring->tx_pending;686 lif->nrxq_descs = ring->rx_pending;687 return 0;688 }689 690 mutex_lock(&lif->queue_lock);691 err = ionic_reconfigure_queues(lif, &qparam);692 mutex_unlock(&lif->queue_lock);693 if (err)694 netdev_info(netdev, "Ring reconfiguration failed, changes canceled: %d\n", err);695 696 return err;697}698 699static void ionic_get_channels(struct net_device *netdev,700 struct ethtool_channels *ch)701{702 struct ionic_lif *lif = netdev_priv(netdev);703 704 /* report maximum channels */705 ch->max_combined = lif->ionic->ntxqs_per_lif;706 ch->max_rx = lif->ionic->ntxqs_per_lif / 2;707 ch->max_tx = lif->ionic->ntxqs_per_lif / 2;708 709 /* report current channels */710 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {711 ch->rx_count = lif->nxqs;712 ch->tx_count = lif->nxqs;713 } else {714 ch->combined_count = lif->nxqs;715 }716}717 718static int ionic_set_channels(struct net_device *netdev,719 struct ethtool_channels *ch)720{721 struct ionic_lif *lif = netdev_priv(netdev);722 struct ionic_queue_params qparam;723 int max_cnt;724 int err;725 726 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))727 return -EBUSY;728 729 ionic_init_queue_params(lif, &qparam);730 731 if ((ch->rx_count || ch->tx_count) && lif->xdp_prog) {732 netdev_info(lif->netdev, "Split Tx/Rx interrupts not available when using XDP\n");733 return -EOPNOTSUPP;734 }735 736 if (ch->rx_count != ch->tx_count) {737 netdev_info(netdev, "The rx and tx count must be equal\n");738 return -EINVAL;739 }740 741 if (ch->combined_count && ch->rx_count) {742 netdev_info(netdev, "Use either combined or rx and tx, not both\n");743 return -EINVAL;744 }745 746 max_cnt = lif->ionic->ntxqs_per_lif;747 if (ch->combined_count) {748 if (ch->combined_count > max_cnt)749 return -EINVAL;750 751 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))752 netdev_info(lif->netdev, "Sharing queue interrupts\n");753 else if (ch->combined_count == lif->nxqs)754 return 0;755 756 if (lif->nxqs != ch->combined_count)757 netdev_info(netdev, "Changing queue count from %d to %d\n",758 lif->nxqs, ch->combined_count);759 760 qparam.nxqs = ch->combined_count;761 qparam.intr_split = false;762 } else {763 max_cnt /= 2;764 if (ch->rx_count > max_cnt)765 return -EINVAL;766 767 if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))768 netdev_info(lif->netdev, "Splitting queue interrupts\n");769 else if (ch->rx_count == lif->nxqs)770 return 0;771 772 if (lif->nxqs != ch->rx_count)773 netdev_info(netdev, "Changing queue count from %d to %d\n",774 lif->nxqs, ch->rx_count);775 776 qparam.nxqs = ch->rx_count;777 qparam.intr_split = true;778 }779 780 err = ionic_validate_cmb_config(lif, &qparam);781 if (err < 0)782 return err;783 784 /* if we're not running, just set the values and return */785 if (!netif_running(lif->netdev)) {786 lif->nxqs = qparam.nxqs;787 788 if (qparam.intr_split) {789 set_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);790 } else {791 clear_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);792 lif->tx_coalesce_usecs = lif->rx_coalesce_usecs;793 lif->tx_coalesce_hw = lif->rx_coalesce_hw;794 }795 return 0;796 }797 798 mutex_lock(&lif->queue_lock);799 err = ionic_reconfigure_queues(lif, &qparam);800 mutex_unlock(&lif->queue_lock);801 if (err)802 netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err);803 804 return err;805}806 807static int ionic_get_rxnfc(struct net_device *netdev,808 struct ethtool_rxnfc *info, u32 *rules)809{810 struct ionic_lif *lif = netdev_priv(netdev);811 int err = 0;812 813 switch (info->cmd) {814 case ETHTOOL_GRXRINGS:815 info->data = lif->nxqs;816 break;817 default:818 netdev_dbg(netdev, "Command parameter %d is not supported\n",819 info->cmd);820 err = -EOPNOTSUPP;821 }822 823 return err;824}825 826static u32 ionic_get_rxfh_indir_size(struct net_device *netdev)827{828 struct ionic_lif *lif = netdev_priv(netdev);829 830 return le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);831}832 833static u32 ionic_get_rxfh_key_size(struct net_device *netdev)834{835 return IONIC_RSS_HASH_KEY_SIZE;836}837 838static int ionic_get_rxfh(struct net_device *netdev,839 struct ethtool_rxfh_param *rxfh)840{841 struct ionic_lif *lif = netdev_priv(netdev);842 unsigned int i, tbl_sz;843 844 if (rxfh->indir) {845 tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);846 for (i = 0; i < tbl_sz; i++)847 rxfh->indir[i] = lif->rss_ind_tbl[i];848 }849 850 if (rxfh->key)851 memcpy(rxfh->key, lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);852 853 rxfh->hfunc = ETH_RSS_HASH_TOP;854 855 return 0;856}857 858static int ionic_set_rxfh(struct net_device *netdev,859 struct ethtool_rxfh_param *rxfh,860 struct netlink_ext_ack *extack)861{862 struct ionic_lif *lif = netdev_priv(netdev);863 864 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&865 rxfh->hfunc != ETH_RSS_HASH_TOP)866 return -EOPNOTSUPP;867 868 return ionic_lif_rss_config(lif, lif->rss_types,869 rxfh->key, rxfh->indir);870}871 872static int ionic_set_tunable(struct net_device *dev,873 const struct ethtool_tunable *tuna,874 const void *data)875{876 struct ionic_lif *lif = netdev_priv(dev);877 u32 rx_copybreak;878 879 switch (tuna->id) {880 case ETHTOOL_RX_COPYBREAK:881 rx_copybreak = *(u32 *)data;882 if (rx_copybreak > IONIC_MAX_RX_COPYBREAK) {883 netdev_err(dev, "Max supported rx_copybreak size: %u\n",884 IONIC_MAX_RX_COPYBREAK);885 return -EINVAL;886 }887 lif->rx_copybreak = (u16)rx_copybreak;888 break;889 default:890 return -EOPNOTSUPP;891 }892 893 return 0;894}895 896static int ionic_get_tunable(struct net_device *netdev,897 const struct ethtool_tunable *tuna, void *data)898{899 struct ionic_lif *lif = netdev_priv(netdev);900 901 switch (tuna->id) {902 case ETHTOOL_RX_COPYBREAK:903 *(u32 *)data = lif->rx_copybreak;904 break;905 default:906 return -EOPNOTSUPP;907 }908 909 return 0;910}911 912static int ionic_get_module_info(struct net_device *netdev,913 struct ethtool_modinfo *modinfo)914 915{916 struct ionic_lif *lif = netdev_priv(netdev);917 struct ionic_dev *idev = &lif->ionic->idev;918 struct ionic_xcvr_status *xcvr;919 struct sfp_eeprom_base *sfp;920 921 xcvr = &idev->port_info->status.xcvr;922 sfp = (struct sfp_eeprom_base *) xcvr->sprom;923 924 /* report the module data type and length */925 switch (sfp->phys_id) {926 case SFF8024_ID_SFP:927 modinfo->type = ETH_MODULE_SFF_8079;928 modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;929 break;930 case SFF8024_ID_QSFP_8436_8636:931 case SFF8024_ID_QSFP28_8636:932 modinfo->type = ETH_MODULE_SFF_8436;933 modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;934 break;935 default:936 netdev_info(netdev, "unknown xcvr type 0x%02x\n",937 xcvr->sprom[0]);938 modinfo->type = 0;939 modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;940 break;941 }942 943 return 0;944}945 946static int ionic_get_module_eeprom(struct net_device *netdev,947 struct ethtool_eeprom *ee,948 u8 *data)949{950 struct ionic_lif *lif = netdev_priv(netdev);951 struct ionic_dev *idev = &lif->ionic->idev;952 struct ionic_xcvr_status *xcvr;953 char tbuf[sizeof(xcvr->sprom)];954 int count = 10;955 u32 len;956 957 /* The NIC keeps the module prom up-to-date in the DMA space958 * so we can simply copy the module bytes into the data buffer.959 */960 xcvr = &idev->port_info->status.xcvr;961 len = min_t(u32, sizeof(xcvr->sprom), ee->len);962 963 do {964 memcpy(data, xcvr->sprom, len);965 memcpy(tbuf, xcvr->sprom, len);966 967 /* Let's make sure we got a consistent copy */968 if (!memcmp(data, tbuf, len))969 break;970 971 } while (--count);972 973 if (!count)974 return -ETIMEDOUT;975 976 return 0;977}978 979static int ionic_get_ts_info(struct net_device *netdev,980 struct kernel_ethtool_ts_info *info)981{982 struct ionic_lif *lif = netdev_priv(netdev);983 struct ionic *ionic = lif->ionic;984 __le64 mask;985 986 if (!lif->phc || !lif->phc->ptp)987 return ethtool_op_get_ts_info(netdev, info);988 989 info->phc_index = ptp_clock_index(lif->phc->ptp);990 991 info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |992 SOF_TIMESTAMPING_TX_HARDWARE |993 SOF_TIMESTAMPING_RX_HARDWARE |994 SOF_TIMESTAMPING_RAW_HARDWARE;995 996 /* tx modes */997 998 info->tx_types = BIT(HWTSTAMP_TX_OFF) |999 BIT(HWTSTAMP_TX_ON);1000 1001 mask = cpu_to_le64(BIT_ULL(IONIC_TXSTAMP_ONESTEP_SYNC));1002 if (ionic->ident.lif.eth.hwstamp_tx_modes & mask)1003 info->tx_types |= BIT(HWTSTAMP_TX_ONESTEP_SYNC);1004 1005 mask = cpu_to_le64(BIT_ULL(IONIC_TXSTAMP_ONESTEP_P2P));1006 if (ionic->ident.lif.eth.hwstamp_tx_modes & mask)1007 info->tx_types |= BIT(HWTSTAMP_TX_ONESTEP_P2P);1008 1009 /* rx filters */1010 1011 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |1012 BIT(HWTSTAMP_FILTER_ALL);1013 1014 mask = cpu_to_le64(IONIC_PKT_CLS_NTP_ALL);1015 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1016 info->rx_filters |= BIT(HWTSTAMP_FILTER_NTP_ALL);1017 1018 mask = cpu_to_le64(IONIC_PKT_CLS_PTP1_SYNC);1019 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1020 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC);1021 1022 mask = cpu_to_le64(IONIC_PKT_CLS_PTP1_DREQ);1023 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1024 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ);1025 1026 mask = cpu_to_le64(IONIC_PKT_CLS_PTP1_ALL);1027 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1028 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT);1029 1030 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L4_SYNC);1031 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1032 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC);1033 1034 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L4_DREQ);1035 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1036 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);1037 1038 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L4_ALL);1039 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1040 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT);1041 1042 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L2_SYNC);1043 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1044 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC);1045 1046 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L2_DREQ);1047 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1048 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);1049 1050 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_L2_ALL);1051 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1052 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT);1053 1054 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_SYNC);1055 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1056 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_SYNC);1057 1058 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_DREQ);1059 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1060 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);1061 1062 mask = cpu_to_le64(IONIC_PKT_CLS_PTP2_ALL);1063 if ((ionic->ident.lif.eth.hwstamp_rx_filters & mask) == mask)1064 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);1065 1066 return 0;1067}1068 1069static int ionic_nway_reset(struct net_device *netdev)1070{1071 struct ionic_lif *lif = netdev_priv(netdev);1072 struct ionic *ionic = lif->ionic;1073 int err = 0;1074 1075 if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))1076 return -EBUSY;1077 1078 /* flap the link to force auto-negotiation */1079 1080 mutex_lock(&ionic->dev_cmd_lock);1081 1082 ionic_dev_cmd_port_state(&ionic->idev, IONIC_PORT_ADMIN_STATE_DOWN);1083 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);1084 1085 if (!err) {1086 ionic_dev_cmd_port_state(&ionic->idev, IONIC_PORT_ADMIN_STATE_UP);1087 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);1088 }1089 1090 mutex_unlock(&ionic->dev_cmd_lock);1091 1092 return err;1093}1094 1095static const struct ethtool_ops ionic_ethtool_ops = {1096 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |1097 ETHTOOL_COALESCE_USE_ADAPTIVE_RX |1098 ETHTOOL_COALESCE_USE_ADAPTIVE_TX,1099 .supported_ring_params = ETHTOOL_RING_USE_TX_PUSH |1100 ETHTOOL_RING_USE_RX_PUSH,1101 .get_drvinfo = ionic_get_drvinfo,1102 .get_regs_len = ionic_get_regs_len,1103 .get_regs = ionic_get_regs,1104 .get_link = ethtool_op_get_link,1105 .get_link_ext_stats = ionic_get_link_ext_stats,1106 .get_link_ksettings = ionic_get_link_ksettings,1107 .set_link_ksettings = ionic_set_link_ksettings,1108 .get_coalesce = ionic_get_coalesce,1109 .set_coalesce = ionic_set_coalesce,1110 .get_ringparam = ionic_get_ringparam,1111 .set_ringparam = ionic_set_ringparam,1112 .get_channels = ionic_get_channels,1113 .set_channels = ionic_set_channels,1114 .get_strings = ionic_get_strings,1115 .get_ethtool_stats = ionic_get_stats,1116 .get_sset_count = ionic_get_sset_count,1117 .get_rxnfc = ionic_get_rxnfc,1118 .get_rxfh_indir_size = ionic_get_rxfh_indir_size,1119 .get_rxfh_key_size = ionic_get_rxfh_key_size,1120 .get_rxfh = ionic_get_rxfh,1121 .set_rxfh = ionic_set_rxfh,1122 .get_tunable = ionic_get_tunable,1123 .set_tunable = ionic_set_tunable,1124 .get_module_info = ionic_get_module_info,1125 .get_module_eeprom = ionic_get_module_eeprom,1126 .get_pauseparam = ionic_get_pauseparam,1127 .set_pauseparam = ionic_set_pauseparam,1128 .get_fecparam = ionic_get_fecparam,1129 .set_fecparam = ionic_set_fecparam,1130 .get_ts_info = ionic_get_ts_info,1131 .nway_reset = ionic_nway_reset,1132};1133 1134void ionic_ethtool_set_ops(struct net_device *netdev)1135{1136 netdev->ethtool_ops = &ionic_ethtool_ops;1137}1138