1247 lines · c
1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)2/* Copyright 2017-2019 NXP */3 4#include <linux/ethtool_netlink.h>5#include <linux/net_tstamp.h>6#include <linux/module.h>7#include "enetc.h"8 9static const u32 enetc_si_regs[] = {10 ENETC_SIMR, ENETC_SIPMAR0, ENETC_SIPMAR1, ENETC_SICBDRMR,11 ENETC_SICBDRSR, ENETC_SICBDRBAR0, ENETC_SICBDRBAR1, ENETC_SICBDRPIR,12 ENETC_SICBDRCIR, ENETC_SICBDRLENR, ENETC_SICAPR0, ENETC_SICAPR1,13 ENETC_SIUEFDCR14};15 16static const u32 enetc_txbdr_regs[] = {17 ENETC_TBMR, ENETC_TBSR, ENETC_TBBAR0, ENETC_TBBAR1,18 ENETC_TBPIR, ENETC_TBCIR, ENETC_TBLENR, ENETC_TBIER, ENETC_TBICR0,19 ENETC_TBICR120};21 22static const u32 enetc_rxbdr_regs[] = {23 ENETC_RBMR, ENETC_RBSR, ENETC_RBBSR, ENETC_RBCIR, ENETC_RBBAR0,24 ENETC_RBBAR1, ENETC_RBPIR, ENETC_RBLENR, ENETC_RBIER, ENETC_RBICR0,25 ENETC_RBICR126};27 28static const u32 enetc_port_regs[] = {29 ENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0),30 ENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1,31 ENETC_PSICFGR0(0), ENETC_PRFSCAPR, ENETC_PTCMSDUR(0),32 ENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE33};34 35static const u32 enetc_port_mm_regs[] = {36 ENETC_MMCSR, ENETC_PFPMR, ENETC_PTCFPR(0), ENETC_PTCFPR(1),37 ENETC_PTCFPR(2), ENETC_PTCFPR(3), ENETC_PTCFPR(4), ENETC_PTCFPR(5),38 ENETC_PTCFPR(6), ENETC_PTCFPR(7),39};40 41static int enetc_get_reglen(struct net_device *ndev)42{43 struct enetc_ndev_priv *priv = netdev_priv(ndev);44 struct enetc_hw *hw = &priv->si->hw;45 int len;46 47 len = ARRAY_SIZE(enetc_si_regs);48 len += ARRAY_SIZE(enetc_txbdr_regs) * priv->num_tx_rings;49 len += ARRAY_SIZE(enetc_rxbdr_regs) * priv->num_rx_rings;50 51 if (hw->port)52 len += ARRAY_SIZE(enetc_port_regs);53 54 if (hw->port && !!(priv->si->hw_features & ENETC_SI_F_QBU))55 len += ARRAY_SIZE(enetc_port_mm_regs);56 57 len *= sizeof(u32) * 2; /* store 2 entries per reg: addr and value */58 59 return len;60}61 62static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs,63 void *regbuf)64{65 struct enetc_ndev_priv *priv = netdev_priv(ndev);66 struct enetc_hw *hw = &priv->si->hw;67 u32 *buf = (u32 *)regbuf;68 int i, j;69 u32 addr;70 71 for (i = 0; i < ARRAY_SIZE(enetc_si_regs); i++) {72 *buf++ = enetc_si_regs[i];73 *buf++ = enetc_rd(hw, enetc_si_regs[i]);74 }75 76 for (i = 0; i < priv->num_tx_rings; i++) {77 for (j = 0; j < ARRAY_SIZE(enetc_txbdr_regs); j++) {78 addr = ENETC_BDR(TX, i, enetc_txbdr_regs[j]);79 80 *buf++ = addr;81 *buf++ = enetc_rd(hw, addr);82 }83 }84 85 for (i = 0; i < priv->num_rx_rings; i++) {86 for (j = 0; j < ARRAY_SIZE(enetc_rxbdr_regs); j++) {87 addr = ENETC_BDR(RX, i, enetc_rxbdr_regs[j]);88 89 *buf++ = addr;90 *buf++ = enetc_rd(hw, addr);91 }92 }93 94 if (!hw->port)95 return;96 97 for (i = 0; i < ARRAY_SIZE(enetc_port_regs); i++) {98 addr = ENETC_PORT_BASE + enetc_port_regs[i];99 *buf++ = addr;100 *buf++ = enetc_rd(hw, addr);101 }102 103 if (priv->si->hw_features & ENETC_SI_F_QBU) {104 for (i = 0; i < ARRAY_SIZE(enetc_port_mm_regs); i++) {105 addr = ENETC_PORT_BASE + enetc_port_mm_regs[i];106 *buf++ = addr;107 *buf++ = enetc_rd(hw, addr);108 }109 }110}111 112static const struct {113 int reg;114 char name[ETH_GSTRING_LEN];115} enetc_si_counters[] = {116 { ENETC_SIROCT, "SI rx octets" },117 { ENETC_SIRFRM, "SI rx frames" },118 { ENETC_SIRUCA, "SI rx u-cast frames" },119 { ENETC_SIRMCA, "SI rx m-cast frames" },120 { ENETC_SITOCT, "SI tx octets" },121 { ENETC_SITFRM, "SI tx frames" },122 { ENETC_SITUCA, "SI tx u-cast frames" },123 { ENETC_SITMCA, "SI tx m-cast frames" },124 { ENETC_RBDCR(0), "Rx ring 0 discarded frames" },125 { ENETC_RBDCR(1), "Rx ring 1 discarded frames" },126 { ENETC_RBDCR(2), "Rx ring 2 discarded frames" },127 { ENETC_RBDCR(3), "Rx ring 3 discarded frames" },128 { ENETC_RBDCR(4), "Rx ring 4 discarded frames" },129 { ENETC_RBDCR(5), "Rx ring 5 discarded frames" },130 { ENETC_RBDCR(6), "Rx ring 6 discarded frames" },131 { ENETC_RBDCR(7), "Rx ring 7 discarded frames" },132 { ENETC_RBDCR(8), "Rx ring 8 discarded frames" },133 { ENETC_RBDCR(9), "Rx ring 9 discarded frames" },134 { ENETC_RBDCR(10), "Rx ring 10 discarded frames" },135 { ENETC_RBDCR(11), "Rx ring 11 discarded frames" },136 { ENETC_RBDCR(12), "Rx ring 12 discarded frames" },137 { ENETC_RBDCR(13), "Rx ring 13 discarded frames" },138 { ENETC_RBDCR(14), "Rx ring 14 discarded frames" },139 { ENETC_RBDCR(15), "Rx ring 15 discarded frames" },140};141 142static const struct {143 int reg;144 char name[ETH_GSTRING_LEN];145} enetc_port_counters[] = {146 { ENETC_PM_REOCT(0), "MAC rx ethernet octets" },147 { ENETC_PM_RALN(0), "MAC rx alignment errors" },148 { ENETC_PM_RXPF(0), "MAC rx valid pause frames" },149 { ENETC_PM_RFRM(0), "MAC rx valid frames" },150 { ENETC_PM_RFCS(0), "MAC rx fcs errors" },151 { ENETC_PM_RVLAN(0), "MAC rx VLAN frames" },152 { ENETC_PM_RERR(0), "MAC rx frame errors" },153 { ENETC_PM_RUCA(0), "MAC rx unicast frames" },154 { ENETC_PM_RMCA(0), "MAC rx multicast frames" },155 { ENETC_PM_RBCA(0), "MAC rx broadcast frames" },156 { ENETC_PM_RDRP(0), "MAC rx dropped packets" },157 { ENETC_PM_RPKT(0), "MAC rx packets" },158 { ENETC_PM_RUND(0), "MAC rx undersized packets" },159 { ENETC_PM_R64(0), "MAC rx 64 byte packets" },160 { ENETC_PM_R127(0), "MAC rx 65-127 byte packets" },161 { ENETC_PM_R255(0), "MAC rx 128-255 byte packets" },162 { ENETC_PM_R511(0), "MAC rx 256-511 byte packets" },163 { ENETC_PM_R1023(0), "MAC rx 512-1023 byte packets" },164 { ENETC_PM_R1522(0), "MAC rx 1024-1522 byte packets" },165 { ENETC_PM_R1523X(0), "MAC rx 1523 to max-octet packets" },166 { ENETC_PM_ROVR(0), "MAC rx oversized packets" },167 { ENETC_PM_RJBR(0), "MAC rx jabber packets" },168 { ENETC_PM_RFRG(0), "MAC rx fragment packets" },169 { ENETC_PM_RCNP(0), "MAC rx control packets" },170 { ENETC_PM_RDRNTP(0), "MAC rx fifo drop" },171 { ENETC_PM_TEOCT(0), "MAC tx ethernet octets" },172 { ENETC_PM_TOCT(0), "MAC tx octets" },173 { ENETC_PM_TCRSE(0), "MAC tx carrier sense errors" },174 { ENETC_PM_TXPF(0), "MAC tx valid pause frames" },175 { ENETC_PM_TFRM(0), "MAC tx frames" },176 { ENETC_PM_TFCS(0), "MAC tx fcs errors" },177 { ENETC_PM_TVLAN(0), "MAC tx VLAN frames" },178 { ENETC_PM_TERR(0), "MAC tx frame errors" },179 { ENETC_PM_TUCA(0), "MAC tx unicast frames" },180 { ENETC_PM_TMCA(0), "MAC tx multicast frames" },181 { ENETC_PM_TBCA(0), "MAC tx broadcast frames" },182 { ENETC_PM_TPKT(0), "MAC tx packets" },183 { ENETC_PM_TUND(0), "MAC tx undersized packets" },184 { ENETC_PM_T64(0), "MAC tx 64 byte packets" },185 { ENETC_PM_T127(0), "MAC tx 65-127 byte packets" },186 { ENETC_PM_T255(0), "MAC tx 128-255 byte packets" },187 { ENETC_PM_T511(0), "MAC tx 256-511 byte packets" },188 { ENETC_PM_T1023(0), "MAC tx 512-1023 byte packets" },189 { ENETC_PM_T1522(0), "MAC tx 1024-1522 byte packets" },190 { ENETC_PM_T1523X(0), "MAC tx 1523 to max-octet packets" },191 { ENETC_PM_TCNP(0), "MAC tx control packets" },192 { ENETC_PM_TDFR(0), "MAC tx deferred packets" },193 { ENETC_PM_TMCOL(0), "MAC tx multiple collisions" },194 { ENETC_PM_TSCOL(0), "MAC tx single collisions" },195 { ENETC_PM_TLCOL(0), "MAC tx late collisions" },196 { ENETC_PM_TECOL(0), "MAC tx excessive collisions" },197 { ENETC_UFDMF, "SI MAC nomatch u-cast discards" },198 { ENETC_MFDMF, "SI MAC nomatch m-cast discards" },199 { ENETC_PBFDSIR, "SI MAC nomatch b-cast discards" },200 { ENETC_PUFDVFR, "SI VLAN nomatch u-cast discards" },201 { ENETC_PMFDVFR, "SI VLAN nomatch m-cast discards" },202 { ENETC_PBFDVFR, "SI VLAN nomatch b-cast discards" },203 { ENETC_PFDMSAPR, "SI pruning discarded frames" },204 { ENETC_PICDR(0), "ICM DR0 discarded frames" },205 { ENETC_PICDR(1), "ICM DR1 discarded frames" },206 { ENETC_PICDR(2), "ICM DR2 discarded frames" },207 { ENETC_PICDR(3), "ICM DR3 discarded frames" },208};209 210static const char rx_ring_stats[][ETH_GSTRING_LEN] = {211 "Rx ring %2d frames",212 "Rx ring %2d alloc errors",213 "Rx ring %2d XDP drops",214 "Rx ring %2d recycles",215 "Rx ring %2d recycle failures",216 "Rx ring %2d redirects",217 "Rx ring %2d redirect failures",218};219 220static const char tx_ring_stats[][ETH_GSTRING_LEN] = {221 "Tx ring %2d frames",222 "Tx ring %2d XDP frames",223 "Tx ring %2d XDP drops",224 "Tx window drop %2d frames",225};226 227static int enetc_get_sset_count(struct net_device *ndev, int sset)228{229 struct enetc_ndev_priv *priv = netdev_priv(ndev);230 int len;231 232 if (sset != ETH_SS_STATS)233 return -EOPNOTSUPP;234 235 len = ARRAY_SIZE(enetc_si_counters) +236 ARRAY_SIZE(tx_ring_stats) * priv->num_tx_rings +237 ARRAY_SIZE(rx_ring_stats) * priv->num_rx_rings;238 239 if (!enetc_si_is_pf(priv->si))240 return len;241 242 len += ARRAY_SIZE(enetc_port_counters);243 244 return len;245}246 247static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)248{249 struct enetc_ndev_priv *priv = netdev_priv(ndev);250 u8 *p = data;251 int i, j;252 253 switch (stringset) {254 case ETH_SS_STATS:255 for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) {256 strscpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);257 p += ETH_GSTRING_LEN;258 }259 for (i = 0; i < priv->num_tx_rings; i++) {260 for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++) {261 snprintf(p, ETH_GSTRING_LEN, tx_ring_stats[j],262 i);263 p += ETH_GSTRING_LEN;264 }265 }266 for (i = 0; i < priv->num_rx_rings; i++) {267 for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++) {268 snprintf(p, ETH_GSTRING_LEN, rx_ring_stats[j],269 i);270 p += ETH_GSTRING_LEN;271 }272 }273 274 if (!enetc_si_is_pf(priv->si))275 break;276 277 for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) {278 strscpy(p, enetc_port_counters[i].name,279 ETH_GSTRING_LEN);280 p += ETH_GSTRING_LEN;281 }282 break;283 }284}285 286static void enetc_get_ethtool_stats(struct net_device *ndev,287 struct ethtool_stats *stats, u64 *data)288{289 struct enetc_ndev_priv *priv = netdev_priv(ndev);290 struct enetc_hw *hw = &priv->si->hw;291 int i, o = 0;292 293 for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++)294 data[o++] = enetc_rd64(hw, enetc_si_counters[i].reg);295 296 for (i = 0; i < priv->num_tx_rings; i++) {297 data[o++] = priv->tx_ring[i]->stats.packets;298 data[o++] = priv->tx_ring[i]->stats.xdp_tx;299 data[o++] = priv->tx_ring[i]->stats.xdp_tx_drops;300 data[o++] = priv->tx_ring[i]->stats.win_drop;301 }302 303 for (i = 0; i < priv->num_rx_rings; i++) {304 data[o++] = priv->rx_ring[i]->stats.packets;305 data[o++] = priv->rx_ring[i]->stats.rx_alloc_errs;306 data[o++] = priv->rx_ring[i]->stats.xdp_drops;307 data[o++] = priv->rx_ring[i]->stats.recycles;308 data[o++] = priv->rx_ring[i]->stats.recycle_failures;309 data[o++] = priv->rx_ring[i]->stats.xdp_redirect;310 data[o++] = priv->rx_ring[i]->stats.xdp_redirect_failures;311 }312 313 if (!enetc_si_is_pf(priv->si))314 return;315 316 for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)317 data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);318}319 320static void enetc_pause_stats(struct enetc_hw *hw, int mac,321 struct ethtool_pause_stats *pause_stats)322{323 pause_stats->tx_pause_frames = enetc_port_rd(hw, ENETC_PM_TXPF(mac));324 pause_stats->rx_pause_frames = enetc_port_rd(hw, ENETC_PM_RXPF(mac));325}326 327static void enetc_get_pause_stats(struct net_device *ndev,328 struct ethtool_pause_stats *pause_stats)329{330 struct enetc_ndev_priv *priv = netdev_priv(ndev);331 struct enetc_hw *hw = &priv->si->hw;332 struct enetc_si *si = priv->si;333 334 switch (pause_stats->src) {335 case ETHTOOL_MAC_STATS_SRC_EMAC:336 enetc_pause_stats(hw, 0, pause_stats);337 break;338 case ETHTOOL_MAC_STATS_SRC_PMAC:339 if (si->hw_features & ENETC_SI_F_QBU)340 enetc_pause_stats(hw, 1, pause_stats);341 break;342 case ETHTOOL_MAC_STATS_SRC_AGGREGATE:343 ethtool_aggregate_pause_stats(ndev, pause_stats);344 break;345 }346}347 348static void enetc_mac_stats(struct enetc_hw *hw, int mac,349 struct ethtool_eth_mac_stats *s)350{351 s->FramesTransmittedOK = enetc_port_rd(hw, ENETC_PM_TFRM(mac));352 s->SingleCollisionFrames = enetc_port_rd(hw, ENETC_PM_TSCOL(mac));353 s->MultipleCollisionFrames = enetc_port_rd(hw, ENETC_PM_TMCOL(mac));354 s->FramesReceivedOK = enetc_port_rd(hw, ENETC_PM_RFRM(mac));355 s->FrameCheckSequenceErrors = enetc_port_rd(hw, ENETC_PM_RFCS(mac));356 s->AlignmentErrors = enetc_port_rd(hw, ENETC_PM_RALN(mac));357 s->OctetsTransmittedOK = enetc_port_rd(hw, ENETC_PM_TEOCT(mac));358 s->FramesWithDeferredXmissions = enetc_port_rd(hw, ENETC_PM_TDFR(mac));359 s->LateCollisions = enetc_port_rd(hw, ENETC_PM_TLCOL(mac));360 s->FramesAbortedDueToXSColls = enetc_port_rd(hw, ENETC_PM_TECOL(mac));361 s->FramesLostDueToIntMACXmitError = enetc_port_rd(hw, ENETC_PM_TERR(mac));362 s->CarrierSenseErrors = enetc_port_rd(hw, ENETC_PM_TCRSE(mac));363 s->OctetsReceivedOK = enetc_port_rd(hw, ENETC_PM_REOCT(mac));364 s->FramesLostDueToIntMACRcvError = enetc_port_rd(hw, ENETC_PM_RDRNTP(mac));365 s->MulticastFramesXmittedOK = enetc_port_rd(hw, ENETC_PM_TMCA(mac));366 s->BroadcastFramesXmittedOK = enetc_port_rd(hw, ENETC_PM_TBCA(mac));367 s->MulticastFramesReceivedOK = enetc_port_rd(hw, ENETC_PM_RMCA(mac));368 s->BroadcastFramesReceivedOK = enetc_port_rd(hw, ENETC_PM_RBCA(mac));369}370 371static void enetc_ctrl_stats(struct enetc_hw *hw, int mac,372 struct ethtool_eth_ctrl_stats *s)373{374 s->MACControlFramesTransmitted = enetc_port_rd(hw, ENETC_PM_TCNP(mac));375 s->MACControlFramesReceived = enetc_port_rd(hw, ENETC_PM_RCNP(mac));376}377 378static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = {379 { 64, 64 },380 { 65, 127 },381 { 128, 255 },382 { 256, 511 },383 { 512, 1023 },384 { 1024, 1522 },385 { 1523, ENETC_MAC_MAXFRM_SIZE },386 {},387};388 389static void enetc_rmon_stats(struct enetc_hw *hw, int mac,390 struct ethtool_rmon_stats *s)391{392 s->undersize_pkts = enetc_port_rd(hw, ENETC_PM_RUND(mac));393 s->oversize_pkts = enetc_port_rd(hw, ENETC_PM_ROVR(mac));394 s->fragments = enetc_port_rd(hw, ENETC_PM_RFRG(mac));395 s->jabbers = enetc_port_rd(hw, ENETC_PM_RJBR(mac));396 397 s->hist[0] = enetc_port_rd(hw, ENETC_PM_R64(mac));398 s->hist[1] = enetc_port_rd(hw, ENETC_PM_R127(mac));399 s->hist[2] = enetc_port_rd(hw, ENETC_PM_R255(mac));400 s->hist[3] = enetc_port_rd(hw, ENETC_PM_R511(mac));401 s->hist[4] = enetc_port_rd(hw, ENETC_PM_R1023(mac));402 s->hist[5] = enetc_port_rd(hw, ENETC_PM_R1522(mac));403 s->hist[6] = enetc_port_rd(hw, ENETC_PM_R1523X(mac));404 405 s->hist_tx[0] = enetc_port_rd(hw, ENETC_PM_T64(mac));406 s->hist_tx[1] = enetc_port_rd(hw, ENETC_PM_T127(mac));407 s->hist_tx[2] = enetc_port_rd(hw, ENETC_PM_T255(mac));408 s->hist_tx[3] = enetc_port_rd(hw, ENETC_PM_T511(mac));409 s->hist_tx[4] = enetc_port_rd(hw, ENETC_PM_T1023(mac));410 s->hist_tx[5] = enetc_port_rd(hw, ENETC_PM_T1522(mac));411 s->hist_tx[6] = enetc_port_rd(hw, ENETC_PM_T1523X(mac));412}413 414static void enetc_get_eth_mac_stats(struct net_device *ndev,415 struct ethtool_eth_mac_stats *mac_stats)416{417 struct enetc_ndev_priv *priv = netdev_priv(ndev);418 struct enetc_hw *hw = &priv->si->hw;419 struct enetc_si *si = priv->si;420 421 switch (mac_stats->src) {422 case ETHTOOL_MAC_STATS_SRC_EMAC:423 enetc_mac_stats(hw, 0, mac_stats);424 break;425 case ETHTOOL_MAC_STATS_SRC_PMAC:426 if (si->hw_features & ENETC_SI_F_QBU)427 enetc_mac_stats(hw, 1, mac_stats);428 break;429 case ETHTOOL_MAC_STATS_SRC_AGGREGATE:430 ethtool_aggregate_mac_stats(ndev, mac_stats);431 break;432 }433}434 435static void enetc_get_eth_ctrl_stats(struct net_device *ndev,436 struct ethtool_eth_ctrl_stats *ctrl_stats)437{438 struct enetc_ndev_priv *priv = netdev_priv(ndev);439 struct enetc_hw *hw = &priv->si->hw;440 struct enetc_si *si = priv->si;441 442 switch (ctrl_stats->src) {443 case ETHTOOL_MAC_STATS_SRC_EMAC:444 enetc_ctrl_stats(hw, 0, ctrl_stats);445 break;446 case ETHTOOL_MAC_STATS_SRC_PMAC:447 if (si->hw_features & ENETC_SI_F_QBU)448 enetc_ctrl_stats(hw, 1, ctrl_stats);449 break;450 case ETHTOOL_MAC_STATS_SRC_AGGREGATE:451 ethtool_aggregate_ctrl_stats(ndev, ctrl_stats);452 break;453 }454}455 456static void enetc_get_rmon_stats(struct net_device *ndev,457 struct ethtool_rmon_stats *rmon_stats,458 const struct ethtool_rmon_hist_range **ranges)459{460 struct enetc_ndev_priv *priv = netdev_priv(ndev);461 struct enetc_hw *hw = &priv->si->hw;462 struct enetc_si *si = priv->si;463 464 *ranges = enetc_rmon_ranges;465 466 switch (rmon_stats->src) {467 case ETHTOOL_MAC_STATS_SRC_EMAC:468 enetc_rmon_stats(hw, 0, rmon_stats);469 break;470 case ETHTOOL_MAC_STATS_SRC_PMAC:471 if (si->hw_features & ENETC_SI_F_QBU)472 enetc_rmon_stats(hw, 1, rmon_stats);473 break;474 case ETHTOOL_MAC_STATS_SRC_AGGREGATE:475 ethtool_aggregate_rmon_stats(ndev, rmon_stats);476 break;477 }478}479 480#define ENETC_RSSHASH_L3 (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO | RXH_IP_SRC | \481 RXH_IP_DST)482#define ENETC_RSSHASH_L4 (ENETC_RSSHASH_L3 | RXH_L4_B_0_1 | RXH_L4_B_2_3)483static int enetc_get_rsshash(struct ethtool_rxnfc *rxnfc)484{485 static const u32 rsshash[] = {486 [TCP_V4_FLOW] = ENETC_RSSHASH_L4,487 [UDP_V4_FLOW] = ENETC_RSSHASH_L4,488 [SCTP_V4_FLOW] = ENETC_RSSHASH_L4,489 [AH_ESP_V4_FLOW] = ENETC_RSSHASH_L3,490 [IPV4_FLOW] = ENETC_RSSHASH_L3,491 [TCP_V6_FLOW] = ENETC_RSSHASH_L4,492 [UDP_V6_FLOW] = ENETC_RSSHASH_L4,493 [SCTP_V6_FLOW] = ENETC_RSSHASH_L4,494 [AH_ESP_V6_FLOW] = ENETC_RSSHASH_L3,495 [IPV6_FLOW] = ENETC_RSSHASH_L3,496 [ETHER_FLOW] = 0,497 };498 499 if (rxnfc->flow_type >= ARRAY_SIZE(rsshash))500 return -EINVAL;501 502 rxnfc->data = rsshash[rxnfc->flow_type];503 504 return 0;505}506 507/* current HW spec does byte reversal on everything including MAC addresses */508static void ether_addr_copy_swap(u8 *dst, const u8 *src)509{510 int i;511 512 for (i = 0; i < ETH_ALEN; i++)513 dst[i] = src[ETH_ALEN - i - 1];514}515 516static int enetc_set_cls_entry(struct enetc_si *si,517 struct ethtool_rx_flow_spec *fs, bool en)518{519 struct ethtool_tcpip4_spec *l4ip4_h, *l4ip4_m;520 struct ethtool_usrip4_spec *l3ip4_h, *l3ip4_m;521 struct ethhdr *eth_h, *eth_m;522 struct enetc_cmd_rfse rfse = { {0} };523 524 if (!en)525 goto done;526 527 switch (fs->flow_type & 0xff) {528 case TCP_V4_FLOW:529 l4ip4_h = &fs->h_u.tcp_ip4_spec;530 l4ip4_m = &fs->m_u.tcp_ip4_spec;531 goto l4ip4;532 case UDP_V4_FLOW:533 l4ip4_h = &fs->h_u.udp_ip4_spec;534 l4ip4_m = &fs->m_u.udp_ip4_spec;535 goto l4ip4;536 case SCTP_V4_FLOW:537 l4ip4_h = &fs->h_u.sctp_ip4_spec;538 l4ip4_m = &fs->m_u.sctp_ip4_spec;539l4ip4:540 rfse.sip_h[0] = l4ip4_h->ip4src;541 rfse.sip_m[0] = l4ip4_m->ip4src;542 rfse.dip_h[0] = l4ip4_h->ip4dst;543 rfse.dip_m[0] = l4ip4_m->ip4dst;544 rfse.sport_h = ntohs(l4ip4_h->psrc);545 rfse.sport_m = ntohs(l4ip4_m->psrc);546 rfse.dport_h = ntohs(l4ip4_h->pdst);547 rfse.dport_m = ntohs(l4ip4_m->pdst);548 if (l4ip4_m->tos)549 netdev_warn(si->ndev, "ToS field is not supported and was ignored\n");550 rfse.ethtype_h = ETH_P_IP; /* IPv4 */551 rfse.ethtype_m = 0xffff;552 break;553 case IP_USER_FLOW:554 l3ip4_h = &fs->h_u.usr_ip4_spec;555 l3ip4_m = &fs->m_u.usr_ip4_spec;556 557 rfse.sip_h[0] = l3ip4_h->ip4src;558 rfse.sip_m[0] = l3ip4_m->ip4src;559 rfse.dip_h[0] = l3ip4_h->ip4dst;560 rfse.dip_m[0] = l3ip4_m->ip4dst;561 if (l3ip4_m->tos)562 netdev_warn(si->ndev, "ToS field is not supported and was ignored\n");563 rfse.ethtype_h = ETH_P_IP; /* IPv4 */564 rfse.ethtype_m = 0xffff;565 break;566 case ETHER_FLOW:567 eth_h = &fs->h_u.ether_spec;568 eth_m = &fs->m_u.ether_spec;569 570 ether_addr_copy_swap(rfse.smac_h, eth_h->h_source);571 ether_addr_copy_swap(rfse.smac_m, eth_m->h_source);572 ether_addr_copy_swap(rfse.dmac_h, eth_h->h_dest);573 ether_addr_copy_swap(rfse.dmac_m, eth_m->h_dest);574 rfse.ethtype_h = ntohs(eth_h->h_proto);575 rfse.ethtype_m = ntohs(eth_m->h_proto);576 break;577 default:578 return -EOPNOTSUPP;579 }580 581 rfse.mode |= ENETC_RFSE_EN;582 if (fs->ring_cookie != RX_CLS_FLOW_DISC) {583 rfse.mode |= ENETC_RFSE_MODE_BD;584 rfse.result = fs->ring_cookie;585 }586done:587 return enetc_set_fs_entry(si, &rfse, fs->location);588}589 590static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc,591 u32 *rule_locs)592{593 struct enetc_ndev_priv *priv = netdev_priv(ndev);594 int i, j;595 596 switch (rxnfc->cmd) {597 case ETHTOOL_GRXRINGS:598 rxnfc->data = priv->num_rx_rings;599 break;600 case ETHTOOL_GRXFH:601 /* get RSS hash config */602 return enetc_get_rsshash(rxnfc);603 case ETHTOOL_GRXCLSRLCNT:604 /* total number of entries */605 rxnfc->data = priv->si->num_fs_entries;606 /* number of entries in use */607 rxnfc->rule_cnt = 0;608 for (i = 0; i < priv->si->num_fs_entries; i++)609 if (priv->cls_rules[i].used)610 rxnfc->rule_cnt++;611 break;612 case ETHTOOL_GRXCLSRULE:613 if (rxnfc->fs.location >= priv->si->num_fs_entries)614 return -EINVAL;615 616 /* get entry x */617 rxnfc->fs = priv->cls_rules[rxnfc->fs.location].fs;618 break;619 case ETHTOOL_GRXCLSRLALL:620 /* total number of entries */621 rxnfc->data = priv->si->num_fs_entries;622 /* array of indexes of used entries */623 j = 0;624 for (i = 0; i < priv->si->num_fs_entries; i++) {625 if (!priv->cls_rules[i].used)626 continue;627 if (j == rxnfc->rule_cnt)628 return -EMSGSIZE;629 rule_locs[j++] = i;630 }631 /* number of entries in use */632 rxnfc->rule_cnt = j;633 break;634 default:635 return -EOPNOTSUPP;636 }637 638 return 0;639}640 641static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc)642{643 struct enetc_ndev_priv *priv = netdev_priv(ndev);644 int err;645 646 switch (rxnfc->cmd) {647 case ETHTOOL_SRXCLSRLINS:648 if (rxnfc->fs.location >= priv->si->num_fs_entries)649 return -EINVAL;650 651 if (rxnfc->fs.ring_cookie >= priv->num_rx_rings &&652 rxnfc->fs.ring_cookie != RX_CLS_FLOW_DISC)653 return -EINVAL;654 655 err = enetc_set_cls_entry(priv->si, &rxnfc->fs, true);656 if (err)657 return err;658 priv->cls_rules[rxnfc->fs.location].fs = rxnfc->fs;659 priv->cls_rules[rxnfc->fs.location].used = 1;660 break;661 case ETHTOOL_SRXCLSRLDEL:662 if (rxnfc->fs.location >= priv->si->num_fs_entries)663 return -EINVAL;664 665 err = enetc_set_cls_entry(priv->si, &rxnfc->fs, false);666 if (err)667 return err;668 priv->cls_rules[rxnfc->fs.location].used = 0;669 break;670 default:671 return -EOPNOTSUPP;672 }673 674 return 0;675}676 677static u32 enetc_get_rxfh_key_size(struct net_device *ndev)678{679 struct enetc_ndev_priv *priv = netdev_priv(ndev);680 681 /* return the size of the RX flow hash key. PF only */682 return (priv->si->hw.port) ? ENETC_RSSHASH_KEY_SIZE : 0;683}684 685static u32 enetc_get_rxfh_indir_size(struct net_device *ndev)686{687 struct enetc_ndev_priv *priv = netdev_priv(ndev);688 689 /* return the size of the RX flow hash indirection table */690 return priv->si->num_rss;691}692 693static int enetc_get_rxfh(struct net_device *ndev,694 struct ethtool_rxfh_param *rxfh)695{696 struct enetc_ndev_priv *priv = netdev_priv(ndev);697 struct enetc_hw *hw = &priv->si->hw;698 int err = 0, i;699 700 /* return hash function */701 rxfh->hfunc = ETH_RSS_HASH_TOP;702 703 /* return hash key */704 if (rxfh->key && hw->port)705 for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)706 ((u32 *)rxfh->key)[i] = enetc_port_rd(hw,707 ENETC_PRSSK(i));708 709 /* return RSS table */710 if (rxfh->indir)711 err = enetc_get_rss_table(priv->si, rxfh->indir,712 priv->si->num_rss);713 714 return err;715}716 717void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)718{719 int i;720 721 for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)722 enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);723}724EXPORT_SYMBOL_GPL(enetc_set_rss_key);725 726static int enetc_set_rxfh(struct net_device *ndev,727 struct ethtool_rxfh_param *rxfh,728 struct netlink_ext_ack *extack)729{730 struct enetc_ndev_priv *priv = netdev_priv(ndev);731 struct enetc_hw *hw = &priv->si->hw;732 int err = 0;733 734 /* set hash key, if PF */735 if (rxfh->key && hw->port)736 enetc_set_rss_key(hw, rxfh->key);737 738 /* set RSS table */739 if (rxfh->indir)740 err = enetc_set_rss_table(priv->si, rxfh->indir,741 priv->si->num_rss);742 743 return err;744}745 746static void enetc_get_ringparam(struct net_device *ndev,747 struct ethtool_ringparam *ring,748 struct kernel_ethtool_ringparam *kernel_ring,749 struct netlink_ext_ack *extack)750{751 struct enetc_ndev_priv *priv = netdev_priv(ndev);752 753 ring->rx_pending = priv->rx_bd_count;754 ring->tx_pending = priv->tx_bd_count;755 756 /* do some h/w sanity checks for BDR length */757 if (netif_running(ndev)) {758 struct enetc_hw *hw = &priv->si->hw;759 u32 val = enetc_rxbdr_rd(hw, 0, ENETC_RBLENR);760 761 if (val != priv->rx_bd_count)762 netif_err(priv, hw, ndev, "RxBDR[RBLENR] = %d!\n", val);763 764 val = enetc_txbdr_rd(hw, 0, ENETC_TBLENR);765 766 if (val != priv->tx_bd_count)767 netif_err(priv, hw, ndev, "TxBDR[TBLENR] = %d!\n", val);768 }769}770 771static int enetc_get_coalesce(struct net_device *ndev,772 struct ethtool_coalesce *ic,773 struct kernel_ethtool_coalesce *kernel_coal,774 struct netlink_ext_ack *extack)775{776 struct enetc_ndev_priv *priv = netdev_priv(ndev);777 struct enetc_int_vector *v = priv->int_vector[0];778 779 ic->tx_coalesce_usecs = enetc_cycles_to_usecs(priv->tx_ictt);780 ic->rx_coalesce_usecs = enetc_cycles_to_usecs(v->rx_ictt);781 782 ic->tx_max_coalesced_frames = ENETC_TXIC_PKTTHR;783 ic->rx_max_coalesced_frames = ENETC_RXIC_PKTTHR;784 785 ic->use_adaptive_rx_coalesce = priv->ic_mode & ENETC_IC_RX_ADAPTIVE;786 787 return 0;788}789 790static int enetc_set_coalesce(struct net_device *ndev,791 struct ethtool_coalesce *ic,792 struct kernel_ethtool_coalesce *kernel_coal,793 struct netlink_ext_ack *extack)794{795 struct enetc_ndev_priv *priv = netdev_priv(ndev);796 u32 rx_ictt, tx_ictt;797 int i, ic_mode;798 bool changed;799 800 tx_ictt = enetc_usecs_to_cycles(ic->tx_coalesce_usecs);801 rx_ictt = enetc_usecs_to_cycles(ic->rx_coalesce_usecs);802 803 if (ic->rx_max_coalesced_frames != ENETC_RXIC_PKTTHR)804 return -EOPNOTSUPP;805 806 if (ic->tx_max_coalesced_frames != ENETC_TXIC_PKTTHR)807 return -EOPNOTSUPP;808 809 ic_mode = ENETC_IC_NONE;810 if (ic->use_adaptive_rx_coalesce) {811 ic_mode |= ENETC_IC_RX_ADAPTIVE;812 rx_ictt = 0x1;813 } else {814 ic_mode |= rx_ictt ? ENETC_IC_RX_MANUAL : 0;815 }816 817 ic_mode |= tx_ictt ? ENETC_IC_TX_MANUAL : 0;818 819 /* commit the settings */820 changed = (ic_mode != priv->ic_mode) || (priv->tx_ictt != tx_ictt);821 822 priv->ic_mode = ic_mode;823 priv->tx_ictt = tx_ictt;824 825 for (i = 0; i < priv->bdr_int_num; i++) {826 struct enetc_int_vector *v = priv->int_vector[i];827 828 v->rx_ictt = rx_ictt;829 v->rx_dim_en = !!(ic_mode & ENETC_IC_RX_ADAPTIVE);830 }831 832 if (netif_running(ndev) && changed) {833 /* reconfigure the operation mode of h/w interrupts,834 * traffic needs to be paused in the process835 */836 enetc_stop(ndev);837 enetc_start(ndev);838 }839 840 return 0;841}842 843static int enetc_get_ts_info(struct net_device *ndev,844 struct kernel_ethtool_ts_info *info)845{846 int *phc_idx;847 848 phc_idx = symbol_get(enetc_phc_index);849 if (phc_idx) {850 info->phc_index = *phc_idx;851 symbol_put(enetc_phc_index);852 }853 854 if (!IS_ENABLED(CONFIG_FSL_ENETC_PTP_CLOCK)) {855 info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE;856 857 return 0;858 }859 860 info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |861 SOF_TIMESTAMPING_RX_HARDWARE |862 SOF_TIMESTAMPING_RAW_HARDWARE |863 SOF_TIMESTAMPING_TX_SOFTWARE;864 865 info->tx_types = (1 << HWTSTAMP_TX_OFF) |866 (1 << HWTSTAMP_TX_ON) |867 (1 << HWTSTAMP_TX_ONESTEP_SYNC);868 869 info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |870 (1 << HWTSTAMP_FILTER_ALL);871 872 return 0;873}874 875static void enetc_get_wol(struct net_device *dev,876 struct ethtool_wolinfo *wol)877{878 wol->supported = 0;879 wol->wolopts = 0;880 881 if (dev->phydev)882 phy_ethtool_get_wol(dev->phydev, wol);883}884 885static int enetc_set_wol(struct net_device *dev,886 struct ethtool_wolinfo *wol)887{888 int ret;889 890 if (!dev->phydev)891 return -EOPNOTSUPP;892 893 ret = phy_ethtool_set_wol(dev->phydev, wol);894 if (!ret)895 device_set_wakeup_enable(&dev->dev, wol->wolopts);896 897 return ret;898}899 900static void enetc_get_pauseparam(struct net_device *dev,901 struct ethtool_pauseparam *pause)902{903 struct enetc_ndev_priv *priv = netdev_priv(dev);904 905 phylink_ethtool_get_pauseparam(priv->phylink, pause);906}907 908static int enetc_set_pauseparam(struct net_device *dev,909 struct ethtool_pauseparam *pause)910{911 struct enetc_ndev_priv *priv = netdev_priv(dev);912 913 return phylink_ethtool_set_pauseparam(priv->phylink, pause);914}915 916static int enetc_get_link_ksettings(struct net_device *dev,917 struct ethtool_link_ksettings *cmd)918{919 struct enetc_ndev_priv *priv = netdev_priv(dev);920 921 if (!priv->phylink)922 return -EOPNOTSUPP;923 924 return phylink_ethtool_ksettings_get(priv->phylink, cmd);925}926 927static int enetc_set_link_ksettings(struct net_device *dev,928 const struct ethtool_link_ksettings *cmd)929{930 struct enetc_ndev_priv *priv = netdev_priv(dev);931 932 if (!priv->phylink)933 return -EOPNOTSUPP;934 935 return phylink_ethtool_ksettings_set(priv->phylink, cmd);936}937 938static void enetc_get_mm_stats(struct net_device *ndev,939 struct ethtool_mm_stats *s)940{941 struct enetc_ndev_priv *priv = netdev_priv(ndev);942 struct enetc_hw *hw = &priv->si->hw;943 struct enetc_si *si = priv->si;944 945 if (!(si->hw_features & ENETC_SI_F_QBU))946 return;947 948 s->MACMergeFrameAssErrorCount = enetc_port_rd(hw, ENETC_MMFAECR);949 s->MACMergeFrameSmdErrorCount = enetc_port_rd(hw, ENETC_MMFSECR);950 s->MACMergeFrameAssOkCount = enetc_port_rd(hw, ENETC_MMFAOCR);951 s->MACMergeFragCountRx = enetc_port_rd(hw, ENETC_MMFCRXR);952 s->MACMergeFragCountTx = enetc_port_rd(hw, ENETC_MMFCTXR);953 s->MACMergeHoldCount = enetc_port_rd(hw, ENETC_MMHCR);954}955 956static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)957{958 struct enetc_ndev_priv *priv = netdev_priv(ndev);959 struct enetc_si *si = priv->si;960 struct enetc_hw *hw = &si->hw;961 u32 lafs, rafs, val;962 963 if (!(si->hw_features & ENETC_SI_F_QBU))964 return -EOPNOTSUPP;965 966 mutex_lock(&priv->mm_lock);967 968 val = enetc_port_rd(hw, ENETC_PFPMR);969 state->pmac_enabled = !!(val & ENETC_PFPMR_PMACE);970 971 val = enetc_port_rd(hw, ENETC_MMCSR);972 973 switch (ENETC_MMCSR_GET_VSTS(val)) {974 case 0:975 state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;976 break;977 case 2:978 state->verify_status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;979 break;980 case 3:981 state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;982 break;983 case 4:984 state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;985 break;986 case 5:987 default:988 state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;989 break;990 }991 992 rafs = ENETC_MMCSR_GET_RAFS(val);993 state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(rafs);994 lafs = ENETC_MMCSR_GET_LAFS(val);995 state->rx_min_frag_size = ethtool_mm_frag_size_add_to_min(lafs);996 state->tx_enabled = !!(val & ENETC_MMCSR_LPE); /* mirror of MMCSR_ME */997 state->tx_active = state->tx_enabled &&998 (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||999 state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);1000 state->verify_enabled = !(val & ENETC_MMCSR_VDIS);1001 state->verify_time = ENETC_MMCSR_GET_VT(val);1002 /* A verifyTime of 128 ms would exceed the 7 bit width1003 * of the ENETC_MMCSR_VT field1004 */1005 state->max_verify_time = 127;1006 1007 mutex_unlock(&priv->mm_lock);1008 1009 return 0;1010}1011 1012static int enetc_mm_wait_tx_active(struct enetc_hw *hw, int verify_time)1013{1014 int timeout = verify_time * USEC_PER_MSEC * ENETC_MM_VERIFY_RETRIES;1015 u32 val;1016 1017 /* This will time out after the standard value of 3 verification1018 * attempts. To not sleep forever, it relies on a non-zero verify_time,1019 * guarantee which is provided by the ethtool nlattr policy.1020 */1021 return read_poll_timeout(enetc_port_rd, val,1022 ENETC_MMCSR_GET_VSTS(val) == 3,1023 ENETC_MM_VERIFY_SLEEP_US, timeout,1024 true, hw, ENETC_MMCSR);1025}1026 1027static void enetc_set_ptcfpr(struct enetc_hw *hw, u8 preemptible_tcs)1028{1029 u32 val;1030 int tc;1031 1032 for (tc = 0; tc < 8; tc++) {1033 val = enetc_port_rd(hw, ENETC_PTCFPR(tc));1034 1035 if (preemptible_tcs & BIT(tc))1036 val |= ENETC_PTCFPR_FPE;1037 else1038 val &= ~ENETC_PTCFPR_FPE;1039 1040 enetc_port_wr(hw, ENETC_PTCFPR(tc), val);1041 }1042}1043 1044/* ENETC does not have an IRQ to notify changes to the MAC Merge TX status1045 * (active/inactive), but the preemptible traffic classes should only be1046 * committed to hardware once TX is active. Resort to polling.1047 */1048void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv)1049{1050 struct enetc_hw *hw = &priv->si->hw;1051 u8 preemptible_tcs = 0;1052 u32 val;1053 int err;1054 1055 val = enetc_port_rd(hw, ENETC_MMCSR);1056 if (!(val & ENETC_MMCSR_ME))1057 goto out;1058 1059 if (!(val & ENETC_MMCSR_VDIS)) {1060 err = enetc_mm_wait_tx_active(hw, ENETC_MMCSR_GET_VT(val));1061 if (err)1062 goto out;1063 }1064 1065 preemptible_tcs = priv->preemptible_tcs;1066out:1067 enetc_set_ptcfpr(hw, preemptible_tcs);1068}1069 1070/* FIXME: Workaround for the link partner's verification failing if ENETC1071 * priorly received too much express traffic. The documentation doesn't1072 * suggest this is needed.1073 */1074static void enetc_restart_emac_rx(struct enetc_si *si)1075{1076 u32 val = enetc_port_rd(&si->hw, ENETC_PM0_CMD_CFG);1077 1078 enetc_port_wr(&si->hw, ENETC_PM0_CMD_CFG, val & ~ENETC_PM0_RX_EN);1079 1080 if (val & ENETC_PM0_RX_EN)1081 enetc_port_wr(&si->hw, ENETC_PM0_CMD_CFG, val);1082}1083 1084static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,1085 struct netlink_ext_ack *extack)1086{1087 struct enetc_ndev_priv *priv = netdev_priv(ndev);1088 struct enetc_hw *hw = &priv->si->hw;1089 struct enetc_si *si = priv->si;1090 u32 val, add_frag_size;1091 int err;1092 1093 if (!(si->hw_features & ENETC_SI_F_QBU))1094 return -EOPNOTSUPP;1095 1096 err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size,1097 &add_frag_size, extack);1098 if (err)1099 return err;1100 1101 mutex_lock(&priv->mm_lock);1102 1103 val = enetc_port_rd(hw, ENETC_PFPMR);1104 if (cfg->pmac_enabled)1105 val |= ENETC_PFPMR_PMACE;1106 else1107 val &= ~ENETC_PFPMR_PMACE;1108 enetc_port_wr(hw, ENETC_PFPMR, val);1109 1110 val = enetc_port_rd(hw, ENETC_MMCSR);1111 1112 if (cfg->verify_enabled)1113 val &= ~ENETC_MMCSR_VDIS;1114 else1115 val |= ENETC_MMCSR_VDIS;1116 1117 if (cfg->tx_enabled)1118 priv->active_offloads |= ENETC_F_QBU;1119 else1120 priv->active_offloads &= ~ENETC_F_QBU;1121 1122 /* If link is up, enable/disable MAC Merge right away */1123 if (!(val & ENETC_MMCSR_LINK_FAIL)) {1124 if (!!(priv->active_offloads & ENETC_F_QBU))1125 val |= ENETC_MMCSR_ME;1126 else1127 val &= ~ENETC_MMCSR_ME;1128 }1129 1130 val &= ~ENETC_MMCSR_VT_MASK;1131 val |= ENETC_MMCSR_VT(cfg->verify_time);1132 1133 val &= ~ENETC_MMCSR_RAFS_MASK;1134 val |= ENETC_MMCSR_RAFS(add_frag_size);1135 1136 enetc_port_wr(hw, ENETC_MMCSR, val);1137 1138 enetc_restart_emac_rx(priv->si);1139 1140 enetc_mm_commit_preemptible_tcs(priv);1141 1142 mutex_unlock(&priv->mm_lock);1143 1144 return 0;1145}1146 1147/* When the link is lost, the verification state machine goes to the FAILED1148 * state and doesn't restart on its own after a new link up event.1149 * According to 802.3 Figure 99-8 - Verify state diagram, the LINK_FAIL bit1150 * should have been sufficient to re-trigger verification, but for ENETC it1151 * doesn't. As a workaround, we need to toggle the Merge Enable bit to1152 * re-trigger verification when link comes up.1153 */1154void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link)1155{1156 struct enetc_hw *hw = &priv->si->hw;1157 u32 val;1158 1159 mutex_lock(&priv->mm_lock);1160 1161 val = enetc_port_rd(hw, ENETC_MMCSR);1162 1163 if (link) {1164 val &= ~ENETC_MMCSR_LINK_FAIL;1165 if (priv->active_offloads & ENETC_F_QBU)1166 val |= ENETC_MMCSR_ME;1167 } else {1168 val |= ENETC_MMCSR_LINK_FAIL;1169 if (priv->active_offloads & ENETC_F_QBU)1170 val &= ~ENETC_MMCSR_ME;1171 }1172 1173 enetc_port_wr(hw, ENETC_MMCSR, val);1174 1175 enetc_mm_commit_preemptible_tcs(priv);1176 1177 mutex_unlock(&priv->mm_lock);1178}1179EXPORT_SYMBOL_GPL(enetc_mm_link_state_update);1180 1181static const struct ethtool_ops enetc_pf_ethtool_ops = {1182 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |1183 ETHTOOL_COALESCE_MAX_FRAMES |1184 ETHTOOL_COALESCE_USE_ADAPTIVE_RX,1185 .get_regs_len = enetc_get_reglen,1186 .get_regs = enetc_get_regs,1187 .get_sset_count = enetc_get_sset_count,1188 .get_strings = enetc_get_strings,1189 .get_ethtool_stats = enetc_get_ethtool_stats,1190 .get_pause_stats = enetc_get_pause_stats,1191 .get_rmon_stats = enetc_get_rmon_stats,1192 .get_eth_ctrl_stats = enetc_get_eth_ctrl_stats,1193 .get_eth_mac_stats = enetc_get_eth_mac_stats,1194 .get_rxnfc = enetc_get_rxnfc,1195 .set_rxnfc = enetc_set_rxnfc,1196 .get_rxfh_key_size = enetc_get_rxfh_key_size,1197 .get_rxfh_indir_size = enetc_get_rxfh_indir_size,1198 .get_rxfh = enetc_get_rxfh,1199 .set_rxfh = enetc_set_rxfh,1200 .get_ringparam = enetc_get_ringparam,1201 .get_coalesce = enetc_get_coalesce,1202 .set_coalesce = enetc_set_coalesce,1203 .get_link_ksettings = enetc_get_link_ksettings,1204 .set_link_ksettings = enetc_set_link_ksettings,1205 .get_link = ethtool_op_get_link,1206 .get_ts_info = enetc_get_ts_info,1207 .get_wol = enetc_get_wol,1208 .set_wol = enetc_set_wol,1209 .get_pauseparam = enetc_get_pauseparam,1210 .set_pauseparam = enetc_set_pauseparam,1211 .get_mm = enetc_get_mm,1212 .set_mm = enetc_set_mm,1213 .get_mm_stats = enetc_get_mm_stats,1214};1215 1216static const struct ethtool_ops enetc_vf_ethtool_ops = {1217 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |1218 ETHTOOL_COALESCE_MAX_FRAMES |1219 ETHTOOL_COALESCE_USE_ADAPTIVE_RX,1220 .get_regs_len = enetc_get_reglen,1221 .get_regs = enetc_get_regs,1222 .get_sset_count = enetc_get_sset_count,1223 .get_strings = enetc_get_strings,1224 .get_ethtool_stats = enetc_get_ethtool_stats,1225 .get_rxnfc = enetc_get_rxnfc,1226 .set_rxnfc = enetc_set_rxnfc,1227 .get_rxfh_indir_size = enetc_get_rxfh_indir_size,1228 .get_rxfh = enetc_get_rxfh,1229 .set_rxfh = enetc_set_rxfh,1230 .get_ringparam = enetc_get_ringparam,1231 .get_coalesce = enetc_get_coalesce,1232 .set_coalesce = enetc_set_coalesce,1233 .get_link = ethtool_op_get_link,1234 .get_ts_info = enetc_get_ts_info,1235};1236 1237void enetc_set_ethtool_ops(struct net_device *ndev)1238{1239 struct enetc_ndev_priv *priv = netdev_priv(ndev);1240 1241 if (enetc_si_is_pf(priv->si))1242 ndev->ethtool_ops = &enetc_pf_ethtool_ops;1243 else1244 ndev->ethtool_ops = &enetc_vf_ethtool_ops;1245}1246EXPORT_SYMBOL_GPL(enetc_set_ethtool_ops);1247