1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
4 #include <linux/module.h>
5 #include <linux/netdevice.h>
10 #include "ionic_lif.h"
11 #include "ionic_ethtool.h"
12 #include "ionic_stats.h"
14 static const char ionic_priv_flags_strings[][ETH_GSTRING_LEN] = {
15 #define IONIC_PRIV_F_SW_DBG_STATS BIT(0)
19 #define IONIC_PRIV_FLAGS_COUNT ARRAY_SIZE(ionic_priv_flags_strings)
21 static void ionic_get_stats_strings(struct ionic_lif *lif, u8 *buf)
25 for (i = 0; i < ionic_num_stats_grps; i++)
26 ionic_stats_groups[i].get_strings(lif, &buf);
29 static void ionic_get_stats(struct net_device *netdev,
30 struct ethtool_stats *stats, u64 *buf)
32 struct ionic_lif *lif;
35 lif = netdev_priv(netdev);
37 memset(buf, 0, stats->n_stats * sizeof(*buf));
38 for (i = 0; i < ionic_num_stats_grps; i++)
39 ionic_stats_groups[i].get_values(lif, &buf);
42 static int ionic_get_stats_count(struct ionic_lif *lif)
46 for (i = 0; i < ionic_num_stats_grps; i++)
47 num_stats += ionic_stats_groups[i].get_count(lif);
52 static int ionic_get_sset_count(struct net_device *netdev, int sset)
54 struct ionic_lif *lif = netdev_priv(netdev);
59 count = ionic_get_stats_count(lif);
61 case ETH_SS_PRIV_FLAGS:
62 count = IONIC_PRIV_FLAGS_COUNT;
68 static void ionic_get_strings(struct net_device *netdev,
71 struct ionic_lif *lif = netdev_priv(netdev);
75 ionic_get_stats_strings(lif, buf);
77 case ETH_SS_PRIV_FLAGS:
78 memcpy(buf, ionic_priv_flags_strings,
79 IONIC_PRIV_FLAGS_COUNT * ETH_GSTRING_LEN);
84 static void ionic_get_drvinfo(struct net_device *netdev,
85 struct ethtool_drvinfo *drvinfo)
87 struct ionic_lif *lif = netdev_priv(netdev);
88 struct ionic *ionic = lif->ionic;
90 strlcpy(drvinfo->driver, IONIC_DRV_NAME, sizeof(drvinfo->driver));
91 strlcpy(drvinfo->fw_version, ionic->idev.dev_info.fw_version,
92 sizeof(drvinfo->fw_version));
93 strlcpy(drvinfo->bus_info, ionic_bus_info(ionic),
94 sizeof(drvinfo->bus_info));
97 static int ionic_get_regs_len(struct net_device *netdev)
99 return (IONIC_DEV_INFO_REG_COUNT + IONIC_DEV_CMD_REG_COUNT) * sizeof(u32);
102 static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
105 struct ionic_lif *lif = netdev_priv(netdev);
109 regs->version = IONIC_DEV_CMD_REG_VERSION;
112 size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
113 memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);
116 size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
117 memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
120 static int ionic_get_link_ksettings(struct net_device *netdev,
121 struct ethtool_link_ksettings *ks)
123 struct ionic_lif *lif = netdev_priv(netdev);
124 struct ionic_dev *idev = &lif->ionic->idev;
127 ethtool_link_ksettings_zero_link_mode(ks, supported);
129 if (!idev->port_info) {
130 netdev_err(netdev, "port_info not initialized\n");
134 /* The port_info data is found in a DMA space that the NIC keeps
135 * up-to-date, so there's no need to request the data from the
136 * NIC, we already have it in our memory space.
139 switch (le16_to_cpu(idev->port_info->status.xcvr.pid)) {
141 case IONIC_XCVR_PID_QSFP_100G_CR4:
142 ethtool_link_ksettings_add_link_mode(ks, supported,
146 case IONIC_XCVR_PID_QSFP_40GBASE_CR4:
147 ethtool_link_ksettings_add_link_mode(ks, supported,
151 case IONIC_XCVR_PID_SFP_25GBASE_CR_S:
152 case IONIC_XCVR_PID_SFP_25GBASE_CR_L:
153 case IONIC_XCVR_PID_SFP_25GBASE_CR_N:
154 ethtool_link_ksettings_add_link_mode(ks, supported,
158 case IONIC_XCVR_PID_SFP_10GBASE_AOC:
159 case IONIC_XCVR_PID_SFP_10GBASE_CU:
160 ethtool_link_ksettings_add_link_mode(ks, supported,
166 case IONIC_XCVR_PID_QSFP_100G_SR4:
167 case IONIC_XCVR_PID_QSFP_100G_AOC:
168 ethtool_link_ksettings_add_link_mode(ks, supported,
171 case IONIC_XCVR_PID_QSFP_100G_CWDM4:
172 case IONIC_XCVR_PID_QSFP_100G_PSM4:
173 case IONIC_XCVR_PID_QSFP_100G_LR4:
174 ethtool_link_ksettings_add_link_mode(ks, supported,
175 100000baseLR4_ER4_Full);
177 case IONIC_XCVR_PID_QSFP_100G_ER4:
178 ethtool_link_ksettings_add_link_mode(ks, supported,
179 100000baseLR4_ER4_Full);
181 case IONIC_XCVR_PID_QSFP_40GBASE_SR4:
182 case IONIC_XCVR_PID_QSFP_40GBASE_AOC:
183 ethtool_link_ksettings_add_link_mode(ks, supported,
186 case IONIC_XCVR_PID_QSFP_40GBASE_LR4:
187 ethtool_link_ksettings_add_link_mode(ks, supported,
190 case IONIC_XCVR_PID_SFP_25GBASE_SR:
191 case IONIC_XCVR_PID_SFP_25GBASE_AOC:
192 case IONIC_XCVR_PID_SFP_25GBASE_ACC:
193 ethtool_link_ksettings_add_link_mode(ks, supported,
196 case IONIC_XCVR_PID_SFP_10GBASE_SR:
197 ethtool_link_ksettings_add_link_mode(ks, supported,
200 case IONIC_XCVR_PID_SFP_10GBASE_LR:
201 ethtool_link_ksettings_add_link_mode(ks, supported,
204 case IONIC_XCVR_PID_SFP_10GBASE_LRM:
205 ethtool_link_ksettings_add_link_mode(ks, supported,
208 case IONIC_XCVR_PID_SFP_10GBASE_ER:
209 ethtool_link_ksettings_add_link_mode(ks, supported,
212 case IONIC_XCVR_PID_UNKNOWN:
213 /* This means there's no module plugged in */
216 dev_info(lif->ionic->dev, "unknown xcvr type pid=%d / 0x%x\n",
217 idev->port_info->status.xcvr.pid,
218 idev->port_info->status.xcvr.pid);
222 bitmap_copy(ks->link_modes.advertising, ks->link_modes.supported,
223 __ETHTOOL_LINK_MODE_MASK_NBITS);
225 ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
226 ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
227 if (idev->port_info->config.fec_type == IONIC_PORT_FEC_TYPE_FC)
228 ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_BASER);
229 else if (idev->port_info->config.fec_type == IONIC_PORT_FEC_TYPE_RS)
230 ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
232 ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE);
233 ethtool_link_ksettings_add_link_mode(ks, supported, Pause);
235 if (idev->port_info->status.xcvr.phy == IONIC_PHY_TYPE_COPPER ||
237 ks->base.port = PORT_DA;
238 else if (idev->port_info->status.xcvr.phy == IONIC_PHY_TYPE_FIBER)
239 ks->base.port = PORT_FIBRE;
241 ks->base.port = PORT_NONE;
243 if (ks->base.port != PORT_NONE) {
244 ks->base.speed = le32_to_cpu(lif->info->status.link_speed);
246 if (le16_to_cpu(lif->info->status.link_status))
247 ks->base.duplex = DUPLEX_FULL;
249 ks->base.duplex = DUPLEX_UNKNOWN;
251 ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
253 if (idev->port_info->config.an_enable) {
254 ethtool_link_ksettings_add_link_mode(ks, advertising,
256 ks->base.autoneg = AUTONEG_ENABLE;
263 static int ionic_set_link_ksettings(struct net_device *netdev,
264 const struct ethtool_link_ksettings *ks)
266 struct ionic_lif *lif = netdev_priv(netdev);
267 struct ionic *ionic = lif->ionic;
268 struct ionic_dev *idev;
271 idev = &lif->ionic->idev;
274 if (ks->base.autoneg != idev->port_info->config.an_enable) {
275 mutex_lock(&ionic->dev_cmd_lock);
276 ionic_dev_cmd_port_autoneg(idev, ks->base.autoneg);
277 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
278 mutex_unlock(&ionic->dev_cmd_lock);
284 if (ks->base.speed != le32_to_cpu(idev->port_info->config.speed)) {
285 mutex_lock(&ionic->dev_cmd_lock);
286 ionic_dev_cmd_port_speed(idev, ks->base.speed);
287 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
288 mutex_unlock(&ionic->dev_cmd_lock);
296 static void ionic_get_pauseparam(struct net_device *netdev,
297 struct ethtool_pauseparam *pause)
299 struct ionic_lif *lif = netdev_priv(netdev);
304 pause_type = lif->ionic->idev.port_info->config.pause_type;
306 pause->rx_pause = (pause_type & IONIC_PAUSE_F_RX) ? 1 : 0;
307 pause->tx_pause = (pause_type & IONIC_PAUSE_F_TX) ? 1 : 0;
311 static int ionic_set_pauseparam(struct net_device *netdev,
312 struct ethtool_pauseparam *pause)
314 struct ionic_lif *lif = netdev_priv(netdev);
315 struct ionic *ionic = lif->ionic;
322 /* change both at the same time */
323 requested_pause = IONIC_PORT_PAUSE_TYPE_LINK;
325 requested_pause |= IONIC_PAUSE_F_RX;
327 requested_pause |= IONIC_PAUSE_F_TX;
329 if (requested_pause == lif->ionic->idev.port_info->config.pause_type)
332 mutex_lock(&ionic->dev_cmd_lock);
333 ionic_dev_cmd_port_pause(&lif->ionic->idev, requested_pause);
334 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
335 mutex_unlock(&ionic->dev_cmd_lock);
342 static int ionic_get_fecparam(struct net_device *netdev,
343 struct ethtool_fecparam *fec)
345 struct ionic_lif *lif = netdev_priv(netdev);
347 switch (lif->ionic->idev.port_info->config.fec_type) {
348 case IONIC_PORT_FEC_TYPE_NONE:
349 fec->active_fec = ETHTOOL_FEC_OFF;
351 case IONIC_PORT_FEC_TYPE_RS:
352 fec->active_fec = ETHTOOL_FEC_RS;
354 case IONIC_PORT_FEC_TYPE_FC:
355 fec->active_fec = ETHTOOL_FEC_BASER;
359 fec->fec = ETHTOOL_FEC_OFF | ETHTOOL_FEC_RS | ETHTOOL_FEC_BASER;
364 static int ionic_set_fecparam(struct net_device *netdev,
365 struct ethtool_fecparam *fec)
367 struct ionic_lif *lif = netdev_priv(netdev);
371 if (lif->ionic->idev.port_info->config.an_enable) {
372 netdev_err(netdev, "FEC request not allowed while autoneg is enabled\n");
377 case ETHTOOL_FEC_NONE:
378 fec_type = IONIC_PORT_FEC_TYPE_NONE;
380 case ETHTOOL_FEC_OFF:
381 fec_type = IONIC_PORT_FEC_TYPE_NONE;
384 fec_type = IONIC_PORT_FEC_TYPE_RS;
386 case ETHTOOL_FEC_BASER:
387 fec_type = IONIC_PORT_FEC_TYPE_FC;
389 case ETHTOOL_FEC_AUTO:
391 netdev_err(netdev, "FEC request 0x%04x not supported\n",
396 if (fec_type != lif->ionic->idev.port_info->config.fec_type) {
397 mutex_lock(&lif->ionic->dev_cmd_lock);
398 ionic_dev_cmd_port_fec(&lif->ionic->idev, fec_type);
399 ret = ionic_dev_cmd_wait(lif->ionic, DEVCMD_TIMEOUT);
400 mutex_unlock(&lif->ionic->dev_cmd_lock);
406 static int ionic_get_coalesce(struct net_device *netdev,
407 struct ethtool_coalesce *coalesce)
409 struct ionic_lif *lif = netdev_priv(netdev);
411 coalesce->tx_coalesce_usecs = lif->tx_coalesce_usecs;
412 coalesce->rx_coalesce_usecs = lif->rx_coalesce_usecs;
414 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
415 coalesce->use_adaptive_tx_coalesce = test_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);
417 coalesce->use_adaptive_tx_coalesce = 0;
419 coalesce->use_adaptive_rx_coalesce = test_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);
424 static int ionic_set_coalesce(struct net_device *netdev,
425 struct ethtool_coalesce *coalesce)
427 struct ionic_lif *lif = netdev_priv(netdev);
428 struct ionic_identity *ident;
433 ident = &lif->ionic->ident;
434 if (ident->dev.intr_coal_div == 0) {
435 netdev_warn(netdev, "bad HW value in dev.intr_coal_div = %d\n",
436 ident->dev.intr_coal_div);
440 /* Tx normally shares Rx interrupt, so only change Rx if not split */
441 if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state) &&
442 (coalesce->tx_coalesce_usecs != lif->rx_coalesce_usecs ||
443 coalesce->use_adaptive_tx_coalesce)) {
444 netdev_warn(netdev, "only rx parameters can be changed\n");
448 /* Convert the usec request to a HW usable value. If they asked
449 * for non-zero and it resolved to zero, bump it up
451 rx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->rx_coalesce_usecs);
452 if (!rx_coal && coalesce->rx_coalesce_usecs)
454 tx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->tx_coalesce_usecs);
455 if (!tx_coal && coalesce->tx_coalesce_usecs)
458 if (rx_coal > IONIC_INTR_CTRL_COAL_MAX ||
459 tx_coal > IONIC_INTR_CTRL_COAL_MAX)
462 /* Save the new values */
463 lif->rx_coalesce_usecs = coalesce->rx_coalesce_usecs;
464 lif->rx_coalesce_hw = rx_coal;
466 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
467 lif->tx_coalesce_usecs = coalesce->tx_coalesce_usecs;
469 lif->tx_coalesce_usecs = coalesce->rx_coalesce_usecs;
470 lif->tx_coalesce_hw = tx_coal;
472 if (coalesce->use_adaptive_rx_coalesce) {
473 set_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);
476 clear_bit(IONIC_LIF_F_RX_DIM_INTR, lif->state);
480 if (coalesce->use_adaptive_tx_coalesce) {
481 set_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);
484 clear_bit(IONIC_LIF_F_TX_DIM_INTR, lif->state);
488 if (test_bit(IONIC_LIF_F_UP, lif->state)) {
489 for (i = 0; i < lif->nxqs; i++) {
490 if (lif->rxqcqs[i]->flags & IONIC_QCQ_F_INTR) {
491 ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
492 lif->rxqcqs[i]->intr.index,
493 lif->rx_coalesce_hw);
494 lif->rxqcqs[i]->intr.dim_coal_hw = rx_dim;
497 if (lif->txqcqs[i]->flags & IONIC_QCQ_F_INTR) {
498 ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
499 lif->txqcqs[i]->intr.index,
500 lif->tx_coalesce_hw);
501 lif->txqcqs[i]->intr.dim_coal_hw = tx_dim;
509 static void ionic_get_ringparam(struct net_device *netdev,
510 struct ethtool_ringparam *ring)
512 struct ionic_lif *lif = netdev_priv(netdev);
514 ring->tx_max_pending = IONIC_MAX_TX_DESC;
515 ring->tx_pending = lif->ntxq_descs;
516 ring->rx_max_pending = IONIC_MAX_RX_DESC;
517 ring->rx_pending = lif->nrxq_descs;
520 static int ionic_set_ringparam(struct net_device *netdev,
521 struct ethtool_ringparam *ring)
523 struct ionic_lif *lif = netdev_priv(netdev);
524 struct ionic_queue_params qparam;
527 ionic_init_queue_params(lif, &qparam);
529 if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
530 netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n");
534 if (!is_power_of_2(ring->tx_pending) ||
535 !is_power_of_2(ring->rx_pending)) {
536 netdev_info(netdev, "Descriptor count must be a power of 2\n");
540 /* if nothing to do return success */
541 if (ring->tx_pending == lif->ntxq_descs &&
542 ring->rx_pending == lif->nrxq_descs)
545 if (ring->tx_pending != lif->ntxq_descs)
546 netdev_info(netdev, "Changing Tx ring size from %d to %d\n",
547 lif->ntxq_descs, ring->tx_pending);
549 if (ring->rx_pending != lif->nrxq_descs)
550 netdev_info(netdev, "Changing Rx ring size from %d to %d\n",
551 lif->nrxq_descs, ring->rx_pending);
553 /* if we're not running, just set the values and return */
554 if (!netif_running(lif->netdev)) {
555 lif->ntxq_descs = ring->tx_pending;
556 lif->nrxq_descs = ring->rx_pending;
560 qparam.ntxq_descs = ring->tx_pending;
561 qparam.nrxq_descs = ring->rx_pending;
562 err = ionic_reconfigure_queues(lif, &qparam);
564 netdev_info(netdev, "Ring reconfiguration failed, changes canceled: %d\n", err);
569 static void ionic_get_channels(struct net_device *netdev,
570 struct ethtool_channels *ch)
572 struct ionic_lif *lif = netdev_priv(netdev);
574 /* report maximum channels */
575 ch->max_combined = lif->ionic->ntxqs_per_lif;
576 ch->max_rx = lif->ionic->ntxqs_per_lif / 2;
577 ch->max_tx = lif->ionic->ntxqs_per_lif / 2;
579 /* report current channels */
580 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
581 ch->rx_count = lif->nxqs;
582 ch->tx_count = lif->nxqs;
584 ch->combined_count = lif->nxqs;
588 static int ionic_set_channels(struct net_device *netdev,
589 struct ethtool_channels *ch)
591 struct ionic_lif *lif = netdev_priv(netdev);
592 struct ionic_queue_params qparam;
596 ionic_init_queue_params(lif, &qparam);
598 if (ch->rx_count != ch->tx_count) {
599 netdev_info(netdev, "The rx and tx count must be equal\n");
603 if (ch->combined_count && ch->rx_count) {
604 netdev_info(netdev, "Use either combined or rx and tx, not both\n");
608 max_cnt = lif->ionic->ntxqs_per_lif;
609 if (ch->combined_count) {
610 if (ch->combined_count > max_cnt)
613 if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
614 netdev_info(lif->netdev, "Sharing queue interrupts\n");
615 else if (ch->combined_count == lif->nxqs)
618 if (lif->nxqs != ch->combined_count)
619 netdev_info(netdev, "Changing queue count from %d to %d\n",
620 lif->nxqs, ch->combined_count);
622 qparam.nxqs = ch->combined_count;
623 qparam.intr_split = 0;
626 if (ch->rx_count > max_cnt)
629 if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
630 netdev_info(lif->netdev, "Splitting queue interrupts\n");
631 else if (ch->rx_count == lif->nxqs)
634 if (lif->nxqs != ch->rx_count)
635 netdev_info(netdev, "Changing queue count from %d to %d\n",
636 lif->nxqs, ch->rx_count);
638 qparam.nxqs = ch->rx_count;
639 qparam.intr_split = 1;
642 /* if we're not running, just set the values and return */
643 if (!netif_running(lif->netdev)) {
644 lif->nxqs = qparam.nxqs;
646 if (qparam.intr_split) {
647 set_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
649 clear_bit(IONIC_LIF_F_SPLIT_INTR, lif->state);
650 lif->tx_coalesce_usecs = lif->rx_coalesce_usecs;
651 lif->tx_coalesce_hw = lif->rx_coalesce_hw;
656 err = ionic_reconfigure_queues(lif, &qparam);
658 netdev_info(netdev, "Queue reconfiguration failed, changes canceled: %d\n", err);
663 static u32 ionic_get_priv_flags(struct net_device *netdev)
665 struct ionic_lif *lif = netdev_priv(netdev);
668 if (test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state))
669 priv_flags |= IONIC_PRIV_F_SW_DBG_STATS;
674 static int ionic_set_priv_flags(struct net_device *netdev, u32 priv_flags)
676 struct ionic_lif *lif = netdev_priv(netdev);
678 clear_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state);
679 if (priv_flags & IONIC_PRIV_F_SW_DBG_STATS)
680 set_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state);
685 static int ionic_get_rxnfc(struct net_device *netdev,
686 struct ethtool_rxnfc *info, u32 *rules)
688 struct ionic_lif *lif = netdev_priv(netdev);
692 case ETHTOOL_GRXRINGS:
693 info->data = lif->nxqs;
696 netdev_err(netdev, "Command parameter %d is not supported\n",
704 static u32 ionic_get_rxfh_indir_size(struct net_device *netdev)
706 struct ionic_lif *lif = netdev_priv(netdev);
708 return le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
711 static u32 ionic_get_rxfh_key_size(struct net_device *netdev)
713 return IONIC_RSS_HASH_KEY_SIZE;
716 static int ionic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
719 struct ionic_lif *lif = netdev_priv(netdev);
720 unsigned int i, tbl_sz;
723 tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
724 for (i = 0; i < tbl_sz; i++)
725 indir[i] = lif->rss_ind_tbl[i];
729 memcpy(key, lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);
732 *hfunc = ETH_RSS_HASH_TOP;
737 static int ionic_set_rxfh(struct net_device *netdev, const u32 *indir,
738 const u8 *key, const u8 hfunc)
740 struct ionic_lif *lif = netdev_priv(netdev);
743 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
746 err = ionic_lif_rss_config(lif, lif->rss_types, key, indir);
753 static int ionic_set_tunable(struct net_device *dev,
754 const struct ethtool_tunable *tuna,
757 struct ionic_lif *lif = netdev_priv(dev);
760 case ETHTOOL_RX_COPYBREAK:
761 lif->rx_copybreak = *(u32 *)data;
770 static int ionic_get_tunable(struct net_device *netdev,
771 const struct ethtool_tunable *tuna, void *data)
773 struct ionic_lif *lif = netdev_priv(netdev);
776 case ETHTOOL_RX_COPYBREAK:
777 *(u32 *)data = lif->rx_copybreak;
786 static int ionic_get_module_info(struct net_device *netdev,
787 struct ethtool_modinfo *modinfo)
790 struct ionic_lif *lif = netdev_priv(netdev);
791 struct ionic_dev *idev = &lif->ionic->idev;
792 struct ionic_xcvr_status *xcvr;
793 struct sfp_eeprom_base *sfp;
795 xcvr = &idev->port_info->status.xcvr;
796 sfp = (struct sfp_eeprom_base *) xcvr->sprom;
798 /* report the module data type and length */
799 switch (sfp->phys_id) {
801 modinfo->type = ETH_MODULE_SFF_8079;
802 modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
804 case SFF8024_ID_QSFP_8436_8636:
805 case SFF8024_ID_QSFP28_8636:
806 modinfo->type = ETH_MODULE_SFF_8436;
807 modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
810 netdev_info(netdev, "unknown xcvr type 0x%02x\n",
813 modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
820 static int ionic_get_module_eeprom(struct net_device *netdev,
821 struct ethtool_eeprom *ee,
824 struct ionic_lif *lif = netdev_priv(netdev);
825 struct ionic_dev *idev = &lif->ionic->idev;
826 struct ionic_xcvr_status *xcvr;
827 char tbuf[sizeof(xcvr->sprom)];
831 /* The NIC keeps the module prom up-to-date in the DMA space
832 * so we can simply copy the module bytes into the data buffer.
834 xcvr = &idev->port_info->status.xcvr;
835 len = min_t(u32, sizeof(xcvr->sprom), ee->len);
838 memcpy(data, xcvr->sprom, len);
839 memcpy(tbuf, xcvr->sprom, len);
841 /* Let's make sure we got a consistent copy */
842 if (!memcmp(data, tbuf, len))
853 static int ionic_nway_reset(struct net_device *netdev)
855 struct ionic_lif *lif = netdev_priv(netdev);
856 struct ionic *ionic = lif->ionic;
859 /* flap the link to force auto-negotiation */
861 mutex_lock(&ionic->dev_cmd_lock);
863 ionic_dev_cmd_port_state(&ionic->idev, IONIC_PORT_ADMIN_STATE_DOWN);
864 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
867 ionic_dev_cmd_port_state(&ionic->idev, IONIC_PORT_ADMIN_STATE_UP);
868 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
871 mutex_unlock(&ionic->dev_cmd_lock);
876 static const struct ethtool_ops ionic_ethtool_ops = {
877 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
878 ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
879 ETHTOOL_COALESCE_USE_ADAPTIVE_TX,
880 .get_drvinfo = ionic_get_drvinfo,
881 .get_regs_len = ionic_get_regs_len,
882 .get_regs = ionic_get_regs,
883 .get_link = ethtool_op_get_link,
884 .get_link_ksettings = ionic_get_link_ksettings,
885 .set_link_ksettings = ionic_set_link_ksettings,
886 .get_coalesce = ionic_get_coalesce,
887 .set_coalesce = ionic_set_coalesce,
888 .get_ringparam = ionic_get_ringparam,
889 .set_ringparam = ionic_set_ringparam,
890 .get_channels = ionic_get_channels,
891 .set_channels = ionic_set_channels,
892 .get_strings = ionic_get_strings,
893 .get_ethtool_stats = ionic_get_stats,
894 .get_sset_count = ionic_get_sset_count,
895 .get_priv_flags = ionic_get_priv_flags,
896 .set_priv_flags = ionic_set_priv_flags,
897 .get_rxnfc = ionic_get_rxnfc,
898 .get_rxfh_indir_size = ionic_get_rxfh_indir_size,
899 .get_rxfh_key_size = ionic_get_rxfh_key_size,
900 .get_rxfh = ionic_get_rxfh,
901 .set_rxfh = ionic_set_rxfh,
902 .get_tunable = ionic_get_tunable,
903 .set_tunable = ionic_set_tunable,
904 .get_module_info = ionic_get_module_info,
905 .get_module_eeprom = ionic_get_module_eeprom,
906 .get_pauseparam = ionic_get_pauseparam,
907 .set_pauseparam = ionic_set_pauseparam,
908 .get_fecparam = ionic_get_fecparam,
909 .set_fecparam = ionic_set_fecparam,
910 .nway_reset = ionic_nway_reset,
913 void ionic_ethtool_set_ops(struct net_device *netdev)
915 netdev->ethtool_ops = &ionic_ethtool_ops;